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