Don't add code dependencies on transitioning stores eagerly.
authorbmeurer@chromium.org <bmeurer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 2 May 2014 06:37:54 +0000 (06:37 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 2 May 2014 06:37:54 +0000 (06:37 +0000)
R=mvstanton@chromium.org

Review URL: https://codereview.chromium.org/256303007

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

21 files changed:
src/arm/lithium-arm.cc
src/arm/lithium-arm.h
src/arm/lithium-codegen-arm.cc
src/arm64/lithium-arm64.cc
src/arm64/lithium-arm64.h
src/arm64/lithium-codegen-arm64.cc
src/handles.h
src/hydrogen-instructions.h
src/hydrogen.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-ia32.cc
src/ia32/lithium-ia32.h
src/lithium.cc
src/lithium.h
src/mips/lithium-codegen-mips.cc
src/mips/lithium-mips.cc
src/mips/lithium-mips.h
src/objects.h
src/x64/lithium-codegen-x64.cc
src/x64/lithium-x64.cc
src/x64/lithium-x64.h

index 5b2a5f5ec1048b662522ba584aa637f3f969162a..0ed3ddb8a414f8332dd13400a42810f8a882c4b4 100644 (file)
@@ -429,6 +429,12 @@ void LChunkBuilder::Abort(BailoutReason reason) {
 }
 
 
+void LChunkBuilder::AddDeprecationDependency(Handle<Map> map) {
+  if (map->is_deprecated()) return Abort(kMapBecameDeprecated);
+  chunk_->AddDeprecationDependency(map);
+}
+
+
 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
   return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
                                   Register::ToAllocationIndex(reg));
@@ -2300,6 +2306,11 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
   // We need a temporary register for write barrier of the map field.
   LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
 
+  // Add a deprecation dependency on the transition target map.
+  if (instr->has_transition()) {
+    AddDeprecationDependency(instr->transition_map());
+  }
+
   LInstruction* result = new(zone()) LStoreNamedField(obj, val, temp);
   if (!instr->access().IsExternalMemory() &&
       instr->field_representation().IsHeapObject() &&
index c22d79f7f8d0e78cfd4028289e66162ed13088b4..2c6f60937c93ce691f0adc5865a89431adf55ebf 100644 (file)
@@ -2748,6 +2748,9 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase {
 
   void Abort(BailoutReason reason);
 
+  // Methods for code dependencies.
+  void AddDeprecationDependency(Handle<Map> map);
+
   // Methods for getting operands for Use / Define / Temp.
   LUnallocated* ToUnallocated(Register reg);
   LUnallocated* ToUnallocated(DoubleRegister reg);
index 7ddbaa9ade99feefe6da5765a4db82ae98dc0802..8d4a7b4b6e4a5c145b615285df53cf5e51543d61 100644 (file)
@@ -63,7 +63,6 @@ void LCodeGen::FinishCode(Handle<Code> code) {
   code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
   if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code);
   PopulateDeoptimizationData(code);
-  info()->CommitDependencies(code);
 }
 
 
index a2c3a3212073a47118dee65cf5367a540857298c..03fee2a537c1bd9b4fd92f0195053cf20191dd23 100644 (file)
@@ -360,6 +360,12 @@ void LChunkBuilder::Abort(BailoutReason reason) {
 }
 
 
+void LChunkBuilder::AddDeprecationDependency(Handle<Map> map) {
+  if (map->is_deprecated()) return Abort(kMapBecameDeprecated);
+  chunk_->AddDeprecationDependency(map);
+}
+
+
 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
   return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
                                   Register::ToAllocationIndex(reg));
@@ -2250,6 +2256,11 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
     temp0 = TempRegister();
   }
 
