Shrink-wrap UnlinkedCodeBlock members.
[WebKit-https.git] / Source / JavaScriptCore / bytecode / UnlinkedCodeBlock.cpp
1 /*
2  * Copyright (C) 2012 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 #include "config.h"
27
28 #include "UnlinkedCodeBlock.h"
29
30 #include "BytecodeGenerator.h"
31 #include "ClassInfo.h"
32 #include "CodeCache.h"
33 #include "Executable.h"
34 #include "JSString.h"
35 #include "Operations.h"
36 #include "SourceProvider.h"
37 #include "Structure.h"
38 #include "SymbolTable.h"
39
40 namespace JSC {
41
42 const ClassInfo UnlinkedFunctionExecutable::s_info = { "UnlinkedFunctionExecutable", 0, 0, 0, CREATE_METHOD_TABLE(UnlinkedFunctionExecutable) };
43 const ClassInfo UnlinkedCodeBlock::s_info = { "UnlinkedCodeBlock", 0, 0, 0, CREATE_METHOD_TABLE(UnlinkedCodeBlock) };
44 const ClassInfo UnlinkedGlobalCodeBlock::s_info = { "UnlinkedGlobalCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedGlobalCodeBlock) };
45 const ClassInfo UnlinkedProgramCodeBlock::s_info = { "UnlinkedProgramCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedProgramCodeBlock) };
46 const ClassInfo UnlinkedEvalCodeBlock::s_info = { "UnlinkedEvalCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedEvalCodeBlock) };
47 const ClassInfo UnlinkedFunctionCodeBlock::s_info = { "UnlinkedFunctionCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedFunctionCodeBlock) };
48
49 unsigned UnlinkedCodeBlock::addOrFindConstant(JSValue v)
50 {
51     unsigned numberOfConstants = numberOfConstantRegisters();
52     for (unsigned i = 0; i < numberOfConstants; ++i) {
53         if (getConstant(FirstConstantRegisterIndex + i) == v)
54             return i;
55     }
56     return addConstant(v);
57 }
58
59 UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(JSGlobalData* globalData, Structure* structure, const SourceCode& source, FunctionBodyNode* node)
60     : Base(*globalData, structure)
61     , m_numCapturedVariables(node->capturedVariableCount())
62     , m_forceUsesArguments(node->usesArguments())
63     , m_isInStrictContext(node->isStrictMode())
64     , m_hasCapturedVariables(node->hasCapturedVariables())
65     , m_name(node->ident())
66     , m_inferredName(node->inferredName())
67     , m_parameters(node->parameters())
68     , m_firstLineOffset(node->firstLine() - source.firstLine())
69     , m_lineCount(node->lastLine() - node->firstLine())
70     , m_functionStartOffset(node->functionStart() - source.startOffset())
71     , m_startOffset(node->source().startOffset() - source.startOffset())
72     , m_sourceLength(node->source().length())
73     , m_features(node->features())
74     , m_functionNameIsInScopeToggle(node->functionNameIsInScopeToggle())
75 {
76 }
77
78 void UnlinkedFunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
79 {
80     UnlinkedFunctionExecutable* thisObject = jsCast<UnlinkedFunctionExecutable*>(cell);
81     ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
82     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
83     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
84     Base::visitChildren(thisObject, visitor);
85     visitor.append(&thisObject->m_nameValue);
86     visitor.append(&thisObject->m_symbolTableForCall);
87     visitor.append(&thisObject->m_symbolTableForConstruct);
88 }
89
90 FunctionExecutable* UnlinkedFunctionExecutable::link(JSGlobalData& globalData, const SourceCode& source, size_t lineOffset, size_t sourceOffset)
91 {
92     unsigned firstLine = lineOffset + m_firstLineOffset;
93     unsigned startOffset = sourceOffset + m_startOffset;
94     SourceCode code(source.provider(), startOffset, startOffset + m_sourceLength, firstLine);
95     return FunctionExecutable::create(globalData, code, this, firstLine, firstLine + m_lineCount);
96 }
97
98 UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger*, const SourceCode& source, JSObject** exception)
99 {
100     ParserError error;
101     CodeCache* codeCache = exec->globalData().codeCache();
102     UnlinkedFunctionExecutable* executable = codeCache->getFunctionExecutableFromGlobalCode(exec->globalData(), name, source, error);
103     if (error.m_type != ParserError::ErrorNone) {
104         *exception = error.toErrorObject(exec->lexicalGlobalObject(), source);
105         return 0;
106     }
107
108     return executable;
109 }
110
111 UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::codeBlockFor(JSGlobalData& globalData, const SourceCode& source, CodeSpecializationKind specializationKind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
112 {
113     switch (specializationKind) {
114     case CodeForCall:
115         if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForCall.get()) {
116             globalData.codeCache()->usedFunctionCode(globalData, codeBlock);
117             return codeBlock;
118         }
119         break;
120     case CodeForConstruct:
121         if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForConstruct.get()) {
122             globalData.codeCache()->usedFunctionCode(globalData, codeBlock);
123             return codeBlock;
124         }
125         break;
126     }
127
128     UnlinkedFunctionCodeBlock* result = globalData.codeCache()->getFunctionCodeBlock(globalData, this, source, specializationKind, debuggerMode, profilerMode, error);
129     
130     if (error.m_type != ParserError::ErrorNone)
131         return 0;
132
133     switch (specializationKind) {
134     case CodeForCall:
135         m_codeBlockForCall = PassWeak<UnlinkedFunctionCodeBlock>(result);
136         m_symbolTableForCall.set(globalData, this, result->symbolTable());
137         break;
138     case CodeForConstruct:
139         m_codeBlockForConstruct = PassWeak<UnlinkedFunctionCodeBlock>(result);
140         m_symbolTableForConstruct.set(globalData, this, result->symbolTable());
141         break;
142     }
143     return result;
144 }
145
146 String UnlinkedFunctionExecutable::paramString() const
147 {
148     FunctionParameters& parameters = *m_parameters;
149     StringBuilder builder;
150     for (size_t pos = 0; pos < parameters.size(); ++pos) {
151         if (!builder.isEmpty())
152             builder.appendLiteral(", ");
153         builder.append(parameters.at(pos).string());
154     }
155     return builder.toString();
156 }
157
158 UnlinkedCodeBlock::UnlinkedCodeBlock(JSGlobalData* globalData, Structure* structure, CodeType codeType, const ExecutableInfo& info)
159     : Base(*globalData, structure)
160     , m_numVars(0)
161     , m_numCalleeRegisters(0)
162     , m_numParameters(0)
163     , m_argumentsRegister(-1)
164     , m_needsFullScopeChain(info.m_needsActivation)
165     , m_usesEval(info.m_usesEval)
166     , m_isNumericCompareFunction(false)
167     , m_isStrictMode(info.m_isStrictMode)
168     , m_isConstructor(info.m_isConstructor)
169     , m_hasCapturedVariables(false)
170     , m_codeType(codeType)
171     , m_features(0)
172     , m_firstLine(0)
173     , m_lineCount(0)
174     , m_resolveOperationCount(0)
175     , m_putToBaseOperationCount(1)
176     , m_arrayProfileCount(0)
177     , m_arrayAllocationProfileCount(0)
178     , m_objectAllocationProfileCount(0)
179     , m_valueProfileCount(0)
180     , m_llintCallLinkInfoCount(0)
181     , m_globalData(globalData)
182 #if ENABLE(BYTECODE_COMMENTS)
183     , m_bytecodeCommentIterator(0)
184 #endif
185 {
186
187 }
188
189 void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
190 {
191     UnlinkedCodeBlock* thisObject = jsCast<UnlinkedCodeBlock*>(cell);
192     ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
193     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
194     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
195     Base::visitChildren(thisObject, visitor);
196     visitor.append(&thisObject->m_symbolTable);
197     for (FunctionExpressionVector::iterator ptr = thisObject->m_functionDecls.begin(), end = thisObject->m_functionDecls.end(); ptr != end; ++ptr)
198         visitor.append(ptr);
199     for (FunctionExpressionVector::iterator ptr = thisObject->m_functionExprs.begin(), end = thisObject->m_functionExprs.end(); ptr != end; ++ptr)
200         visitor.append(ptr);
201     visitor.appendValues(thisObject->m_constantRegisters.data(), thisObject->m_constantRegisters.size());
202     if (thisObject->m_rareData) {
203         for (size_t i = 0, end = thisObject->m_rareData->m_regexps.size(); i != end; i++)
204             visitor.append(&thisObject->m_rareData->m_regexps[i]);
205     }
206 }
207
208 int UnlinkedCodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
209 {
210     ASSERT(bytecodeOffset < instructions().size());
211     Vector<LineInfo>& lineInfo = m_lineInfo;
212     
213     int low = 0;
214     int high = lineInfo.size();
215     while (low < high) {
216         int mid = low + (high - low) / 2;
217         if (lineInfo[mid].instructionOffset <= bytecodeOffset)
218             low = mid + 1;
219         else
220             high = mid;
221     }
222     
223     if (!low)
224         return 0;
225     return lineInfo[low - 1].lineNumber;
226 }
227
228 void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
229 {
230     ASSERT(bytecodeOffset < instructions().size());
231
232     if (!m_expressionInfo.size()) {
233         startOffset = 0;
234         endOffset = 0;
235         divot = 0;
236         return;
237     }
238
239     Vector<ExpressionRangeInfo>& expressionInfo = m_expressionInfo;
240
241     int low = 0;
242     int high = expressionInfo.size();
243     while (low < high) {
244         int mid = low + (high - low) / 2;
245         if (expressionInfo[mid].instructionOffset <= bytecodeOffset)
246             low = mid + 1;
247         else
248             high = mid;
249     }
250
251     ASSERT(low);
252     if (!low) {
253         startOffset = 0;
254         endOffset = 0;
255         divot = 0;
256         return;
257     }
258
259     startOffset = expressionInfo[low - 1].startOffset;
260     endOffset = expressionInfo[low - 1].endOffset;
261     divot = expressionInfo[low - 1].divotPoint;
262 }
263
264 void UnlinkedProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
265 {
266     UnlinkedProgramCodeBlock* thisObject = jsCast<UnlinkedProgramCodeBlock*>(cell);
267     ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
268     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
269     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
270     Base::visitChildren(thisObject, visitor);
271     for (size_t i = 0, end = thisObject->m_functionDeclarations.size(); i != end; i++)
272         visitor.append(&thisObject->m_functionDeclarations[i].second);
273 }
274
275 UnlinkedCodeBlock::~UnlinkedCodeBlock()
276 {
277 }
278
279 void UnlinkedProgramCodeBlock::destroy(JSCell* cell)
280 {
281     jsCast<UnlinkedProgramCodeBlock*>(cell)->~UnlinkedProgramCodeBlock();
282 }
283
284 void UnlinkedEvalCodeBlock::destroy(JSCell* cell)
285 {
286     jsCast<UnlinkedEvalCodeBlock*>(cell)->~UnlinkedEvalCodeBlock();
287 }
288
289 void UnlinkedFunctionCodeBlock::destroy(JSCell* cell)
290 {
291     jsCast<UnlinkedFunctionCodeBlock*>(cell)->~UnlinkedFunctionCodeBlock();
292 }
293
294 void UnlinkedFunctionExecutable::destroy(JSCell* cell)
295 {
296     jsCast<UnlinkedFunctionExecutable*>(cell)->~UnlinkedFunctionExecutable();
297 }
298
299 }
300