JSFunction-inl.h (4785B)
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/GCProbes.h" 13 14 #include "gc/ObjectKind-inl.h" 15 #include "vm/JSContext-inl.h" 16 #include "vm/JSObject-inl.h" 17 #include "vm/NativeObject-inl.h" 18 19 namespace js { 20 21 inline const char* GetFunctionNameBytes(JSContext* cx, JSFunction* fun, 22 UniqueChars* bytes) { 23 if (fun->isAccessorWithLazyName()) { 24 JSAtom* name = fun->getAccessorNameForLazy(cx); 25 if (!name) { 26 return nullptr; 27 } 28 29 *bytes = StringToNewUTF8CharsZ(cx, *name); 30 return bytes->get(); 31 } 32 33 if (JSAtom* name = fun->fullExplicitName()) { 34 *bytes = StringToNewUTF8CharsZ(cx, *name); 35 return bytes->get(); 36 } 37 38 return "anonymous"; 39 } 40 41 } /* namespace js */ 42 43 /* static */ 44 inline JSFunction* JSFunction::create(JSContext* cx, js::gc::AllocKind kind, 45 js::gc::Heap heap, 46 js::Handle<js::SharedShape*> shape, 47 js::gc::AllocSite* site) { 48 MOZ_ASSERT(kind == js::gc::AllocKind::FUNCTION || 49 kind == js::gc::AllocKind::FUNCTION_EXTENDED); 50 51 debugCheckNewObject(shape, kind, heap); 52 53 const JSClass* clasp = shape->getObjectClass(); 54 MOZ_ASSERT(clasp->isNativeObject()); 55 MOZ_ASSERT(clasp->isJSFunction()); 56 MOZ_ASSERT_IF(kind == js::gc::AllocKind::FUNCTION, 57 clasp == js::FunctionClassPtr); 58 MOZ_ASSERT_IF(kind == js::gc::AllocKind::FUNCTION_EXTENDED, 59 clasp == js::FunctionExtendedClassPtr); 60 61 MOZ_ASSERT(calculateDynamicSlots(shape->numFixedSlots(), shape->slotSpan(), 62 clasp) == 0); 63 64 NativeObject* nobj = cx->newCell<NativeObject>(kind, heap, clasp, site); 65 if (!nobj) { 66 return nullptr; 67 } 68 69 nobj->initShape(shape); 70 71 nobj->initEmptyDynamicSlots(); 72 nobj->setEmptyElements(); 73 74 JSFunction* fun = static_cast<JSFunction*>(nobj); 75 fun->initFixedSlots(JSCLASS_RESERVED_SLOTS(clasp)); 76 fun->initFlagsAndArgCount(); 77 fun->initFixedSlot(NativeJitInfoOrInterpretedScriptSlot, 78 JS::PrivateValue(nullptr)); 79 80 if (kind == js::gc::AllocKind::FUNCTION_EXTENDED) { 81 fun->setFlags(FunctionFlags::EXTENDED); 82 } 83 84 MOZ_ASSERT(!clasp->shouldDelayMetadataBuilder(), 85 "Function has no extra data hanging off it, that wouldn't be " 86 "allocated at this point, that would require delaying the " 87 "building of metadata for it"); 88 if (MOZ_UNLIKELY(cx->realm()->hasAllocationMetadataBuilder())) { 89 fun = SetNewObjectMetadata(cx, fun); 90 } 91 92 js::gc::gcprobes::CreateObject(fun); 93 94 return fun; 95 } 96 97 /* static */ 98 inline bool JSFunction::getLength(JSContext* cx, js::HandleFunction fun, 99 uint16_t* length) { 100 if (fun->isNativeFun()) { 101 *length = fun->nargs(); 102 return true; 103 } 104 105 JSScript* script = getOrCreateScript(cx, fun); 106 if (!script) { 107 return false; 108 } 109 110 *length = script->funLength(); 111 return true; 112 } 113 114 /* static */ 115 inline bool JSFunction::getUnresolvedLength(JSContext* cx, 116 js::HandleFunction fun, 117 uint16_t* length) { 118 MOZ_ASSERT(!IsInternalFunctionObject(*fun)); 119 MOZ_ASSERT(!fun->hasResolvedLength()); 120 121 return JSFunction::getLength(cx, fun, length); 122 } 123 124 inline JSAtom* JSFunction::getUnresolvedName(JSContext* cx) { 125 if (isAccessorWithLazyName()) { 126 return getAccessorNameForLazy(cx); 127 } 128 129 return infallibleGetUnresolvedName(cx); 130 } 131 132 inline JSAtom* JSFunction::infallibleGetUnresolvedName(JSContext* cx) { 133 MOZ_ASSERT(!IsInternalFunctionObject(*this)); 134 MOZ_ASSERT(!isAccessorWithLazyName()); 135 MOZ_ASSERT(!hasResolvedName()); 136 137 if (JSAtom* name = fullExplicitOrInferredName()) { 138 return name; 139 } 140 141 return cx->names().empty_; 142 } 143 144 /* static */ inline bool JSFunction::getAllocKindForThis( 145 JSContext* cx, js::HandleFunction func, js::gc::AllocKind& allocKind) { 146 JSScript* script = getOrCreateScript(cx, func); 147 if (!script) { 148 return false; 149 } 150 151 size_t propertyCountEstimate = 152 script->immutableScriptData()->propertyCountEstimate; 153 154 // Choose the alloc assuming at least the default NewObjectKind slots, but 155 // bigger if our estimate shows we need it. 156 allocKind = js::gc::GetGCObjectKind(std::max( 157 js::gc::GetGCKindSlots(js::NewObjectGCKind()), propertyCountEstimate)); 158 return true; 159 } 160 161 #endif /* vm_JSFunction_inl_h */