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_JSFunction_inl_h
8 #define vm_JSFunction_inl_h
9
10 #include "vm/JSFunction.h"
11
12 #include "gc/Allocator.h"
13 #include "gc/GCProbes.h"
14 #include "js/CharacterEncoding.h"
15 #include "vm/EnvironmentObject.h"
16 #include "vm/WellKnownAtom.h" // js_*_str
17
18 #include "vm/JSObject-inl.h"
19 #include "vm/NativeObject-inl.h"
20
21 namespace js {
22
GetFunctionNameBytes(JSContext * cx,JSFunction * fun,UniqueChars * bytes)23 inline const char* GetFunctionNameBytes(JSContext* cx, JSFunction* fun,
24 UniqueChars* bytes) {
25 if (JSAtom* name = fun->explicitName()) {
26 *bytes = StringToNewUTF8CharsZ(cx, *name);
27 return bytes->get();
28 }
29 return js_anonymous_str;
30 }
31
32 inline JSFunction* CloneFunctionObject(JSContext* cx, HandleFunction fun,
33 HandleObject enclosingEnv,
34 HandleObject proto = nullptr) {
35 // These intermediate variables are needed to avoid link errors on some
36 // platforms. Sigh.
37 gc::AllocKind finalizeKind = gc::AllocKind::FUNCTION;
38 gc::AllocKind extendedFinalizeKind = gc::AllocKind::FUNCTION_EXTENDED;
39 gc::AllocKind kind = fun->isExtended() ? extendedFinalizeKind : finalizeKind;
40
41 MOZ_ASSERT(CanReuseScriptForClone(cx->realm(), fun, enclosingEnv));
42 return CloneFunctionReuseScript(cx, fun, enclosingEnv, kind, proto);
43 }
44
45 } /* namespace js */
46
create(JSContext * cx,js::gc::AllocKind kind,js::gc::InitialHeap heap,js::HandleShape shape)47 /* static */ inline JS::Result<JSFunction*, JS::OOM> JSFunction::create(
48 JSContext* cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
49 js::HandleShape shape) {
50 MOZ_ASSERT(kind == js::gc::AllocKind::FUNCTION ||
51 kind == js::gc::AllocKind::FUNCTION_EXTENDED);
52
53 debugCheckNewObject(shape, kind, heap);
54
55 const JSClass* clasp = shape->getObjectClass();
56 MOZ_ASSERT(clasp->isNativeObject());
57 MOZ_ASSERT(clasp->isJSFunction());
58
59 static constexpr size_t NumDynamicSlots = 0;
60 MOZ_ASSERT(calculateDynamicSlots(shape->numFixedSlots(), shape->slotSpan(),
61 clasp) == NumDynamicSlots);
62
63 JSObject* obj = js::AllocateObject(cx, kind, NumDynamicSlots, heap, clasp);
64 if (!obj) {
65 return cx->alreadyReportedOOM();
66 }
67
68 NativeObject* nobj = static_cast<NativeObject*>(obj);
69 nobj->initShape(shape);
70
71 nobj->initEmptyDynamicSlots();
72 nobj->setEmptyElements();
73
74 MOZ_ASSERT(!clasp->hasPrivate());
75 MOZ_ASSERT(shape->slotSpan() == 0);
76
77 JSFunction* fun = static_cast<JSFunction*>(nobj);
78 fun->nargs_ = 0;
79
80 // This must be overwritten by some ultimate caller: there's no default
81 // value to which we could sensibly initialize this.
82 MOZ_MAKE_MEM_UNDEFINED(&fun->u, sizeof(u));
83
84 fun->atom_.init(nullptr);
85
86 if (kind == js::gc::AllocKind::FUNCTION_EXTENDED) {
87 fun->setFlags(FunctionFlags::EXTENDED);
88 for (js::GCPtrValue& extendedSlot : fun->toExtended()->extendedSlots) {
89 extendedSlot.init(JS::UndefinedValue());
90 }
91 } else {
92 fun->setFlags(0);
93 }
94
95 MOZ_ASSERT(!clasp->shouldDelayMetadataBuilder(),
96 "Function has no extra data hanging off it, that wouldn't be "
97 "allocated at this point, that would require delaying the "
98 "building of metadata for it");
99 fun = SetNewObjectMetadata(cx, fun);
100
101 js::gc::gcprobes::CreateObject(fun);
102
103 return fun;
104 }
105
106 #endif /* vm_JSFunction_inl_h */
107