/* -*- 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/. */ #ifndef vm_PlainObject_inl_h #define vm_PlainObject_inl_h #include "vm/PlainObject.h" #include "mozilla/Assertions.h" // MOZ_ASSERT, MOZ_ASSERT_IF #include "mozilla/Attributes.h" // MOZ_ALWAYS_INLINE #include "gc/Allocator.h" // js::gc::InitialHeap #include "js/RootingAPI.h" // JS::Handle, JS::Rooted, JS::MutableHandle #include "js/Value.h" // JS::Value, JS_IS_CONSTRUCTING #include "vm/JSFunction.h" // JSFunction #include "vm/NativeObject.h" // js::NativeObject::create #include "vm/ObjectGroup.h" // js::ObjectGroup, js::GenericObject, js::NewObjectKind #include "vm/Shape.h" // js::Shape #include "gc/ObjectKind-inl.h" // js::gc::GetGCObjectKind #include "vm/JSObject-inl.h" // js::GetInitialHeap, js::NewBuiltinClassInstance #include "vm/NativeObject-inl.h" // js::NativeObject::{create,setLastProperty} /* static */ inline JS::Result js::PlainObject::createWithTemplate(JSContext* cx, JS::Handle templateObject) { JS::Rooted group(cx, templateObject->group()); MOZ_ASSERT(group->clasp() == &PlainObject::class_); gc::InitialHeap heap = GetInitialHeap(GenericObject, group); JS::Rooted shape(cx, templateObject->lastProperty()); gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots()); MOZ_ASSERT(gc::CanChangeToBackgroundAllocKind(kind, shape->getObjectClass())); kind = gc::ForegroundToBackgroundAllocKind(kind); return NativeObject::create(cx, kind, heap, shape, group) .map([](NativeObject* obj) { return &obj->as(); }); } inline js::gc::AllocKind js::PlainObject::allocKindForTenure() const { gc::AllocKind kind = gc::GetGCObjectFixedSlotsKind(numFixedSlots()); MOZ_ASSERT(!gc::IsBackgroundFinalized(kind)); MOZ_ASSERT(gc::CanChangeToBackgroundAllocKind(kind, getClass())); return gc::ForegroundToBackgroundAllocKind(kind); } namespace js { // Create an object based on a template object created for either a NewObject // bytecode op or for a constructor call. static inline PlainObject* CopyTemplateObject( JSContext* cx, JS::Handle baseobj, NewObjectKind newKind = GenericObject) { MOZ_ASSERT(!baseobj->inDictionaryMode()); gc::AllocKind allocKind = gc::GetGCObjectFixedSlotsKind(baseobj->numFixedSlots()); allocKind = gc::ForegroundToBackgroundAllocKind(allocKind); MOZ_ASSERT_IF(baseobj->isTenured(), allocKind == baseobj->asTenured().getAllocKind()); RootedObject proto(cx, baseobj->staticPrototype()); JS::Rooted obj(cx, NewObjectWithGivenProtoAndKinds( cx, proto, allocKind, newKind)); if (!obj) { return nullptr; } if (!obj->setLastProperty(cx, baseobj->lastProperty())) { return nullptr; } return obj; } static MOZ_ALWAYS_INLINE bool CreateThis(JSContext* cx, JS::Handle callee, JS::Handle newTarget, NewObjectKind newKind, JS::MutableHandle thisv) { if (callee->constructorNeedsUninitializedThis()) { thisv.setMagic(JS_UNINITIALIZED_LEXICAL); return true; } MOZ_ASSERT(thisv.isMagic(JS_IS_CONSTRUCTING)); PlainObject* obj = CreateThisForFunction(cx, callee, newTarget, newKind); if (!obj) { return false; } MOZ_ASSERT(obj->nonCCWRealm() == callee->realm()); thisv.setObject(*obj); return true; } } // namespace js #endif // vm_PlainObject_inl_h