size_t ForkJoinNursery::copyObjectToTospace(JSObject *dst, JSObject *src, AllocKind dstKind) { size_t srcSize = Arena::thingSize(dstKind); size_t movedSize = srcSize; // Arrays do not necessarily have the same AllocKind between src and dst. // We deal with this by copying elements manually, possibly re-inlining // them if there is adequate room inline in dst. if (src->is<ArrayObject>()) srcSize = movedSize = sizeof(ObjectImpl); js_memcpy(dst, src, srcSize); movedSize += copySlotsToTospace(dst, src, dstKind); movedSize += copyElementsToTospace(dst, src, dstKind); if (src->is<TypedArrayObject>()) dst->setPrivate(dst->fixedData(TypedArrayObject::FIXED_DATA_START)); // The shape's list head may point into the old object. if (&src->shape_ == dst->shape_->listp) { JS_ASSERT(cx_->isThreadLocal(dst->shape_.get())); dst->shape_->listp = &dst->shape_; } return movedSize; }
HeapSlot * ForkJoinNursery::reallocateSlots(JSObject *obj, HeapSlot *oldSlots, uint32_t oldCount, uint32_t newCount) { if (newCount & mozilla::tl::MulOverflowMask<sizeof(HeapSlot)>::value) return nullptr; size_t oldSize = oldCount * sizeof(HeapSlot); size_t newSize = newCount * sizeof(HeapSlot); if (!isInsideNewspace(obj)) { JS_ASSERT_IF(oldSlots, !isInsideNewspace(oldSlots)); return static_cast<HeapSlot *>(cx_->realloc_(oldSlots, oldSize, newSize)); } if (!isInsideNewspace(oldSlots)) return reallocateHugeSlots(oldSlots, oldSize, newSize); // No-op if we're shrinking, we can't make use of the freed portion. if (newCount < oldCount) return oldSlots; HeapSlot *newSlots = allocateSlots(obj, newCount); if (!newSlots) return nullptr; js_memcpy(newSlots, oldSlots, oldSize); return newSlots; }
void Ring::copyBytes(void *data, size_t size) { if (size >= bufferSize()) size = bufferSize(); if (offset + size > bufferSize()) { size_t first = bufferSize() - offset; size_t second = size - first; js_memcpy(&buffer[offset], data, first); js_memcpy(buffer, (char *)data + first, second); offset = second; } else { js_memcpy(&buffer[offset], data, size); offset += size; } }
size_t ForkJoinNursery::copyElementsToTospace(JSObject *dst, JSObject *src, AllocKind dstKind) { if (src->hasEmptyElements()) return 0; ObjectElements *srcHeader = src->getElementsHeader(); ObjectElements *dstHeader; // TODO Bug 874151: Prefer to put element data inline if we have space. // (Note, not a correctness issue.) if (!isInsideFromspace(srcHeader)) { JS_ASSERT(src->elements == dst->elements); hugeSlots[hugeSlotsFrom].remove(reinterpret_cast<HeapSlot*>(srcHeader)); if (!isEvacuating_) hugeSlots[hugeSlotsNew].put(reinterpret_cast<HeapSlot*>(srcHeader)); return 0; } size_t nslots = ObjectElements::VALUES_PER_HEADER + srcHeader->capacity; // Unlike other objects, Arrays can have fixed elements. if (src->is<ArrayObject>() && nslots <= GetGCKindSlots(dstKind)) { dst->setFixedElements(); dstHeader = dst->getElementsHeader(); js_memcpy(dstHeader, srcHeader, nslots * sizeof(HeapSlot)); setElementsForwardingPointer(srcHeader, dstHeader, nslots); return nslots * sizeof(HeapSlot); } JS_ASSERT(nslots >= 2); dstHeader = reinterpret_cast<ObjectElements *>(allocateInTospace(nslots, sizeof(HeapSlot))); if (!dstHeader) CrashAtUnhandlableOOM("Failed to allocate elements while moving object."); js_memcpy(dstHeader, srcHeader, nslots * sizeof(HeapSlot)); setElementsForwardingPointer(srcHeader, dstHeader, nslots); dst->elements = dstHeader->elements(); return nslots * sizeof(HeapSlot); }
size_t ForkJoinNursery::copySlotsToTospace(JSObject *dst, JSObject *src, AllocKind dstKind) { // Fixed slots have already been copied over. if (!src->hasDynamicSlots()) return 0; if (!isInsideFromspace(src->slots)) { hugeSlots[hugeSlotsFrom].remove(src->slots); if (!isEvacuating_) hugeSlots[hugeSlotsNew].put(src->slots); return 0; } size_t count = src->numDynamicSlots(); dst->slots = reinterpret_cast<HeapSlot *>(allocateInTospace(count, sizeof(HeapSlot))); if (!dst->slots) CrashAtUnhandlableOOM("Failed to allocate slots while moving object."); js_memcpy(dst->slots, src->slots, count * sizeof(HeapSlot)); setSlotsForwardingPointer(src->slots, dst->slots, count); return count * sizeof(HeapSlot); }