Author: [EMAIL PROTECTED]
Date: Wed Oct 22 01:21:18 2008
New Revision: 548

Modified:
    branches/bleeding_edge/src/codegen-arm.cc
    branches/bleeding_edge/src/codegen-ia32.cc
    branches/bleeding_edge/src/handles.cc
    branches/bleeding_edge/src/handles.h
    branches/bleeding_edge/src/heap-inl.h
    branches/bleeding_edge/src/heap.cc
    branches/bleeding_edge/src/heap.h
    branches/bleeding_edge/src/objects-inl.h
    branches/bleeding_edge/src/objects.cc
    branches/bleeding_edge/src/objects.h
    branches/bleeding_edge/src/runtime.cc
    branches/bleeding_edge/src/spaces-inl.h
    branches/bleeding_edge/test/cctest/test-heap.cc

Log:
- Optimized CopyFixedArray and CopyJSObject.
- Refactored block copying.

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

Modified: branches/bleeding_edge/src/codegen-arm.cc
==============================================================================
--- branches/bleeding_edge/src/codegen-arm.cc   (original)
+++ branches/bleeding_edge/src/codegen-arm.cc   Wed Oct 22 01:21:18 2008
@@ -3909,7 +3909,7 @@

  #ifdef DEBUG
    if (FLAG_gc_greedy) {
-    Failure* failure = Failure::RetryAfterGC(0, NEW_SPACE);
+    Failure* failure = Failure::RetryAfterGC(0);
      __ mov(r0, Operand(reinterpret_cast<intptr_t>(failure)));
    }
    GenerateCore(masm,

Modified: branches/bleeding_edge/src/codegen-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/codegen-ia32.cc  (original)
+++ branches/bleeding_edge/src/codegen-ia32.cc  Wed Oct 22 01:21:18 2008
@@ -4937,7 +4937,7 @@

  #ifdef DEBUG
    if (FLAG_gc_greedy) {
-    Failure* failure = Failure::RetryAfterGC(0, NEW_SPACE);
+    Failure* failure = Failure::RetryAfterGC(0);
      __ mov(Operand(eax), Immediate(reinterpret_cast<int32_t>(failure)));
    }
    GenerateCore(masm, &throw_normal_exception,

Modified: branches/bleeding_edge/src/handles.cc
==============================================================================
--- branches/bleeding_edge/src/handles.cc       (original)
+++ branches/bleeding_edge/src/handles.cc       Wed Oct 22 01:21:18 2008
@@ -237,8 +237,8 @@
  }


-Handle<JSObject> Copy(Handle<JSObject> obj, PretenureFlag pretenure) {
-  CALL_HEAP_FUNCTION(obj->Copy(pretenure), JSObject);
+Handle<JSObject> Copy(Handle<JSObject> obj) {
+  CALL_HEAP_FUNCTION(Heap::CopyJSObject(*obj), JSObject);
  }



Modified: branches/bleeding_edge/src/handles.h
==============================================================================
--- branches/bleeding_edge/src/handles.h        (original)
+++ branches/bleeding_edge/src/handles.h        Wed Oct 22 01:21:18 2008
@@ -144,7 +144,7 @@

  Handle<Object> LookupSingleCharacterStringFromCode(uint32_t index);

-Handle<JSObject> Copy(Handle<JSObject> obj, PretenureFlag = NOT_TENURED);
+Handle<JSObject> Copy(Handle<JSObject> obj);

  // Get the JS object corresponding to the given script; create it
  // if none exists.

Modified: branches/bleeding_edge/src/heap-inl.h
==============================================================================
--- branches/bleeding_edge/src/heap-inl.h       (original)
+++ branches/bleeding_edge/src/heap-inl.h       Wed Oct 22 01:21:18 2008
@@ -146,6 +146,25 @@
  }


+void Heap::CopyBlock(Object** dst, Object** src, int byte_size) {
+  ASSERT(IsAligned(byte_size, kPointerSize));
+
+  // Use block copying memcpy if the segment we're copying is
+  // enough to justify the extra call/setup overhead.
+  static const int kBlockCopyLimit = 16 * kPointerSize;
+
+  if (byte_size >= kBlockCopyLimit) {
+    memcpy(dst, src, byte_size);
+  } else {
+    int remaining = byte_size / kPointerSize;
+    do {
+      remaining--;
+      *dst++ = *src++;
+    } while (remaining > 0);
+  }
+}
+
+
  #define GC_GREEDY_CHECK() \
    ASSERT(!FLAG_gc_greedy ||  
v8::internal::Heap::GarbageCollectionGreedyCheck())


Modified: branches/bleeding_edge/src/heap.cc
==============================================================================
--- branches/bleeding_edge/src/heap.cc  (original)
+++ branches/bleeding_edge/src/heap.cc  Wed Oct 22 01:21:18 2008
@@ -726,25 +726,14 @@
  #endif  // defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)


+
  HeapObject* Heap::MigrateObject(HeapObject* source,
                                  HeapObject* target,
                                  int size) {
-  void** src = reinterpret_cast<void**>(source->address());
-  void** dst = reinterpret_cast<void**>(target->address());
-
-  // Use block copying memcpy if the object we're migrating is big
-  // enough to justify the extra call/setup overhead.
-  static const int kBlockCopyLimit = 16 * kPointerSize;
-
-  if (size >= kBlockCopyLimit) {
-    memcpy(dst, src, size);
-  } else {
-    int remaining = size / kPointerSize;
-    do {
-      remaining--;
-      *dst++ = *src++;
-    } while (remaining > 0);
-  }
+  // Copy the content of source to target.
+  CopyBlock(reinterpret_cast<Object**>(target->address()),
+            reinterpret_cast<Object**>(source->address()),
+            size);

    // Set the forwarding address.
    source->set_map_word(MapWord::FromForwardingAddress(target));
@@ -1589,8 +1578,9 @@
    // Copy code object.
    Address old_addr = code->address();
    Address new_addr = reinterpret_cast<HeapObject*>(result)->address();
-  memcpy(new_addr, old_addr, obj_size);
-
+  CopyBlock(reinterpret_cast<Object**>(new_addr),
+            reinterpret_cast<Object**>(old_addr),
+            obj_size);
    // Relocate the copy.
    Code* new_code = Code::cast(result);
    new_code->Relocate(new_addr - old_addr);
@@ -1657,7 +1647,7 @@

    JSObject* boilerplate =
        Top::context()->global_context()->arguments_boilerplate();
-  Object* result = boilerplate->Copy();
+  Object* result = CopyJSObject(boilerplate);
    if (result->IsFailure()) return result;

    Object* obj = JSObject::cast(result)->properties();
@@ -1764,6 +1754,42 @@
  }


+Object* Heap::CopyJSObject(JSObject* source) {
+  // Never used to copy functions.  If functions need to be copied we
+  // have to be careful to clear the literals array.
+  ASSERT(!source->IsJSFunction());
+
+  // Make the clone.
+  Map* map = source->map();
+  int object_size = map->instance_size();
+  Object* clone = new_space_.AllocateRaw(object_size);
+  if (clone->IsFailure()) return clone;
+  ASSERT(Heap::InNewSpace(clone));
+
+  // Copy the content.
+  CopyBlock(reinterpret_cast<Object**>(HeapObject::cast(clone)->address()),
+            reinterpret_cast<Object**>(source->address()),
+            object_size);
+
+  FixedArray* elements = FixedArray::cast(source->elements());
+  FixedArray* properties = FixedArray::cast(source->properties());
+  // Update elements if necessary.
+  if (elements->length()> 0) {
+    Object* elem = Heap::CopyFixedArray(elements);
+    if (elem->IsFailure()) return elem;
+    JSObject::cast(clone)->set_elements(FixedArray::cast(elem));
+  }
+  // Update properties if necessary.
+  if (properties->length() > 0) {
+    Object* prop = Heap::CopyFixedArray(properties);
+    if (prop->IsFailure()) return prop;
+    JSObject::cast(clone)->set_properties(FixedArray::cast(prop));
+  }
+  // Return the new clone.
+  return clone;
+}
+
+
  Object* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor,
                                          JSGlobalProxy* object) {
    // Allocate initial map if absent.
@@ -2064,14 +2090,20 @@

  Object* Heap::CopyFixedArray(FixedArray* src) {
    int len = src->length();
-  Object* obj = Heap::AllocateRawFixedArray(len);
+  Object* obj = AllocateRawFixedArray(len);
    if (obj->IsFailure()) return obj;
+  if (Heap::InNewSpace(obj)) {
+    HeapObject* dst = HeapObject::cast(obj);
+    CopyBlock(reinterpret_cast<Object**>(dst->address()),
+              reinterpret_cast<Object**>(src->address()),
+              FixedArray::SizeFor(len));
+    return obj;
+  }
    HeapObject::cast(obj)->set_map(src->map());
    FixedArray* result = FixedArray::cast(obj);
    result->set_length(len);
-  FixedArray::WriteBarrierMode mode = result->GetWriteBarrierMode();
    // Copy the content
-  for (int i = 0; i < len; i++) result->set(i, src->get(i), mode);
+  for (int i = 0; i < len; i++) result->set(i, src->get(i));
    return result;
  }


Modified: branches/bleeding_edge/src/heap.h
==============================================================================
--- branches/bleeding_edge/src/heap.h   (original)
+++ branches/bleeding_edge/src/heap.h   Wed Oct 22 01:21:18 2008
@@ -274,6 +274,11 @@
    static Object* AllocateJSObject(JSFunction* constructor,
                                    PretenureFlag pretenure = NOT_TENURED);

+  // Returns a deep copy of the JavaScript object.
+  // Properties and elements are copied too.
+  // Returns failure if allocation failed.
+  static Object* CopyJSObject(JSObject* source);
+
    // Allocates the function prototype.
    // Returns Failure::RetryAfterGC(requested_bytes, space) if the  
allocation
    // failed.
@@ -884,6 +889,9 @@

    // Slow part of scavenge object.
    static void ScavengeObjectSlow(HeapObject** p, HeapObject* object);
+
+  // Copy memory from src to dst.
+  inline static void CopyBlock(Object** dst, Object** src, int byte_size);

    static const int kInitialSymbolTableSize = 2048;
    static const int kInitialEvalCacheSize = 64;

Modified: branches/bleeding_edge/src/objects-inl.h
==============================================================================
--- branches/bleeding_edge/src/objects-inl.h    (original)
+++ branches/bleeding_edge/src/objects-inl.h    Wed Oct 22 01:21:18 2008
@@ -595,6 +595,17 @@
  }


