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 #ifndef vm_PlainObject_inl_h
8 #define vm_PlainObject_inl_h
9
10 #include "vm/PlainObject.h"
11
12 #include "mozilla/Assertions.h" // MOZ_ASSERT, MOZ_ASSERT_IF
13 #include "mozilla/Attributes.h" // MOZ_ALWAYS_INLINE
14
15 #include "gc/Allocator.h" // js::gc::InitialHeap
16 #include "js/RootingAPI.h" // JS::Handle, JS::Rooted, JS::MutableHandle
17 #include "js/Value.h" // JS::Value, JS_IS_CONSTRUCTING
18 #include "vm/JSFunction.h" // JSFunction
19 #include "vm/JSObject.h" // js::GenericObject, js::NewObjectKind
20 #include "vm/NativeObject.h" // js::NativeObject::create
21 #include "vm/Shape.h" // js::Shape
22
23 #include "gc/ObjectKind-inl.h" // js::gc::GetGCObjectKind
24 #include "vm/JSObject-inl.h" // js::GetInitialHeap, js::NewBuiltinClassInstance
25 #include "vm/NativeObject-inl.h" // js::NativeObject::{create,setLastProperty}
26
27 /* static */ inline JS::Result<js::PlainObject*, JS::OOM>
createWithShape(JSContext * cx,JS::Handle<Shape * > shape)28 js::PlainObject::createWithShape(JSContext* cx, JS::Handle<Shape*> shape) {
29 MOZ_ASSERT(shape->getObjectClass() == &PlainObject::class_);
30 gc::InitialHeap heap = GetInitialHeap(GenericObject, &PlainObject::class_);
31
32 gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
33 MOZ_ASSERT(gc::CanChangeToBackgroundAllocKind(kind, shape->getObjectClass()));
34 kind = gc::ForegroundToBackgroundAllocKind(kind);
35
36 return NativeObject::create(cx, kind, heap, shape).map([](NativeObject* obj) {
37 return &obj->as<PlainObject>();
38 });
39 }
40
41 /* static */ inline JS::Result<js::PlainObject*, JS::OOM>
createWithTemplate(JSContext * cx,JS::Handle<PlainObject * > templateObject)42 js::PlainObject::createWithTemplate(JSContext* cx,
43 JS::Handle<PlainObject*> templateObject) {
44 JS::Rooted<Shape*> shape(cx, templateObject->shape());
45 return createWithShape(cx, shape);
46 }
47
allocKindForTenure()48 inline js::gc::AllocKind js::PlainObject::allocKindForTenure() const {
49 gc::AllocKind kind = gc::GetGCObjectFixedSlotsKind(numFixedSlots());
50 MOZ_ASSERT(!gc::IsBackgroundFinalized(kind));
51 MOZ_ASSERT(gc::CanChangeToBackgroundAllocKind(kind, getClass()));
52 return gc::ForegroundToBackgroundAllocKind(kind);
53 }
54
55 namespace js {
56
57 // Create an object based on a template object created for either a NewObject
58 // bytecode op or for a constructor call.
59 static inline PlainObject* CopyTemplateObject(
60 JSContext* cx, JS::Handle<PlainObject*> baseobj,
61 NewObjectKind newKind = GenericObject) {
62 MOZ_ASSERT(!baseobj->inDictionaryMode());
63
64 gc::AllocKind allocKind =
65 gc::GetGCObjectFixedSlotsKind(baseobj->numFixedSlots());
66 allocKind = gc::ForegroundToBackgroundAllocKind(allocKind);
67 MOZ_ASSERT_IF(baseobj->isTenured(),
68 allocKind == baseobj->asTenured().getAllocKind());
69 RootedObject proto(cx, baseobj->staticPrototype());
70 JS::Rooted<PlainObject*> obj(cx, NewObjectWithGivenProtoAndKinds<PlainObject>(
71 cx, proto, allocKind, newKind));
72 if (!obj) {
73 return nullptr;
74 }
75
76 if (!obj->setShapeAndUpdateSlots(cx, baseobj->shape())) {
77 return nullptr;
78 }
79
80 return obj;
81 }
82
CreateThis(JSContext * cx,JS::Handle<JSFunction * > callee,JS::Handle<JSObject * > newTarget,NewObjectKind newKind,JS::MutableHandle<JS::Value> thisv)83 static MOZ_ALWAYS_INLINE bool CreateThis(JSContext* cx,
84 JS::Handle<JSFunction*> callee,
85 JS::Handle<JSObject*> newTarget,
86 NewObjectKind newKind,
87 JS::MutableHandle<JS::Value> thisv) {
88 if (callee->constructorNeedsUninitializedThis()) {
89 thisv.setMagic(JS_UNINITIALIZED_LEXICAL);
90 return true;
91 }
92
93 MOZ_ASSERT(thisv.isMagic(JS_IS_CONSTRUCTING));
94
95 PlainObject* obj = CreateThisForFunction(cx, callee, newTarget, newKind);
96 if (!obj) {
97 return false;
98 }
99
100 MOZ_ASSERT(obj->nonCCWRealm() == callee->realm());
101 thisv.setObject(*obj);
102 return true;
103 }
104
105 } // namespace js
106
107 #endif // vm_PlainObject_inl_h
108