/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "jit/ShapeList.h" #include "gc/GC.h" #include "vm/List-inl.h" using namespace js; using namespace js::jit; const JSClass ShapeListObject::class_ = { "JIT ShapeList", 0, &classOps_, }; const JSClassOps ShapeListObject::classOps_ = { nullptr, // addProperty nullptr, // delProperty nullptr, // enumerate nullptr, // newEnumerate nullptr, // resolve nullptr, // mayResolve nullptr, // finalize nullptr, // call nullptr, // construct ShapeListObject::trace, // trace }; /* static */ ShapeListObject* ShapeListObject::create(JSContext* cx) { NativeObject* obj = NewTenuredObjectWithGivenProto(cx, &class_, nullptr); if (!obj) { return nullptr; } // Register this object so the GC can sweep its weak pointers. if (!cx->zone()->registerObjectWithWeakPointers(obj)) { ReportOutOfMemory(cx); return nullptr; } return &obj->as(); } Shape* ShapeListObject::get(uint32_t index) const { Shape* shape = getUnbarriered(index); gc::ReadBarrier(shape); return shape; } Shape* ShapeListObject::getUnbarriered(uint32_t index) const { Value value = ListObject::get(index); return static_cast(value.toPrivate()); } void ShapeListObject::trace(JSTracer* trc, JSObject* obj) { if (trc->traceWeakEdges()) { obj->as().traceWeak(trc); } } bool ShapeListObject::traceWeak(JSTracer* trc) { uint32_t length = getDenseInitializedLength(); if (length == 0) { return false; // Object may be uninitialized. } const HeapSlot* src = elements_; const HeapSlot* end = src + length; HeapSlot* dst = elements_; while (src != end) { Shape* shape = static_cast(src->toPrivate()); MOZ_ASSERT(shape->is()); if (TraceManuallyBarrieredWeakEdge(trc, &shape, "ShapeListObject shape")) { dst->unbarrieredSet(PrivateValue(shape)); dst++; } src++; } MOZ_ASSERT(dst <= end); uint32_t newLength = dst - elements_; setDenseInitializedLength(newLength); if (length != newLength) { JitSpew(JitSpew_StubFolding, "Cleared %u/%u shapes from %p", length - newLength, length, this); } return length != 0; } const JSClass ShapeListWithOffsetsObject::class_ = { "JIT ShapeList", 0, &classOps_, }; const JSClassOps ShapeListWithOffsetsObject::classOps_ = { nullptr, // addProperty nullptr, // delProperty nullptr, // enumerate nullptr, // newEnumerate nullptr, // resolve nullptr, // mayResolve nullptr, // finalize nullptr, // call nullptr, // construct ShapeListWithOffsetsObject::trace, // trace }; /* static */ ShapeListWithOffsetsObject* ShapeListWithOffsetsObject::create( JSContext* cx) { NativeObject* obj = NewTenuredObjectWithGivenProto(cx, &class_, nullptr); if (!obj) { return nullptr; } // Register this object so the GC can sweep its weak pointers. if (!cx->zone()->registerObjectWithWeakPointers(obj)) { ReportOutOfMemory(cx); return nullptr; } return &obj->as(); } Shape* ShapeListWithOffsetsObject::getShape(uint32_t index) const { Shape* shape = getShapeUnbarriered(index); gc::ReadBarrier(shape); return shape; } Shape* ShapeListWithOffsetsObject::getShapeUnbarriered(uint32_t index) const { Value value = ListObject::get(index * 2); return static_cast(value.toPrivate()); } uint32_t ShapeListWithOffsetsObject::getOffset(uint32_t index) const { Value value = ListObject::get(index * 2 + 1); return value.toPrivateUint32(); } uint32_t ShapeListWithOffsetsObject::numShapes() const { MOZ_ASSERT(length() % 2 == 0); return length() / 2; }; void ShapeListWithOffsetsObject::trace(JSTracer* trc, JSObject* obj) { if (trc->traceWeakEdges()) { obj->as().traceWeak(trc); } } bool ShapeListWithOffsetsObject::traceWeak(JSTracer* trc) { uint32_t length = getDenseInitializedLength(); if (length == 0) { return false; // Object may be uninitialized. } const HeapSlot* src = elements_; const HeapSlot* end = src + length; HeapSlot* dst = elements_; while (src != end) { Shape* shape = static_cast(src[0].toPrivate()); uint32_t offset = src[1].toPrivateUint32(); MOZ_ASSERT(shape->is()); if (TraceManuallyBarrieredWeakEdge(trc, &shape, "ShapeListWithOffsetsObject shape")) { dst[0].unbarrieredSet(PrivateValue(shape)); dst[1].unbarrieredSet(PrivateUint32Value(offset)); dst += 2; } src += 2; } MOZ_ASSERT(dst <= end); uint32_t newLength = dst - elements_; setDenseInitializedLength(newLength); if (length != newLength) { JitSpew(JitSpew_StubFolding, "Cleared %u/%u shapes from %p", (length - newLength) / 2, (length) / 2, this); } return length != 0; }