+Failure* Failure::RetryAfterGC(int requested_bytes) {
+  int requested = requested_bytes >> kObjectAlignmentBits;
+  int value = (requested << kSpaceTagSize) | NEW_SPACE;
+  ASSERT(value >> kSpaceTagSize == requested);
+  ASSERT(Smi::IsValid(value));
+  ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
+  ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
+  return Construct(RETRY_AFTER_GC, value);
+}
+
+
  Failure* Failure::Construct(Type type, int value) {
    int info = (value << kFailureTypeTagSize) | type;
    ASSERT(Smi::IsValid(info));  // Same validation check as in Smi
@@ -791,21 +802,6 @@
  }


-void HeapObject::CopyBody(JSObject* from) {
-  ASSERT(map() == from->map());
-  ASSERT(Size() == from->Size());
-  int object_size = Size();
-  for (int offset = kHeaderSize;
-       offset < object_size;
-       offset += kPointerSize) {
-    Object* value = READ_FIELD(from, offset);
-    // Note: WRITE_FIELD does not update the write barrier.
-    WRITE_FIELD(this, offset, value);
-    WRITE_BARRIER(this, offset);
-  }
-}
-
-
  bool HeapObject::IsMarked() {
    return map_word().IsMarked();
  }
@@ -963,15 +959,17 @@


  void JSObject::InitializeBody(int object_size) {
+  Object* value = Heap::undefined_value();
    for (int offset = kHeaderSize; offset < object_size; offset +=  
kPointerSize) {
-    WRITE_FIELD(this, offset, Heap::undefined_value());
+    WRITE_FIELD(this, offset, value);
    }
  }


  void Struct::InitializeBody(int object_size) {
+  Object* value = Heap::undefined_value();
    for (int offset = kHeaderSize; offset < object_size; offset +=  
kPointerSize) {
-    WRITE_FIELD(this, offset, Heap::undefined_value());
+    WRITE_FIELD(this, offset, value);
    }
  }