+  // Add a deprecation dependency on the transition target map.
+  if (instr->has_transition()) {
+    AddDeprecationDependency(instr->transition_map());
+  }
+
   LStoreNamedField* result =
       new(zone()) LStoreNamedField(object, value, temp0, temp1);
   if (instr->field_representation().IsHeapObject() &&
index e60dc0509aa21816a6f3f64ea464490c826bc52f..9422f9e306329010be36207d71bea3a1d203c60e 100644 (file)
@@ -2999,6 +2999,9 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase {
 
   void Abort(BailoutReason reason);
 
+  // Methods for code dependencies.
+  void AddDeprecationDependency(Handle<Map> map);
+
   // Methods for getting operands for Use / Define / Temp.
   LUnallocated* ToUnallocated(Register reg);
   LUnallocated* ToUnallocated(DoubleRegister reg);
index 1860e6344abfd20e1f4f1797d912a4d64100723c..46fefc8c789072b06d0767f04ab93afeb3f01834 100644 (file)
@@ -892,7 +892,6 @@ void LCodeGen::FinishCode(Handle<Code> code) {
   code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
   if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code);
   PopulateDeoptimizationData(code);
-  info()->CommitDependencies(code);
 }
 
 
index 017bfee3d02fe0ecfdf3afdf30e55bf91f80d8c2..5dc4a5ddda2c42be14287f69c58a135540dbebad 100644 (file)
@@ -155,6 +155,13 @@ inline Handle<T> handle(T* t) {
 }
 
 
+// Key comparison function for Map handles.
+inline bool operator<(const Handle<Map>& lhs, const Handle<Map>& rhs) {
+  // This is safe because maps don't move.
+  return *lhs < *rhs;
+}
+
+
 class DeferredHandles;
 class HandleScopeImplementer;
 
index c69a94188e82ac541b1f80bdca312a92d485985b..c38b2485bd006ed813f3a4d3797cbcfd734e51de 100644 (file)
@@ -6611,14 +6611,9 @@ class HStoreNamedField V8_FINAL : public HTemplateInstruction<3> {
     }
   }
 
-  void SetTransition(HConstant* map_constant, CompilationInfo* info) {
+  void SetTransition(HConstant* transition) {
     ASSERT(!has_transition());  // Only set once.
-    Handle<Map> map = Handle<Map>::cast(map_constant->handle(info->isolate()));
-    if (map->CanBeDeprecated()) {
-      Map::AddDependentCompilationInfo(
-          map, DependentCode::kTransitionGroup, info);
-    }
-    SetOperandAt(2, map_constant);
+    SetOperandAt(2, transition);
     has_transition_ = true;
   }
 
index 7ea9e930f16a286460a0e88c2d99b6b09824f2ed..da9b2133cce04ce4d8b72f0a9588f2028a8ebdad 100644 (file)
@@ -5420,9 +5420,9 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
   }
 
   if (transition_to_field) {
-    HConstant* transition_constant = Add<HConstant>(info->transition());
-    instr->SetTransition(transition_constant, top_info());
-    instr->SetChangesFlag(kMaps);
+    Handle<Map> transition(info->transition());
+    ASSERT(!transition->is_deprecated());
+    instr->SetTransition(Add<HConstant>(transition));
   }
   return instr;
 }
index e1dce514e3768e4425d1714dae66d58ef2801e7a..63925aa501a7984f81d778536c1554dda55bee94 100644 (file)
@@ -86,7 +86,6 @@ void LCodeGen::FinishCode(Handle<Code> code) {
   if (!info()->IsStub()) {
     Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
   }
-  info()->CommitDependencies(code);
 }
 
 
@@ -4344,7 +4343,7 @@ void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
 
 
 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
-  Representation representation = instr->representation();
+  Representation representation = instr->hydrogen()->field_representation();
 
   HObjectAccess access = instr->hydrogen()->access();
   int offset = access.offset();
@@ -4366,7 +4365,6 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
   }
 
   Register object = ToRegister(instr->object());
-  Handle<Map> transition = instr->transition();
   SmiCheck check_needed =
       instr->hydrogen()->value()->IsHeapObject()
           ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
