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