]>
Commit | Line | Data |
---|---|---|
93a37866 | 1 | /* |
ed1e77d3 | 2 | * Copyright (C) 2012-2015 Apple Inc. All Rights Reserved. |
93a37866 A |
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 | #ifndef UnlinkedCodeBlock_h | |
27 | #define UnlinkedCodeBlock_h | |
28 | ||
29 | #include "BytecodeConventions.h" | |
93a37866 A |
30 | #include "CodeSpecializationKind.h" |
31 | #include "CodeType.h" | |
32 | #include "ExpressionRangeInfo.h" | |
ed1e77d3 | 33 | #include "HandlerInfo.h" |
93a37866 A |
34 | #include "Identifier.h" |
35 | #include "JSCell.h" | |
36 | #include "JSString.h" | |
93a37866 A |
37 | #include "ParserModes.h" |
38 | #include "RegExp.h" | |
39 | #include "SpecialPointer.h" | |
40 | #include "SymbolTable.h" | |
81345200 | 41 | #include "VirtualRegister.h" |
93a37866 A |
42 | |
43 | #include <wtf/RefCountedArray.h> | |
44 | #include <wtf/Vector.h> | |
45 | ||
46 | namespace JSC { | |
47 | ||
48 | class Debugger; | |
49 | class FunctionBodyNode; | |
50 | class FunctionExecutable; | |
51 | class FunctionParameters; | |
52 | class JSScope; | |
ed1e77d3 | 53 | class ParserError; |
93a37866 A |
54 | class ScriptExecutable; |
55 | class SourceCode; | |
56 | class SourceProvider; | |
81345200 | 57 | class SymbolTable; |
93a37866 A |
58 | class UnlinkedCodeBlock; |
59 | class UnlinkedFunctionCodeBlock; | |
81345200 | 60 | class UnlinkedInstructionStream; |
93a37866 A |
61 | |
62 | typedef unsigned UnlinkedValueProfile; | |
63 | typedef unsigned UnlinkedArrayProfile; | |
64 | typedef unsigned UnlinkedArrayAllocationProfile; | |
65 | typedef unsigned UnlinkedObjectAllocationProfile; | |
66 | typedef unsigned UnlinkedLLIntCallLinkInfo; | |
67 | ||
68 | struct ExecutableInfo { | |
ed1e77d3 | 69 | ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, ConstructorKind constructorKind) |
93a37866 A |
70 | : m_needsActivation(needsActivation) |
71 | , m_usesEval(usesEval) | |
72 | , m_isStrictMode(isStrictMode) | |
73 | , m_isConstructor(isConstructor) | |
81345200 | 74 | , m_isBuiltinFunction(isBuiltinFunction) |
ed1e77d3 | 75 | , m_constructorKind(static_cast<unsigned>(constructorKind)) |
93a37866 | 76 | { |
ed1e77d3 | 77 | ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind)); |
93a37866 | 78 | } |
ed1e77d3 A |
79 | |
80 | bool needsActivation() const { return m_needsActivation; } | |
81 | bool usesEval() const { return m_usesEval; } | |
82 | bool isStrictMode() const { return m_isStrictMode; } | |
83 | bool isConstructor() const { return m_isConstructor; } | |
84 | bool isBuiltinFunction() const { return m_isBuiltinFunction; } | |
85 | ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); } | |
86 | ||
87 | private: | |
88 | unsigned m_needsActivation : 1; | |
89 | unsigned m_usesEval : 1; | |
90 | unsigned m_isStrictMode : 1; | |
91 | unsigned m_isConstructor : 1; | |
92 | unsigned m_isBuiltinFunction : 1; | |
93 | unsigned m_constructorKind : 2; | |
81345200 A |
94 | }; |
95 | ||
96 | enum UnlinkedFunctionKind { | |
97 | UnlinkedNormalFunction, | |
98 | UnlinkedBuiltinFunction, | |
93a37866 A |
99 | }; |
100 | ||
ed1e77d3 | 101 | class UnlinkedFunctionExecutable final : public JSCell { |
93a37866 | 102 | public: |
81345200 | 103 | friend class BuiltinExecutables; |
93a37866 | 104 | friend class CodeCache; |
81345200 | 105 | friend class VM; |
ed1e77d3 | 106 | |
93a37866 | 107 | typedef JSCell Base; |
ed1e77d3 A |
108 | static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; |
109 | ||
110 | static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionBodyNode* node, UnlinkedFunctionKind unlinkedFunctionKind, RefPtr<SourceProvider>&& sourceOverride = nullptr) | |
93a37866 | 111 | { |
ed1e77d3 A |
112 | UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap)) |
113 | UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, WTF::move(sourceOverride), node, unlinkedFunctionKind); | |
93a37866 A |
114 | instance->finishCreation(*vm); |
115 | return instance; | |
116 | } | |
117 | ||
118 | const Identifier& name() const { return m_name; } | |
119 | const Identifier& inferredName() const { return m_inferredName; } | |
120 | JSString* nameValue() const { return m_nameValue.get(); } | |
81345200 | 121 | SymbolTable* symbolTable(CodeSpecializationKind kind) |
93a37866 A |
122 | { |
123 | return (kind == CodeForCall) ? m_symbolTableForCall.get() : m_symbolTableForConstruct.get(); | |
124 | } | |
125 | size_t parameterCount() const; | |
126 | bool isInStrictContext() const { return m_isInStrictContext; } | |
ed1e77d3 A |
127 | FunctionMode functionMode() const { return static_cast<FunctionMode>(m_functionMode); } |
128 | ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); } | |
93a37866 | 129 | |
81345200 A |
130 | unsigned unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; } |
131 | unsigned unlinkedBodyStartColumn() const { return m_unlinkedBodyStartColumn; } | |
132 | unsigned unlinkedBodyEndColumn() const { return m_unlinkedBodyEndColumn; } | |
93a37866 A |
133 | unsigned startOffset() const { return m_startOffset; } |
134 | unsigned sourceLength() { return m_sourceLength; } | |
ed1e77d3 A |
135 | unsigned parametersStartOffset() const { return m_parametersStartOffset; } |
136 | unsigned typeProfilingStartOffset() const { return m_typeProfilingStartOffset; } | |
137 | unsigned typeProfilingEndOffset() const { return m_typeProfilingEndOffset; } | |
93a37866 | 138 | |
ed1e77d3 A |
139 | UnlinkedFunctionCodeBlock* codeBlockFor( |
140 | VM&, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, | |
141 | ParserError&); | |
93a37866 | 142 | |
ed1e77d3 A |
143 | static UnlinkedFunctionExecutable* fromGlobalCode( |
144 | const Identifier&, ExecState&, const SourceCode&, JSObject*& exception, | |
145 | int overrideLineNumber); | |
93a37866 | 146 | |
ed1e77d3 | 147 | FunctionExecutable* link(VM&, const SourceCode&, int overrideLineNumber = -1); |
93a37866 A |
148 | |
149 | void clearCodeForRecompilation() | |
150 | { | |
151 | m_symbolTableForCall.clear(); | |
152 | m_symbolTableForConstruct.clear(); | |
153 | m_codeBlockForCall.clear(); | |
154 | m_codeBlockForConstruct.clear(); | |
155 | } | |
156 | ||
157 | FunctionParameters* parameters() { return m_parameters.get(); } | |
158 | ||
81345200 | 159 | void recordParse(CodeFeatures features, bool hasCapturedVariables) |
93a37866 A |
160 | { |
161 | m_features = features; | |
162 | m_hasCapturedVariables = hasCapturedVariables; | |
93a37866 A |
163 | } |
164 | ||
93a37866 A |
165 | CodeFeatures features() const { return m_features; } |
166 | bool hasCapturedVariables() const { return m_hasCapturedVariables; } | |
167 | ||
168 | static const bool needsDestruction = true; | |
93a37866 A |
169 | static void destroy(JSCell*); |
170 | ||
81345200 | 171 | bool isBuiltinFunction() const { return m_isBuiltinFunction; } |
ed1e77d3 | 172 | bool isClassConstructorFunction() const { return constructorKind() != ConstructorKind::None; } |
81345200 | 173 | |
93a37866 | 174 | private: |
ed1e77d3 | 175 | UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, RefPtr<SourceProvider>&& sourceOverride, FunctionBodyNode*, UnlinkedFunctionKind); |
93a37866 A |
176 | WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall; |
177 | WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct; | |
178 | ||
93a37866 A |
179 | Identifier m_name; |
180 | Identifier m_inferredName; | |
181 | WriteBarrier<JSString> m_nameValue; | |
81345200 A |
182 | WriteBarrier<SymbolTable> m_symbolTableForCall; |
183 | WriteBarrier<SymbolTable> m_symbolTableForConstruct; | |
93a37866 | 184 | RefPtr<FunctionParameters> m_parameters; |
ed1e77d3 | 185 | RefPtr<SourceProvider> m_sourceOverride; |
93a37866 A |
186 | unsigned m_firstLineOffset; |
187 | unsigned m_lineCount; | |
81345200 A |
188 | unsigned m_unlinkedFunctionNameStart; |
189 | unsigned m_unlinkedBodyStartColumn; | |
190 | unsigned m_unlinkedBodyEndColumn; | |
93a37866 A |
191 | unsigned m_startOffset; |
192 | unsigned m_sourceLength; | |
ed1e77d3 A |
193 | unsigned m_parametersStartOffset; |
194 | unsigned m_typeProfilingStartOffset; | |
195 | unsigned m_typeProfilingEndOffset; | |
93a37866 A |
196 | |
197 | CodeFeatures m_features; | |
198 | ||
ed1e77d3 A |
199 | unsigned m_isInStrictContext : 1; |
200 | unsigned m_hasCapturedVariables : 1; | |
201 | unsigned m_isBuiltinFunction : 1; | |
202 | unsigned m_constructorKind : 2; | |
203 | unsigned m_functionMode : 1; // FunctionMode | |
93a37866 A |
204 | |
205 | protected: | |
206 | void finishCreation(VM& vm) | |
207 | { | |
208 | Base::finishCreation(vm); | |
209 | m_nameValue.set(vm, this, jsString(&vm, name().string())); | |
210 | } | |
211 | ||
212 | static void visitChildren(JSCell*, SlotVisitor&); | |
213 | ||
214 | public: | |
215 | static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) | |
216 | { | |
81345200 | 217 | return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionExecutableType, StructureFlags), info()); |
93a37866 A |
218 | } |
219 | ||
81345200 | 220 | DECLARE_EXPORT_INFO; |
93a37866 A |
221 | }; |
222 | ||
223 | struct UnlinkedStringJumpTable { | |
224 | typedef HashMap<RefPtr<StringImpl>, int32_t> StringOffsetTable; | |
225 | StringOffsetTable offsetTable; | |
226 | ||
227 | inline int32_t offsetForValue(StringImpl* value, int32_t defaultOffset) | |
228 | { | |
229 | StringOffsetTable::const_iterator end = offsetTable.end(); | |
230 | StringOffsetTable::const_iterator loc = offsetTable.find(value); | |
231 | if (loc == end) | |
232 | return defaultOffset; | |
233 | return loc->value; | |
234 | } | |
235 | ||
236 | }; | |
237 | ||
238 | struct UnlinkedSimpleJumpTable { | |
239 | Vector<int32_t> branchOffsets; | |
240 | int32_t min; | |
241 | ||
242 | int32_t offsetForValue(int32_t value, int32_t defaultOffset); | |
243 | void add(int32_t key, int32_t offset) | |
244 | { | |
245 | if (!branchOffsets[key]) | |
246 | branchOffsets[key] = offset; | |
247 | } | |
248 | }; | |
249 | ||
93a37866 A |
250 | struct UnlinkedInstruction { |
251 | UnlinkedInstruction() { u.operand = 0; } | |
252 | UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; } | |
253 | UnlinkedInstruction(int operand) { u.operand = operand; } | |
254 | union { | |
255 | OpcodeID opcode; | |
256 | int32_t operand; | |
81345200 | 257 | unsigned index; |
93a37866 A |
258 | } u; |
259 | }; | |
260 | ||
261 | class UnlinkedCodeBlock : public JSCell { | |
262 | public: | |
263 | typedef JSCell Base; | |
ed1e77d3 A |
264 | static const unsigned StructureFlags = Base::StructureFlags; |
265 | ||
93a37866 | 266 | static const bool needsDestruction = true; |
93a37866 A |
267 | |
268 | enum { CallFunction, ApplyFunction }; | |
269 | ||
270 | bool isConstructor() const { return m_isConstructor; } | |
271 | bool isStrictMode() const { return m_isStrictMode; } | |
272 | bool usesEval() const { return m_usesEval; } | |
273 | ||
274 | bool needsFullScopeChain() const { return m_needsFullScopeChain; } | |
93a37866 A |
275 | |
276 | void addExpressionInfo(unsigned instructionOffset, int divot, | |
277 | int startOffset, int endOffset, unsigned line, unsigned column); | |
278 | ||
ed1e77d3 A |
279 | void addTypeProfilerExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot); |
280 | ||
93a37866 A |
281 | bool hasExpressionInfo() { return m_expressionInfo.size(); } |
282 | ||
283 | // Special registers | |
81345200 | 284 | void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; } |
ed1e77d3 A |
285 | void setScopeRegister(VirtualRegister scopeRegister) { m_scopeRegister = scopeRegister; } |
286 | void setActivationRegister(VirtualRegister activationRegister) { m_lexicalEnvironmentRegister = activationRegister; } | |
93a37866 | 287 | |
81345200 A |
288 | bool usesGlobalObject() const { return m_globalObjectRegister.isValid(); } |
289 | void setGlobalObjectRegister(VirtualRegister globalObjectRegister) { m_globalObjectRegister = globalObjectRegister; } | |
290 | VirtualRegister globalObjectRegister() const { return m_globalObjectRegister; } | |
93a37866 A |
291 | |
292 | // Parameter information | |
293 | void setNumParameters(int newValue) { m_numParameters = newValue; } | |
294 | void addParameter() { m_numParameters++; } | |
295 | unsigned numParameters() const { return m_numParameters; } | |
296 | ||
297 | unsigned addRegExp(RegExp* r) | |
298 | { | |
299 | createRareDataIfNecessary(); | |
300 | unsigned size = m_rareData->m_regexps.size(); | |
301 | m_rareData->m_regexps.append(WriteBarrier<RegExp>(*m_vm, this, r)); | |
302 | return size; | |
303 | } | |
304 | unsigned numberOfRegExps() const | |
305 | { | |
306 | if (!m_rareData) | |
307 | return 0; | |
308 | return m_rareData->m_regexps.size(); | |
309 | } | |
310 | RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); } | |
311 | ||
312 | // Constant Pools | |
313 | ||
314 | size_t numberOfIdentifiers() const { return m_identifiers.size(); } | |
315 | void addIdentifier(const Identifier& i) { return m_identifiers.append(i); } | |
316 | const Identifier& identifier(int index) const { return m_identifiers[index]; } | |
317 | const Vector<Identifier>& identifiers() const { return m_identifiers; } | |
318 | ||
ed1e77d3 | 319 | unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other) |
93a37866 A |
320 | { |
321 | unsigned result = m_constantRegisters.size(); | |
322 | m_constantRegisters.append(WriteBarrier<Unknown>()); | |
323 | m_constantRegisters.last().set(*m_vm, this, v); | |
ed1e77d3 A |
324 | m_constantsSourceCodeRepresentation.append(sourceCodeRepresentation); |
325 | return result; | |
326 | } | |
327 | unsigned addConstant(LinkTimeConstant type) | |
328 | { | |
329 | unsigned result = m_constantRegisters.size(); | |
330 | ASSERT(result); | |
331 | unsigned index = static_cast<unsigned>(type); | |
332 | ASSERT(index < LinkTimeConstantCount); | |
333 | m_linkTimeConstants[index] = result; | |
334 | m_constantRegisters.append(WriteBarrier<Unknown>()); | |
335 | m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other); | |
93a37866 A |
336 | return result; |
337 | } | |
ed1e77d3 A |
338 | unsigned registerIndexForLinkTimeConstant(LinkTimeConstant type) |
339 | { | |
340 | unsigned index = static_cast<unsigned>(type); | |
341 | ASSERT(index < LinkTimeConstantCount); | |
342 | return m_linkTimeConstants[index]; | |
343 | } | |
81345200 | 344 | const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; } |
93a37866 A |
345 | const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; } |
346 | ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; } | |
ed1e77d3 | 347 | const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation() { return m_constantsSourceCodeRepresentation; } |
93a37866 A |
348 | |
349 | // Jumps | |
350 | size_t numberOfJumpTargets() const { return m_jumpTargets.size(); } | |
351 | void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); } | |
352 | unsigned jumpTarget(int index) const { return m_jumpTargets[index]; } | |
353 | unsigned lastJumpTarget() const { return m_jumpTargets.last(); } | |
354 | ||
81345200 | 355 | bool isBuiltinFunction() const { return m_isBuiltinFunction; } |
ed1e77d3 A |
356 | |
357 | ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); } | |
358 | ||
93a37866 A |
359 | void shrinkToFit() |
360 | { | |
361 | m_jumpTargets.shrinkToFit(); | |
362 | m_identifiers.shrinkToFit(); | |
363 | m_constantRegisters.shrinkToFit(); | |
ed1e77d3 | 364 | m_constantsSourceCodeRepresentation.shrinkToFit(); |
93a37866 A |
365 | m_functionDecls.shrinkToFit(); |
366 | m_functionExprs.shrinkToFit(); | |
367 | m_propertyAccessInstructions.shrinkToFit(); | |
368 | m_expressionInfo.shrinkToFit(); | |
369 | ||
370 | #if ENABLE(BYTECODE_COMMENTS) | |
371 | m_bytecodeComments.shrinkToFit(); | |
372 | #endif | |
373 | if (m_rareData) { | |
374 | m_rareData->m_exceptionHandlers.shrinkToFit(); | |
375 | m_rareData->m_regexps.shrinkToFit(); | |
376 | m_rareData->m_constantBuffers.shrinkToFit(); | |
81345200 | 377 | m_rareData->m_switchJumpTables.shrinkToFit(); |
93a37866 A |
378 | m_rareData->m_stringSwitchJumpTables.shrinkToFit(); |
379 | m_rareData->m_expressionInfoFatPositions.shrinkToFit(); | |
380 | } | |
381 | } | |
382 | ||
81345200 A |
383 | void setInstructions(std::unique_ptr<UnlinkedInstructionStream>); |
384 | const UnlinkedInstructionStream& instructions() const; | |
93a37866 A |
385 | |
386 | int m_numVars; | |
387 | int m_numCapturedVars; | |
388 | int m_numCalleeRegisters; | |
389 | ||
390 | // Jump Tables | |
391 | ||
81345200 A |
392 | size_t numberOfSwitchJumpTables() const { return m_rareData ? m_rareData->m_switchJumpTables.size() : 0; } |
393 | UnlinkedSimpleJumpTable& addSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_switchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_switchJumpTables.last(); } | |
394 | UnlinkedSimpleJumpTable& switchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_switchJumpTables[tableIndex]; } | |
93a37866 A |
395 | |
396 | size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; } | |
397 | UnlinkedStringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(UnlinkedStringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); } | |
398 | UnlinkedStringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; } | |
399 | ||
400 | unsigned addFunctionDecl(UnlinkedFunctionExecutable* n) | |
401 | { | |
402 | unsigned size = m_functionDecls.size(); | |
403 | m_functionDecls.append(WriteBarrier<UnlinkedFunctionExecutable>()); | |
404 | m_functionDecls.last().set(*m_vm, this, n); | |
405 | return size; | |
406 | } | |
407 | UnlinkedFunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); } | |
408 | size_t numberOfFunctionDecls() { return m_functionDecls.size(); } | |
409 | unsigned addFunctionExpr(UnlinkedFunctionExecutable* n) | |
410 | { | |
411 | unsigned size = m_functionExprs.size(); | |
412 | m_functionExprs.append(WriteBarrier<UnlinkedFunctionExecutable>()); | |
413 | m_functionExprs.last().set(*m_vm, this, n); | |
414 | return size; | |
415 | } | |
416 | UnlinkedFunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); } | |
417 | size_t numberOfFunctionExprs() { return m_functionExprs.size(); } | |
418 | ||
419 | // Exception handling support | |
420 | size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; } | |
ed1e77d3 | 421 | void addExceptionHandler(const UnlinkedHandlerInfo& handler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(handler); } |
93a37866 A |
422 | UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; } |
423 | ||
81345200 A |
424 | SymbolTable* symbolTable() const { return m_symbolTable.get(); } |
425 | void setSymbolTable(SymbolTable* table) { m_symbolTable.set(*m_vm, this, table); } | |
93a37866 A |
426 | |
427 | VM* vm() const { return m_vm; } | |
428 | ||
93a37866 A |
429 | UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; } |
430 | unsigned numberOfArrayProfiles() { return m_arrayProfileCount; } | |
431 | UnlinkedArrayAllocationProfile addArrayAllocationProfile() { return m_arrayAllocationProfileCount++; } | |
432 | unsigned numberOfArrayAllocationProfiles() { return m_arrayAllocationProfileCount; } | |
433 | UnlinkedObjectAllocationProfile addObjectAllocationProfile() { return m_objectAllocationProfileCount++; } | |
434 | unsigned numberOfObjectAllocationProfiles() { return m_objectAllocationProfileCount; } | |
435 | UnlinkedValueProfile addValueProfile() { return m_valueProfileCount++; } | |
436 | unsigned numberOfValueProfiles() { return m_valueProfileCount; } | |
437 | ||
438 | UnlinkedLLIntCallLinkInfo addLLIntCallLinkInfo() { return m_llintCallLinkInfoCount++; } | |
439 | unsigned numberOfLLintCallLinkInfos() { return m_llintCallLinkInfoCount; } | |
440 | ||
441 | CodeType codeType() const { return m_codeType; } | |
442 | ||
81345200 | 443 | VirtualRegister thisRegister() const { return m_thisRegister; } |
ed1e77d3 A |
444 | VirtualRegister scopeRegister() const { return m_scopeRegister; } |
445 | VirtualRegister activationRegister() const { return m_lexicalEnvironmentRegister; } | |
446 | bool hasActivationRegister() const { return m_lexicalEnvironmentRegister.isValid(); } | |
93a37866 A |
447 | |
448 | void addPropertyAccessInstruction(unsigned propertyAccessInstruction) | |
449 | { | |
450 | m_propertyAccessInstructions.append(propertyAccessInstruction); | |
451 | } | |
452 | ||
453 | size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); } | |
454 | const Vector<unsigned>& propertyAccessInstructions() const { return m_propertyAccessInstructions; } | |
455 | ||
456 | typedef Vector<JSValue> ConstantBuffer; | |
457 | ||
458 | size_t constantBufferCount() { ASSERT(m_rareData); return m_rareData->m_constantBuffers.size(); } | |
459 | unsigned addConstantBuffer(unsigned length) | |
460 | { | |
461 | createRareDataIfNecessary(); | |
462 | unsigned size = m_rareData->m_constantBuffers.size(); | |
463 | m_rareData->m_constantBuffers.append(Vector<JSValue>(length)); | |
464 | return size; | |
465 | } | |
466 | ||
467 | const ConstantBuffer& constantBuffer(unsigned index) const | |
468 | { | |
469 | ASSERT(m_rareData); | |
470 | return m_rareData->m_constantBuffers[index]; | |
471 | } | |
472 | ||
473 | ConstantBuffer& constantBuffer(unsigned index) | |
474 | { | |
475 | ASSERT(m_rareData); | |
476 | return m_rareData->m_constantBuffers[index]; | |
477 | } | |
478 | ||
ed1e77d3 | 479 | bool hasRareData() const { return m_rareData.get(); } |
93a37866 A |
480 | |
481 | int lineNumberForBytecodeOffset(unsigned bytecodeOffset); | |
482 | ||
483 | void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, | |
484 | int& startOffset, int& endOffset, unsigned& line, unsigned& column); | |
485 | ||
ed1e77d3 A |
486 | bool typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot); |
487 | ||
81345200 | 488 | void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount, unsigned endColumn) |
93a37866 A |
489 | { |
490 | m_features = features; | |
491 | m_hasCapturedVariables = hasCapturedVariables; | |
492 | m_firstLine = firstLine; | |
493 | m_lineCount = lineCount; | |
81345200 A |
494 | // For the UnlinkedCodeBlock, startColumn is always 0. |
495 | m_endColumn = endColumn; | |
93a37866 A |
496 | } |
497 | ||
498 | CodeFeatures codeFeatures() const { return m_features; } | |
499 | bool hasCapturedVariables() const { return m_hasCapturedVariables; } | |
500 | unsigned firstLine() const { return m_firstLine; } | |
501 | unsigned lineCount() const { return m_lineCount; } | |
81345200 A |
502 | ALWAYS_INLINE unsigned startColumn() const { return 0; } |
503 | unsigned endColumn() const { return m_endColumn; } | |
93a37866 | 504 | |
ed1e77d3 A |
505 | void addOpProfileControlFlowBytecodeOffset(size_t offset) { m_opProfileControlFlowBytecodeOffsets.append(offset); } |
506 | const Vector<size_t>& opProfileControlFlowBytecodeOffsets() const { return m_opProfileControlFlowBytecodeOffsets; } | |
507 | ||
81345200 | 508 | void dumpExpressionRangeInfo(); // For debugging purpose only. |
93a37866 A |
509 | |
510 | protected: | |
511 | UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&); | |
512 | ~UnlinkedCodeBlock(); | |
513 | ||
514 | void finishCreation(VM& vm) | |
515 | { | |
516 | Base::finishCreation(vm); | |
517 | if (codeType() == GlobalCode) | |
518 | return; | |
81345200 | 519 | m_symbolTable.set(vm, this, SymbolTable::create(vm)); |
93a37866 A |
520 | } |
521 | ||
522 | private: | |
523 | ||
524 | void createRareDataIfNecessary() | |
525 | { | |
526 | if (!m_rareData) | |
ed1e77d3 | 527 | m_rareData = std::make_unique<RareData>(); |
93a37866 A |
528 | } |
529 | ||
81345200 A |
530 | void getLineAndColumn(ExpressionRangeInfo&, unsigned& line, unsigned& column); |
531 | ||
532 | std::unique_ptr<UnlinkedInstructionStream> m_unlinkedInstructions; | |
93a37866 A |
533 | |
534 | int m_numParameters; | |
535 | VM* m_vm; | |
536 | ||
81345200 | 537 | VirtualRegister m_thisRegister; |
ed1e77d3 A |
538 | VirtualRegister m_scopeRegister; |
539 | VirtualRegister m_lexicalEnvironmentRegister; | |
81345200 | 540 | VirtualRegister m_globalObjectRegister; |
93a37866 | 541 | |
ed1e77d3 A |
542 | unsigned m_needsFullScopeChain : 1; |
543 | unsigned m_usesEval : 1; | |
544 | unsigned m_isStrictMode : 1; | |
545 | unsigned m_isConstructor : 1; | |
546 | unsigned m_hasCapturedVariables : 1; | |
547 | unsigned m_isBuiltinFunction : 1; | |
548 | unsigned m_constructorKind : 2; | |
549 | ||
93a37866 A |
550 | unsigned m_firstLine; |
551 | unsigned m_lineCount; | |
81345200 | 552 | unsigned m_endColumn; |
93a37866 A |
553 | |
554 | CodeFeatures m_features; | |
555 | CodeType m_codeType; | |
556 | ||
557 | Vector<unsigned> m_jumpTargets; | |
558 | ||
559 | // Constant Pools | |
560 | Vector<Identifier> m_identifiers; | |
81345200 | 561 | Vector<WriteBarrier<Unknown>> m_constantRegisters; |
ed1e77d3 A |
562 | Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation; |
563 | std::array<unsigned, LinkTimeConstantCount> m_linkTimeConstants; | |
81345200 | 564 | typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector; |
93a37866 A |
565 | FunctionExpressionVector m_functionDecls; |
566 | FunctionExpressionVector m_functionExprs; | |
567 | ||
81345200 | 568 | WriteBarrier<SymbolTable> m_symbolTable; |
93a37866 A |
569 | |
570 | Vector<unsigned> m_propertyAccessInstructions; | |
571 | ||
572 | #if ENABLE(BYTECODE_COMMENTS) | |
573 | Vector<Comment> m_bytecodeComments; | |
574 | size_t m_bytecodeCommentIterator; | |
575 | #endif | |
576 | ||
93a37866 A |
577 | unsigned m_arrayProfileCount; |
578 | unsigned m_arrayAllocationProfileCount; | |
579 | unsigned m_objectAllocationProfileCount; | |
580 | unsigned m_valueProfileCount; | |
581 | unsigned m_llintCallLinkInfoCount; | |
582 | ||
583 | public: | |
584 | struct RareData { | |
585 | WTF_MAKE_FAST_ALLOCATED; | |
586 | public: | |
587 | Vector<UnlinkedHandlerInfo> m_exceptionHandlers; | |
588 | ||
589 | // Rare Constants | |
81345200 | 590 | Vector<WriteBarrier<RegExp>> m_regexps; |
93a37866 A |
591 | |
592 | // Buffers used for large array literals | |
593 | Vector<ConstantBuffer> m_constantBuffers; | |
594 | ||
595 | // Jump Tables | |
81345200 | 596 | Vector<UnlinkedSimpleJumpTable> m_switchJumpTables; |
93a37866 | 597 | Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables; |
93a37866 A |
598 | |
599 | Vector<ExpressionRangeInfo::FatPosition> m_expressionInfoFatPositions; | |
600 | }; | |
601 | ||
602 | private: | |
ed1e77d3 | 603 | std::unique_ptr<RareData> m_rareData; |
93a37866 | 604 | Vector<ExpressionRangeInfo> m_expressionInfo; |
ed1e77d3 A |
605 | struct TypeProfilerExpressionRange { |
606 | unsigned m_startDivot; | |
607 | unsigned m_endDivot; | |
608 | }; | |
609 | HashMap<unsigned, TypeProfilerExpressionRange> m_typeProfilerInfoMap; | |
610 | Vector<size_t> m_opProfileControlFlowBytecodeOffsets; | |
93a37866 A |
611 | |
612 | protected: | |
93a37866 A |
613 | static void visitChildren(JSCell*, SlotVisitor&); |
614 | ||
615 | public: | |
81345200 | 616 | DECLARE_INFO; |
93a37866 A |
617 | }; |
618 | ||
619 | class UnlinkedGlobalCodeBlock : public UnlinkedCodeBlock { | |
620 | public: | |
621 | typedef UnlinkedCodeBlock Base; | |
622 | ||
623 | protected: | |
624 | UnlinkedGlobalCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info) | |
625 | : Base(vm, structure, codeType, info) | |
626 | { | |
627 | } | |
628 | ||
81345200 | 629 | DECLARE_INFO; |
93a37866 A |
630 | }; |
631 | ||
ed1e77d3 | 632 | class UnlinkedProgramCodeBlock final : public UnlinkedGlobalCodeBlock { |
93a37866 A |
633 | private: |
634 | friend class CodeCache; | |
635 | static UnlinkedProgramCodeBlock* create(VM* vm, const ExecutableInfo& info) | |
636 | { | |
637 | UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedProgramCodeBlock>(vm->heap)) UnlinkedProgramCodeBlock(vm, vm->unlinkedProgramCodeBlockStructure.get(), info); | |
638 | instance->finishCreation(*vm); | |
639 | return instance; | |
640 | } | |
641 | ||
642 | public: | |
643 | typedef UnlinkedGlobalCodeBlock Base; | |
ed1e77d3 | 644 | static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; |
93a37866 | 645 | |
ed1e77d3 | 646 | static void destroy(JSCell*); |
93a37866 A |
647 | |
648 | void addVariableDeclaration(const Identifier& name, bool isConstant) | |
649 | { | |
650 | m_varDeclarations.append(std::make_pair(name, isConstant)); | |
651 | } | |
652 | ||
81345200 | 653 | typedef Vector<std::pair<Identifier, bool>> VariableDeclations; |
93a37866 A |
654 | |
655 | const VariableDeclations& variableDeclarations() const { return m_varDeclarations; } | |
93a37866 A |
656 | |
657 | static void visitChildren(JSCell*, SlotVisitor&); | |
658 | ||
659 | private: | |
660 | UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info) | |
661 | : Base(vm, structure, GlobalCode, info) | |
662 | { | |
663 | } | |
664 | ||
665 | VariableDeclations m_varDeclarations; | |
93a37866 A |
666 | |
667 | public: | |
668 | static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) | |
669 | { | |
81345200 | 670 | return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedProgramCodeBlockType, StructureFlags), info()); |
93a37866 A |
671 | } |
672 | ||
81345200 | 673 | DECLARE_INFO; |
93a37866 A |
674 | }; |
675 | ||
ed1e77d3 | 676 | class UnlinkedEvalCodeBlock final : public UnlinkedGlobalCodeBlock { |
93a37866 A |
677 | private: |
678 | friend class CodeCache; | |
679 | ||
680 | static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo& info) | |
681 | { | |
682 | UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell<UnlinkedEvalCodeBlock>(vm->heap)) UnlinkedEvalCodeBlock(vm, vm->unlinkedEvalCodeBlockStructure.get(), info); | |
683 | instance->finishCreation(*vm); | |
684 | return instance; | |
685 | } | |
686 | ||
687 | public: | |
688 | typedef UnlinkedGlobalCodeBlock Base; | |
ed1e77d3 A |
689 | static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; |
690 | ||
93a37866 A |
691 | static void destroy(JSCell*); |
692 | ||
693 | const Identifier& variable(unsigned index) { return m_variables[index]; } | |
694 | unsigned numVariables() { return m_variables.size(); } | |
695 | void adoptVariables(Vector<Identifier, 0, UnsafeVectorOverflow>& variables) | |
696 | { | |
697 | ASSERT(m_variables.isEmpty()); | |
698 | m_variables.swap(variables); | |
699 | } | |
700 | ||
701 | private: | |
702 | UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info) | |
703 | : Base(vm, structure, EvalCode, info) | |
704 | { | |
705 | } | |
706 | ||
707 | Vector<Identifier, 0, UnsafeVectorOverflow> m_variables; | |
708 | ||
709 | public: | |
710 | static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) | |
711 | { | |
81345200 | 712 | return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedEvalCodeBlockType, StructureFlags), info()); |
93a37866 A |
713 | } |
714 | ||
81345200 | 715 | DECLARE_INFO; |
93a37866 A |
716 | }; |
717 | ||
ed1e77d3 | 718 | class UnlinkedFunctionCodeBlock final : public UnlinkedCodeBlock { |
93a37866 | 719 | public: |
ed1e77d3 A |
720 | typedef UnlinkedCodeBlock Base; |
721 | static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; | |
722 | ||
93a37866 A |
723 | static UnlinkedFunctionCodeBlock* create(VM* vm, CodeType codeType, const ExecutableInfo& info) |
724 | { | |
725 | UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell<UnlinkedFunctionCodeBlock>(vm->heap)) UnlinkedFunctionCodeBlock(vm, vm->unlinkedFunctionCodeBlockStructure.get(), codeType, info); | |
726 | instance->finishCreation(*vm); | |
727 | return instance; | |
728 | } | |
729 | ||
93a37866 A |
730 | static void destroy(JSCell*); |
731 | ||
732 | private: | |
733 | UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info) | |
734 | : Base(vm, structure, codeType, info) | |
735 | { | |
736 | } | |
737 | ||
738 | public: | |
739 | static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) | |
740 | { | |
81345200 | 741 | return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionCodeBlockType, StructureFlags), info()); |
93a37866 A |
742 | } |
743 | ||
81345200 | 744 | DECLARE_INFO; |
93a37866 A |
745 | }; |
746 | ||
747 | } | |
748 | ||
749 | #endif // UnlinkedCodeBlock_h |