|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
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 jsfuninlines_h |
|
8 #define jsfuninlines_h |
|
9 |
|
10 #include "jsfun.h" |
|
11 |
|
12 #include "vm/ScopeObject.h" |
|
13 |
|
14 namespace js { |
|
15 |
|
16 inline const char * |
|
17 GetFunctionNameBytes(JSContext *cx, JSFunction *fun, JSAutoByteString *bytes) |
|
18 { |
|
19 JSAtom *atom = fun->atom(); |
|
20 if (atom) |
|
21 return bytes->encodeLatin1(cx, atom); |
|
22 return js_anonymous_str; |
|
23 } |
|
24 |
|
25 static inline JSObject * |
|
26 SkipScopeParent(JSObject *parent) |
|
27 { |
|
28 if (!parent) |
|
29 return nullptr; |
|
30 while (parent->is<ScopeObject>()) |
|
31 parent = &parent->as<ScopeObject>().enclosingScope(); |
|
32 return parent; |
|
33 } |
|
34 |
|
35 inline bool |
|
36 CanReuseFunctionForClone(JSContext *cx, HandleFunction fun) |
|
37 { |
|
38 if (!fun->hasSingletonType()) |
|
39 return false; |
|
40 if (fun->isInterpretedLazy()) { |
|
41 LazyScript *lazy = fun->lazyScript(); |
|
42 if (lazy->hasBeenCloned()) |
|
43 return false; |
|
44 lazy->setHasBeenCloned(); |
|
45 } else { |
|
46 JSScript *script = fun->nonLazyScript(); |
|
47 if (script->hasBeenCloned()) |
|
48 return false; |
|
49 script->setHasBeenCloned(); |
|
50 } |
|
51 return true; |
|
52 } |
|
53 |
|
54 inline JSFunction * |
|
55 CloneFunctionObjectIfNotSingleton(JSContext *cx, HandleFunction fun, HandleObject parent, |
|
56 NewObjectKind newKind = GenericObject) |
|
57 { |
|
58 /* |
|
59 * For attempts to clone functions at a function definition opcode, |
|
60 * try to avoid the the clone if the function has singleton type. This |
|
61 * was called pessimistically, and we need to preserve the type's |
|
62 * property that if it is singleton there is only a single object |
|
63 * with its type in existence. |
|
64 * |
|
65 * For functions inner to run once lambda, it may be possible that |
|
66 * the lambda runs multiple times and we repeatedly clone it. In these |
|
67 * cases, fall through to CloneFunctionObject, which will deep clone |
|
68 * the function's script. |
|
69 */ |
|
70 if (CanReuseFunctionForClone(cx, fun)) { |
|
71 RootedObject obj(cx, SkipScopeParent(parent)); |
|
72 if (!JSObject::setParent(cx, fun, obj)) |
|
73 return nullptr; |
|
74 fun->setEnvironment(parent); |
|
75 return fun; |
|
76 } |
|
77 |
|
78 // These intermediate variables are needed to avoid link errors on some |
|
79 // platforms. Sigh. |
|
80 gc::AllocKind finalizeKind = JSFunction::FinalizeKind; |
|
81 gc::AllocKind extendedFinalizeKind = JSFunction::ExtendedFinalizeKind; |
|
82 gc::AllocKind kind = fun->isExtended() |
|
83 ? extendedFinalizeKind |
|
84 : finalizeKind; |
|
85 return CloneFunctionObject(cx, fun, parent, kind, newKind); |
|
86 } |
|
87 |
|
88 } /* namespace js */ |
|
89 |
|
90 #endif /* jsfuninlines_h */ |