ShapeList.cpp (5598B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "jit/ShapeList.h" 8 9 #include "gc/GC.h" 10 11 #include "vm/List-inl.h" 12 13 using namespace js; 14 using namespace js::jit; 15 16 const JSClass ShapeListObject::class_ = { 17 "JIT ShapeList", 18 0, 19 &classOps_, 20 }; 21 22 const JSClassOps ShapeListObject::classOps_ = { 23 nullptr, // addProperty 24 nullptr, // delProperty 25 nullptr, // enumerate 26 nullptr, // newEnumerate 27 nullptr, // resolve 28 nullptr, // mayResolve 29 nullptr, // finalize 30 nullptr, // call 31 nullptr, // construct 32 ShapeListObject::trace, // trace 33 }; 34 35 /* static */ ShapeListObject* ShapeListObject::create(JSContext* cx) { 36 NativeObject* obj = NewTenuredObjectWithGivenProto(cx, &class_, nullptr); 37 if (!obj) { 38 return nullptr; 39 } 40 41 // Register this object so the GC can sweep its weak pointers. 42 if (!cx->zone()->registerObjectWithWeakPointers(obj)) { 43 ReportOutOfMemory(cx); 44 return nullptr; 45 } 46 47 return &obj->as<ShapeListObject>(); 48 } 49 50 Shape* ShapeListObject::get(uint32_t index) const { 51 Shape* shape = getUnbarriered(index); 52 gc::ReadBarrier(shape); 53 return shape; 54 } 55 56 Shape* ShapeListObject::getUnbarriered(uint32_t index) const { 57 Value value = ListObject::get(index); 58 return static_cast<Shape*>(value.toPrivate()); 59 } 60 61 void ShapeListObject::trace(JSTracer* trc, JSObject* obj) { 62 if (trc->traceWeakEdges()) { 63 obj->as<ShapeListObject>().traceWeak(trc); 64 } 65 } 66 67 bool ShapeListObject::traceWeak(JSTracer* trc) { 68 uint32_t length = getDenseInitializedLength(); 69 if (length == 0) { 70 return false; // Object may be uninitialized. 71 } 72 73 const HeapSlot* src = elements_; 74 const HeapSlot* end = src + length; 75 HeapSlot* dst = elements_; 76 while (src != end) { 77 Shape* shape = static_cast<Shape*>(src->toPrivate()); 78 MOZ_ASSERT(shape->is<Shape>()); 79 if (TraceManuallyBarrieredWeakEdge(trc, &shape, "ShapeListObject shape")) { 80 dst->unbarrieredSet(PrivateValue(shape)); 81 dst++; 82 } 83 src++; 84 } 85 86 MOZ_ASSERT(dst <= end); 87 uint32_t newLength = dst - elements_; 88 setDenseInitializedLength(newLength); 89 90 if (length != newLength) { 91 JitSpew(JitSpew_StubFolding, "Cleared %u/%u shapes from %p", 92 length - newLength, length, this); 93 } 94 95 return length != 0; 96 } 97 98 const JSClass ShapeListWithOffsetsObject::class_ = { 99 "JIT ShapeList", 100 0, 101 &classOps_, 102 }; 103 104 const JSClassOps ShapeListWithOffsetsObject::classOps_ = { 105 nullptr, // addProperty 106 nullptr, // delProperty 107 nullptr, // enumerate 108 nullptr, // newEnumerate 109 nullptr, // resolve 110 nullptr, // mayResolve 111 nullptr, // finalize 112 nullptr, // call 113 nullptr, // construct 114 ShapeListWithOffsetsObject::trace, // trace 115 }; 116 117 /* static */ ShapeListWithOffsetsObject* ShapeListWithOffsetsObject::create( 118 JSContext* cx) { 119 NativeObject* obj = NewTenuredObjectWithGivenProto(cx, &class_, nullptr); 120 if (!obj) { 121 return nullptr; 122 } 123 124 // Register this object so the GC can sweep its weak pointers. 125 if (!cx->zone()->registerObjectWithWeakPointers(obj)) { 126 ReportOutOfMemory(cx); 127 return nullptr; 128 } 129 130 return &obj->as<ShapeListWithOffsetsObject>(); 131 } 132 133 Shape* ShapeListWithOffsetsObject::getShape(uint32_t index) const { 134 Shape* shape = getShapeUnbarriered(index); 135 gc::ReadBarrier(shape); 136 return shape; 137 } 138 139 Shape* ShapeListWithOffsetsObject::getShapeUnbarriered(uint32_t index) const { 140 Value value = ListObject::get(index * 2); 141 return static_cast<Shape*>(value.toPrivate()); 142 } 143 144 uint32_t ShapeListWithOffsetsObject::getOffset(uint32_t index) const { 145 Value value = ListObject::get(index * 2 + 1); 146 return value.toPrivateUint32(); 147 } 148 149 uint32_t ShapeListWithOffsetsObject::numShapes() const { 150 MOZ_ASSERT(length() % 2 == 0); 151 return length() / 2; 152 }; 153 154 void ShapeListWithOffsetsObject::trace(JSTracer* trc, JSObject* obj) { 155 if (trc->traceWeakEdges()) { 156 obj->as<ShapeListWithOffsetsObject>().traceWeak(trc); 157 } 158 } 159 160 bool ShapeListWithOffsetsObject::traceWeak(JSTracer* trc) { 161 uint32_t length = getDenseInitializedLength(); 162 if (length == 0) { 163 return false; // Object may be uninitialized. 164 } 165 166 const HeapSlot* src = elements_; 167 const HeapSlot* end = src + length; 168 HeapSlot* dst = elements_; 169 while (src != end) { 170 Shape* shape = static_cast<Shape*>(src[0].toPrivate()); 171 uint32_t offset = src[1].toPrivateUint32(); 172 MOZ_ASSERT(shape->is<Shape>()); 173 if (TraceManuallyBarrieredWeakEdge(trc, &shape, 174 "ShapeListWithOffsetsObject shape")) { 175 dst[0].unbarrieredSet(PrivateValue(shape)); 176 dst[1].unbarrieredSet(PrivateUint32Value(offset)); 177 dst += 2; 178 } 179 src += 2; 180 } 181 182 MOZ_ASSERT(dst <= end); 183 uint32_t newLength = dst - elements_; 184 setDenseInitializedLength(newLength); 185 186 if (length != newLength) { 187 JitSpew(JitSpew_StubFolding, "Cleared %u/%u shapes from %p", 188 (length - newLength) / 2, (length) / 2, this); 189 } 190 191 return length != 0; 192 }