inline HeapWord* G1BlockOffsetArray:: forward_to_block_containing_addr_const(HeapWord* q, HeapWord* n, const void* addr) const { if (addr >= gsp()->top()) return gsp()->top(); while (n <= addr) { q = n; oop obj = oop(q); if (obj->klass_or_null() == NULL) return q; n += block_size(q); } assert(q <= n, "wrong order for q and addr"); assert(addr < n, "wrong order for addr and n"); return q; }
// static void WindowNamedPropertiesHandler::Install(JSContext* aCx, JS::Handle<JSObject*> aProto) { JS::Rooted<JSObject*> protoProto(aCx); if (!::JS_GetPrototype(aCx, aProto, &protoProto)) { return; } // Note: since the scope polluter proxy lives on the window's prototype // chain, it needs a singleton type to avoid polluting type information // for properties on the window. JS::Rooted<JSObject*> gsp(aCx); js::ProxyOptions options; options.setSingleton(true); gsp = js::NewProxyObject(aCx, WindowNamedPropertiesHandler::getInstance(), JS::NullHandleValue, protoProto, js::GetGlobalForObjectCrossCompartment(aProto), options); if (!gsp) { return; } // And then set the prototype of the interface prototype object to be the // global scope polluter. ::JS_SplicePrototype(aCx, aProto, gsp); }
// static JSObject* WindowNamedPropertiesHandler::Create(JSContext* aCx, JS::Handle<JSObject*> aProto) { // Note: since the scope polluter proxy lives on the window's prototype // chain, it needs a singleton type to avoid polluting type information // for properties on the window. js::ProxyOptions options; options.setSingleton(true); options.setClass(&WindowNamedPropertiesClass.mBase); JS::Rooted<JSObject*> gsp(aCx); gsp = js::NewProxyObject(aCx, WindowNamedPropertiesHandler::getInstance(), JS::NullHandleValue, aProto, options); if (!gsp) { return nullptr; } bool succeeded; if (!JS_SetImmutablePrototype(aCx, gsp, &succeeded)) { return nullptr; } MOZ_ASSERT(succeeded, "errors making the [[Prototype]] of the named properties object " "immutable should have been JSAPI failures, not !succeeded"); return gsp; }
inline HeapWord* G1BlockOffsetArray::block_at_or_preceding(const void* addr, bool has_max_index, size_t max_index) const { assert(_array->offset_array(0) == 0, "objects can't cross covered areas"); size_t index = _array->index_for(addr); // We must make sure that the offset table entry we use is valid. If // "addr" is past the end, start at the last known one and go forward. if (has_max_index) { index = MIN2(index, max_index); } HeapWord* q = _array->address_for_index(index); uint offset = _array->offset_array(index); // Extend u_char to uint. while (offset >= N_words) { // The excess of the offset from N_words indicates a power of Base // to go back by. size_t n_cards_back = BlockOffsetArray::entry_to_cards_back(offset); q -= (N_words * n_cards_back); assert(q >= gsp()->bottom(), "Went below bottom!"); index -= n_cards_back; offset = _array->offset_array(index); } assert(offset < N_words, "offset too large"); q -= offset; return q; }
HeapWord* G1BlockOffsetArray::forward_to_block_containing_addr_slow(HeapWord* q, HeapWord* n, const void* addr) { // We're not in the normal case. We need to handle an important subcase // here: LAB allocation. An allocation previously recorded in the // offset table was actually a lab allocation, and was divided into // several objects subsequently. Fix this situation as we answer the // query, by updating entries as we cross them. // If the fist object's end q is at the card boundary. Start refining // with the corresponding card (the value of the entry will be basically // set to 0). If the object crosses the boundary -- start from the next card. size_t n_index = _array->index_for(n); size_t next_index = _array->index_for(n) + !_array->is_card_boundary(n); // Calculate a consistent next boundary. If "n" is not at the boundary // already, step to the boundary. HeapWord* next_boundary = _array->address_for_index(n_index) + (n_index == next_index ? 0 : N_words); assert(next_boundary <= _array->_end, err_msg("next_boundary is beyond the end of the covered region " " next_boundary " PTR_FORMAT " _array->_end " PTR_FORMAT, p2i(next_boundary), p2i(_array->_end))); if (addr >= gsp()->top()) return gsp()->top(); while (next_boundary < addr) { while (n <= next_boundary) { q = n; oop obj = oop(q); if (obj->klass_or_null() == NULL) return q; n += block_size(q); } assert(q <= next_boundary && n > next_boundary, "Consequence of loop"); // [q, n) is the block that crosses the boundary. alloc_block_work2(&next_boundary, &next_index, q, n); } return forward_to_block_containing_addr_const(q, n, addr); }
// static JSObject* WindowNamedPropertiesHandler::Create(JSContext* aCx, JS::Handle<JSObject*> aProto) { // Note: since the scope polluter proxy lives on the window's prototype // chain, it needs a singleton type to avoid polluting type information // for properties on the window. JS::Rooted<JSObject*> gsp(aCx); js::ProxyOptions options; options.setSingleton(true); options.setClass(&WindowNamedPropertiesClass.mBase); return js::NewProxyObject(aCx, WindowNamedPropertiesHandler::getInstance(), JS::NullHandleValue, aProto, options); }
inline size_t G1BlockOffsetArray::block_size(const HeapWord* p) const { return gsp()->block_size(p); }