@@ -4391,8 +4389,8 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
       }
     }
   } else if (representation.IsDouble()) {
-    ASSERT(transition.is_null());
     ASSERT(access.IsInobject());
+    ASSERT(!instr->hydrogen()->has_transition());
     ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
     if (CpuFeatures::IsSupported(SSE2)) {
       CpuFeatureScope scope(masm(), SSE2);
@@ -4405,7 +4403,8 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
     return;
   }
 
-  if (!transition.is_null()) {
+  if (instr->hydrogen()->has_transition()) {
+    Handle<Map> transition = instr->hydrogen()->transition_map();
     if (!instr->hydrogen()->NeedsWriteBarrierForMap()) {
       __ mov(FieldOperand(object, HeapObject::kMapOffset), transition);
     } else {
index e81ae935993a370dc2eab3bf2fa38ce3dc609956..a77121608154091312d0287467b0c322666ca7ae 100644 (file)
@@ -478,6 +478,12 @@ void LChunkBuilder::Abort(BailoutReason reason) {
 }
 
 
+void LChunkBuilder::AddDeprecationDependency(Handle<Map> map) {
+  if (map->is_deprecated()) return Abort(kMapBecameDeprecated);
+  chunk_->AddDeprecationDependency(map);
+}
+
+
 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
   return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
                                   Register::ToAllocationIndex(reg));
@@ -2422,6 +2428,11 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
   // We need a temporary register for write barrier of the map field.
   LOperand* temp_map = needs_write_barrier_for_map ? TempRegister() : NULL;
 
+  // Add a deprecation dependency on the transition target map.
+  if (instr->has_transition()) {
+    AddDeprecationDependency(instr->transition_map());
+  }
+
   LInstruction* result =
       new(zone()) LStoreNamedField(obj, val, temp, temp_map);
   if (!instr->access().IsExternalMemory() &&
index df718c7330e5cffb392aa65662be4428bae48f96..54e3bd26cd36350990b9a5f1617402207dab3a16 100644 (file)
@@ -2191,11 +2191,6 @@ class LStoreNamedField V8_FINAL : public LTemplateInstruction<0, 2, 2> {
   DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
 
   virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
-
-  Handle<Map> transition() const { return hydrogen()->transition_map(); }
-  Representation representation() const {
-    return hydrogen()->field_representation();
-  }
 };
 
 
@@ -2780,6 +2775,9 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase {
 
   void Abort(BailoutReason reason);
 
+  // Methods for code dependencies.
+  void AddDeprecationDependency(Handle<Map> map);
+
   // Methods for getting operands for Use / Define / Temp.
   LUnallocated* ToUnallocated(Register reg);
   LUnallocated* ToUnallocated(XMMRegister reg);
index f23503afdd3ff37cde5c4a0901bb1b7d71a12a3d..ecb5a5863563f84f14b3037e6a214617b7bea9ea 100644 (file)
@@ -233,7 +233,8 @@ LChunk::LChunk(CompilationInfo* info, HGraph* graph)
       graph_(graph),
       instructions_(32, graph->zone()),
       pointer_maps_(8, graph->zone()),
-      inlined_closures_(1, graph->zone()) {
+      inlined_closures_(1, graph->zone()),
+      deprecation_dependencies_(MapLess(), MapAllocator(graph->zone())) {
 }
 
 
@@ -372,6 +373,19 @@ Representation LChunk::LookupLiteralRepresentation(
 }
 
 
+void LChunk::CommitDependencies(Handle<Code> code) const {
+  for (MapSet::const_iterator it = deprecation_dependencies_.begin(),
+       iend = deprecation_dependencies_.end(); it != iend; ++it) {
+    Handle<Map> map = *it;
+    ASSERT(!map->is_deprecated());
+    ASSERT(map->CanBeDeprecated());
+    Map::AddDependentCode(map, DependentCode::kTransitionGroup, code);
+  }
+
+  info_->CommitDependencies(code);
+}
+
+
 LChunk* LChunk::NewChunk(HGraph* graph) {
   DisallowHandleAllocation no_handles;
   DisallowHeapAllocation no_gc;
@@ -415,6 +429,7 @@ Handle<Code> LChunk::Codegen() {
     Handle<Code> code =
         CodeGenerator::MakeCodeEpilogue(&assembler, flags, info());
     generator.FinishCode(code);
+    CommitDependencies(code);
     code->set_is_crankshafted(true);
     void* jit_handler_data =
         assembler.positions_recorder()->DetachJITHandlerData();
index 5b65045762872756930c534cbd6f7f9e64b880b9..050b3e5498dac0813c3a79a9e1848dea394e6ec1 100644 (file)
@@ -5,9 +5,12 @@
 #ifndef V8_LITHIUM_H_
 #define V8_LITHIUM_H_
 
+#include <set>
+
 #include "allocation.h"
 #include "hydrogen.h"
 #include "safepoint-table.h"
+#include "zone-allocator.h"
 
 namespace v8 {
 namespace internal {
@@ -642,6 +645,13 @@ class LChunk : public ZoneObject {
     inlined_closures_.Add(closure, zone());
   }
 
+  void AddDeprecationDependency(Handle<Map> map) {
+    ASSERT(!map->is_deprecated());
+    if (!map->CanBeDeprecated()) return;
+    ASSERT(!info_->IsStub());
+    deprecation_dependencies_.insert(map);
+  }
+
   Zone* zone() const { return info_->zone(); }
 
   Handle<Code> Codegen();
@@ -657,12 +667,19 @@ class LChunk : public ZoneObject {
   int spill_slot_count_;
 
  private:
+  typedef std::less<Handle<Map> > MapLess;
+  typedef zone_allocator<Handle<Map> > MapAllocator;
+  typedef std::set<Handle<Map>, MapLess, MapAllocator> MapSet;
+
+  void CommitDependencies(Handle<Code> code) const;
+
   CompilationInfo* info_;
   HGraph* const graph_;
   BitVector* allocated_double_registers_;
   ZoneList<LInstruction*> instructions_;
   ZoneList<LPointerMap*> pointer_maps_;
   ZoneList<Handle<JSFunction> > inlined_closures_;
+  MapSet deprecation_dependencies_;
 };
 
 
index d41f019a7a5a757107680f35fca71a9def67d726..90247fe57c9c39b5693a2591f6e126a15bb96e6c 100644 (file)
@@ -86,7 +86,6 @@ void LCodeGen::FinishCode(Handle<Code> code) {
   code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
   if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code);
   PopulateDeoptimizationData(code);
-  info()->CommitDependencies(code);
 }
 
 
index 0c85f8b89328af93d2d297be895749cf09468bee..6243f43bb565315a39ba34690746421ca8be1eaa 100644 (file)
@@ -434,6 +434,12 @@ void LCodeGen::Abort(BailoutReason reason) {
 }
 
 
+void LChunkBuilder::AddDeprecationDependency(Handle<Map> map) {
+  if (map->is_deprecated()) return Abort(kMapBecameDeprecated);
+  chunk_->AddDeprecationDependency(map);
+}
+
+
 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
   return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
                                   Register::ToAllocationIndex(reg));
@@ -2251,6 +2257,11 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
   // We need a temporary register for write barrier of the map field.
   LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
 
+  // Add a deprecation dependency on the transition target map.
+  if (instr->has_transition()) {
+    AddDeprecationDependency(instr->transition_map());
+  }
+
   LInstruction* result = new(zone()) LStoreNamedField(obj, val, temp);
   if (!instr->access().IsExternalMemory() &&
       instr->field_representation().IsHeapObject() &&
index 7a0e359e2d68842407a40f167b31c0c8c713e5cf..479fa895bdfee7a4d3030373f1029f67bf9a05f7 100644 (file)
@@ -2703,6 +2703,9 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase {
 
   void Abort(BailoutReason reason);
 
+  // Methods for code dependencies.
+  void AddDeprecationDependency(Handle<Map> map);
+
   // Methods for getting operands for Use / Define / Temp.
   LUnallocated* ToUnallocated(Register reg);
   LUnallocated* ToUnallocated(DoubleRegister reg);
index 4ea399e1bbd4d4657eaf316e64e13fca6ddc9fa1..9fff61d8aaa44eb80b7b38bdb6f46a88e494fd8d 100644 (file)
@@ -1156,6 +1156,7 @@ template <class C> inline bool Is(Object* obj);
   V(kLiveEdit, "LiveEdit")                                                    \
   V(kLookupVariableInCountOperation,                                          \
     "Lookup variable in count operation")                                     \
+  V(kMapBecameDeprecated, "Map became deprecated")                            \
   V(kMapIsNoLongerInEax, "Map is no longer in eax")                           \
   V(kModuleDeclaration, "Module declaration")                                 \
   V(kModuleLiteral, "Module literal")                                         \
index 421aba8d4245639a17f8e20f6f447904a25e0185..19915425cf8b6808b59d7007bc5f42ed1ac839a0 100644 (file)
@@ -66,7 +66,6 @@ void LCodeGen::FinishCode(Handle<Code> code) {
   code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
   if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code);
   PopulateDeoptimizationData(code);
-  info()->CommitDependencies(code);
 }
 
 
index f0aac8495d25e9622ac235a8ad03df4c83904194..d7ddb9ea0145e1e49b14c11da76cec312bb5e5c3 100644 (file)
@@ -445,6 +445,12 @@ void LCodeGen::Abort(BailoutReason reason) {
 }
 
 
+void LChunkBuilder::AddDeprecationDependency(Handle<Map> map) {
+  if (map->is_deprecated()) return Abort(kMapBecameDeprecated);
+  chunk_->AddDeprecationDependency(map);
+}
+
+
 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
   return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
                                   Register::ToAllocationIndex(reg));
@@ -2314,6 +2320,11 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
   LOperand* temp = (!is_in_object || needs_write_barrier ||
       needs_write_barrier_for_map) ? TempRegister() : NULL;
 
+  // Add a deprecation dependency on the transition target map.
+  if (instr->has_transition()) {
+    AddDeprecationDependency(instr->transition_map());
+  }
+
   LInstruction* result = new(zone()) LStoreNamedField(obj, val, temp);
   if (!instr->access().IsExternalMemory() &&
       instr->field_representation().IsHeapObject() &&
index ad8413818b11d94289ac997fbc8feb5059747cfd..6d460c67f70667514bd256c0550a7ff667ad9805 100644 (file)
@@ -2710,6 +2710,9 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase {
 
   void Abort(BailoutReason reason);
 
+  // Methods for code dependencies.
+  void AddDeprecationDependency(Handle<Map> map);
+
   // Methods for getting operands for Use / Define / Temp.
   LUnallocated* ToUnallocated(Register reg);
   LUnallocated* ToUnallocated(XMMRegister reg);