7c1b0889d5ef0ebf214a4a7042acd56fe781fb9f
[WebKit-https.git] / Source / JavaScriptCore / runtime / FunctionExecutable.h
1 /*
2  * Copyright (C) 2009, 2010, 2013-2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #pragma once
27
28 #include "ScriptExecutable.h"
29
30 namespace JSC {
31
32 class FunctionExecutable final : public ScriptExecutable {
33     friend class JIT;
34     friend class LLIntOffsetsExtractor;
35 public:
36     typedef ScriptExecutable Base;
37     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
38
39     static FunctionExecutable* create(
40         VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, 
41         unsigned lastLine, unsigned endColumn, Intrinsic intrinsic)
42     {
43         FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, lastLine, endColumn, intrinsic);
44         executable->finishCreation(vm);
45         return executable;
46     }
47     static FunctionExecutable* fromGlobalCode(
48         const Identifier& name, ExecState&, const SourceCode&, 
49         JSObject*& exception, int overrideLineNumber);
50
51     static void destroy(JSCell*);
52         
53     UnlinkedFunctionExecutable* unlinkedExecutable() const
54     {
55         return m_unlinkedExecutable.get();
56     }
57
58     // Returns either call or construct bytecode. This can be appropriate
59     // for answering questions that that don't vary between call and construct --
60     // for example, argumentsRegister().
61     FunctionCodeBlock* eitherCodeBlock()
62     {
63         if (m_codeBlockForCall)
64             return m_codeBlockForCall.get();
65         return m_codeBlockForConstruct.get();
66     }
67         
68     bool isGeneratedForCall() const
69     {
70         return !!m_codeBlockForCall;
71     }
72
73     FunctionCodeBlock* codeBlockForCall()
74     {
75         return m_codeBlockForCall.get();
76     }
77
78     bool isGeneratedForConstruct() const
79     {
80         return m_codeBlockForConstruct.get();
81     }
82
83     FunctionCodeBlock* codeBlockForConstruct()
84     {
85         return m_codeBlockForConstruct.get();
86     }
87         
88     bool isGeneratedFor(CodeSpecializationKind kind)
89     {
90         if (kind == CodeForCall)
91             return isGeneratedForCall();
92         ASSERT(kind == CodeForConstruct);
93         return isGeneratedForConstruct();
94     }
95         
96     FunctionCodeBlock* codeBlockFor(CodeSpecializationKind kind)
97     {
98         if (kind == CodeForCall)
99             return codeBlockForCall();
100         ASSERT(kind == CodeForConstruct);
101         return codeBlockForConstruct();
102     }
103
104     FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind);
105         
106     FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind)
107     {
108         return baselineCodeBlockFor(kind);
109     }
110
111     RefPtr<TypeSet> returnStatementTypeSet() 
112     {
113         if (!m_returnStatementTypeSet)
114             m_returnStatementTypeSet = TypeSet::create();
115
116         return m_returnStatementTypeSet;
117     }
118         
119     FunctionMode functionMode() { return m_unlinkedExecutable->functionMode(); }
120     bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); }
121     ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); }
122     bool isClass() const { return !classSource().isNull(); }
123     bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; }
124     bool isGetter() const { return parseMode() == SourceParseMode::GetterMode; }
125     bool isSetter() const { return parseMode() == SourceParseMode::SetterMode; }
126     bool isGenerator() const { return isGeneratorParseMode(parseMode()); }
127     bool isMethod() const { return parseMode() == SourceParseMode::MethodMode; }
128     bool hasCallerAndArgumentsProperties() const
129     {
130         // Per https://tc39.github.io/ecma262/#sec-forbidden-extensions, only sloppy-mode non-builtin functions in old-style (pre-ES6) syntactic forms can contain
131         // "caller" and "arguments".
132         return !isStrictMode() && parseMode() == SourceParseMode::NormalFunctionMode && !isClassConstructorFunction();
133     }
134     bool hasPrototypeProperty() const
135     {
136         return SourceParseModeSet(
137             SourceParseMode::NormalFunctionMode,
138             SourceParseMode::GeneratorBodyMode,
139             SourceParseMode::GeneratorWrapperFunctionMode,
140             SourceParseMode::GeneratorWrapperMethodMode
141         ).contains(parseMode()) || isClass();
142     }
143     DerivedContextType derivedContextType() const { return m_unlinkedExecutable->derivedContextType(); }
144     bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); }
145     const Identifier& name() { return m_unlinkedExecutable->name(); }
146     const Identifier& ecmaName() { return m_unlinkedExecutable->ecmaName(); }
147     const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
148     unsigned parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
149     SourceParseMode parseMode() const { return m_unlinkedExecutable->parseMode(); }
150     JSParserScriptMode scriptMode() const { return m_unlinkedExecutable->scriptMode(); }
151     const SourceCode& classSource() const { return m_unlinkedExecutable->classSource(); }
152
153     static void visitChildren(JSCell*, SlotVisitor&);
154     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
155     {
156         return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), info());
157     }
158
159     unsigned parametersStartOffset() const { return m_parametersStartOffset; }
160
161     void overrideParameterAndTypeProfilingStartEndOffsets(unsigned parametersStartOffset, unsigned typeProfilingStartOffset, unsigned typeProfilingEndOffset)
162     {
163         m_parametersStartOffset = parametersStartOffset;
164         m_typeProfilingStartOffset = typeProfilingStartOffset;
165         m_typeProfilingEndOffset = typeProfilingEndOffset;
166     }
167
168     DECLARE_INFO;
169
170     InferredValue* singletonFunction() { return m_singletonFunction.get(); }
171
172 private:
173     friend class ExecutableBase;
174     FunctionExecutable(
175         VM&, const SourceCode&, UnlinkedFunctionExecutable*,
176         unsigned lastLine, unsigned endColumn, Intrinsic);
177     
178     void finishCreation(VM&);
179
180     friend class ScriptExecutable;
181     
182     unsigned m_parametersStartOffset;
183     WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
184     WriteBarrier<FunctionCodeBlock> m_codeBlockForCall;
185     WriteBarrier<FunctionCodeBlock> m_codeBlockForConstruct;
186     RefPtr<TypeSet> m_returnStatementTypeSet;
187     WriteBarrier<InferredValue> m_singletonFunction;
188 };
189
190 } // namespace JSC