Modified: branches/bleeding_edge/src/objects.cc
==============================================================================
--- branches/bleeding_edge/src/objects.cc       (original)
+++ branches/bleeding_edge/src/objects.cc       Wed Oct 22 01:21:18 2008
@@ -910,33 +910,6 @@
  }


-Object* JSObject::Copy(PretenureFlag pretenure) {
-  // Never used to copy functions.  If functions need to be copied we
-  // have to be careful to clear the literals array.
-  ASSERT(!IsJSFunction());
-
-  // Copy the elements and properties.
-  Object* elem = FixedArray::cast(elements())->Copy();
-  if (elem->IsFailure()) return elem;
-  Object* prop = properties()->Copy();
-  if (prop->IsFailure()) return prop;
-
-  // Make the clone.
-  Object* clone = (pretenure == NOT_TENURED) ?
-      Heap::Allocate(map(), NEW_SPACE) :
-      Heap::Allocate(map(), OLD_POINTER_SPACE);
-  if (clone->IsFailure()) return clone;
-  JSObject::cast(clone)->CopyBody(this);
-
-  // Set the new elements and properties.
-  JSObject::cast(clone)->set_elements(FixedArray::cast(elem));
-  JSObject::cast(clone)->set_properties(FixedArray::cast(prop));
-
-  // Return the new clone.
-  return clone;
-}
-
-
  Object* JSObject::AddFastPropertyUsingMap(Map* new_map,
                                            String* name,
                                            Object* value) {

Modified: branches/bleeding_edge/src/objects.h
==============================================================================
--- branches/bleeding_edge/src/objects.h        (original)
+++ branches/bleeding_edge/src/objects.h        Wed Oct 22 01:21:18 2008
@@ -812,6 +812,7 @@
    inline bool IsOutOfMemoryException() const;

    static Failure* RetryAfterGC(int requested_bytes, AllocationSpace space);
+  static inline Failure* RetryAfterGC(int requested_bytes);  // NEW_SPACE
    static inline Failure* Exception();
    static inline Failure* InternalError();
    static inline Failure* OutOfMemoryException();
@@ -996,10 +997,6 @@
    // of this struct.
    void IterateStructBody(int object_size, ObjectVisitor* v);

-  // Copy the body from the 'from' object to this.
-  // Please note the two object must have the same map prior to the call.
-  inline void CopyBody(JSObject* from);
-
    // Returns the heap object's size in bytes
    inline int Size();

@@ -1252,11 +1249,6 @@
    inline int GetInternalFieldCount();
    inline Object* GetInternalField(int index);
    inline void SetInternalField(int index, Object* value);
-
-  // Returns a deep copy of the JavaScript object.
-  // Properties and elements are copied too.
-  // Returns failure if allocation failed.
-  Object* Copy(PretenureFlag pretenure = NOT_TENURED);

    // Lookup a property.  If found, the result is valid and has
    // detailed information.

Modified: branches/bleeding_edge/src/runtime.cc
==============================================================================
--- branches/bleeding_edge/src/runtime.cc       (original)
+++ branches/bleeding_edge/src/runtime.cc       Wed Oct 22 01:21:18 2008
@@ -94,7 +94,7 @@

  static Object* Runtime_CloneObjectLiteralBoilerplate(Arguments args) {
    CONVERT_CHECKED(JSObject, boilerplate, args[0]);
-  return boilerplate->Copy();
+  return Heap::CopyJSObject(boilerplate);
  }



Modified: branches/bleeding_edge/src/spaces-inl.h
==============================================================================
--- branches/bleeding_edge/src/spaces-inl.h     (original)
+++ branches/bleeding_edge/src/spaces-inl.h     Wed Oct 22 01:21:18 2008
@@ -300,9 +300,7 @@
  Object* NewSpace::AllocateRawInternal(int size_in_bytes,
                                        AllocationInfo* alloc_info) {
    Address new_top = alloc_info->top + size_in_bytes;
-  if (new_top > alloc_info->limit) {
-    return Failure::RetryAfterGC(size_in_bytes, identity());
-  }
+  if (new_top > alloc_info->limit) return  
Failure::RetryAfterGC(size_in_bytes);

    Object* obj = HeapObject::FromAddress(alloc_info->top);
    alloc_info->top = new_top;

Modified: branches/bleeding_edge/test/cctest/test-heap.cc
==============================================================================
--- branches/bleeding_edge/test/cctest/test-heap.cc     (original)
+++ branches/bleeding_edge/test/cctest/test-heap.cc     Wed Oct 22 01:21:18 2008
@@ -664,7 +664,7 @@
    obj->SetElement(1, second);

    // Make the clone.
-  JSObject* clone = JSObject::cast(obj->Copy());
+  JSObject* clone = JSObject::cast(Heap::CopyJSObject(obj));
    CHECK(clone != obj);

    CHECK_EQ(obj->GetElement(0), clone->GetElement(0));

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to