UnlinkedCodeBlock.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. /*
  2. * Copyright (C) 2012, 2013 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. #include "config.h"
  26. #include "UnlinkedCodeBlock.h"
  27. #include "BytecodeGenerator.h"
  28. #include "ClassInfo.h"
  29. #include "CodeCache.h"
  30. #include "Executable.h"
  31. #include "JSString.h"
  32. #include "Operations.h"
  33. #include "Parser.h"
  34. #include "SourceProvider.h"
  35. #include "Structure.h"
  36. #include "SymbolTable.h"
  37. namespace JSC {
  38. const ClassInfo UnlinkedFunctionExecutable::s_info = { "UnlinkedFunctionExecutable", 0, 0, 0, CREATE_METHOD_TABLE(UnlinkedFunctionExecutable) };
  39. const ClassInfo UnlinkedCodeBlock::s_info = { "UnlinkedCodeBlock", 0, 0, 0, CREATE_METHOD_TABLE(UnlinkedCodeBlock) };
  40. const ClassInfo UnlinkedGlobalCodeBlock::s_info = { "UnlinkedGlobalCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedGlobalCodeBlock) };
  41. const ClassInfo UnlinkedProgramCodeBlock::s_info = { "UnlinkedProgramCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedProgramCodeBlock) };
  42. const ClassInfo UnlinkedEvalCodeBlock::s_info = { "UnlinkedEvalCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedEvalCodeBlock) };
  43. const ClassInfo UnlinkedFunctionCodeBlock::s_info = { "UnlinkedFunctionCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedFunctionCodeBlock) };
  44. static UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(VM& vm, JSScope* scope, UnlinkedFunctionExecutable* executable, const SourceCode& source, CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
  45. {
  46. RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(&vm, source, executable->parameters(), executable->name(), executable->isInStrictContext() ? JSParseStrict : JSParseNormal, JSParseFunctionCode, error);
  47. if (!body) {
  48. ASSERT(error.m_type != ParserError::ErrorNone);
  49. return 0;
  50. }
  51. if (executable->forceUsesArguments())
  52. body->setUsesArguments();
  53. body->finishParsing(executable->parameters(), executable->name(), executable->functionNameIsInScopeToggle());
  54. executable->recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
  55. UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, ExecutableInfo(body->needsActivation(), body->usesEval(), body->isStrictMode(), kind == CodeForConstruct));
  56. OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(vm, scope, body.get(), result, debuggerMode, profilerMode)));
  57. error = generator->generate();
  58. body->destroyData();
  59. if (error.m_type != ParserError::ErrorNone)
  60. return 0;
  61. return result;
  62. }
  63. unsigned UnlinkedCodeBlock::addOrFindConstant(JSValue v)
  64. {
  65. unsigned numberOfConstants = numberOfConstantRegisters();
  66. for (unsigned i = 0; i < numberOfConstants; ++i) {
  67. if (getConstant(FirstConstantRegisterIndex + i) == v)
  68. return i;
  69. }
  70. return addConstant(v);
  71. }
  72. UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, FunctionBodyNode* node)
  73. : Base(*vm, structure)
  74. , m_numCapturedVariables(node->capturedVariableCount())
  75. , m_forceUsesArguments(node->usesArguments())
  76. , m_isInStrictContext(node->isStrictMode())
  77. , m_hasCapturedVariables(node->hasCapturedVariables())
  78. , m_name(node->ident())
  79. , m_inferredName(node->inferredName())
  80. , m_parameters(node->parameters())
  81. , m_firstLineOffset(node->firstLine() - source.firstLine())
  82. , m_lineCount(node->lastLine() - node->firstLine())
  83. , m_functionStartOffset(node->functionStart() - source.startOffset())
  84. , m_functionStartColumn(node->startColumn())
  85. , m_startOffset(node->source().startOffset() - source.startOffset())
  86. , m_sourceLength(node->source().length())
  87. , m_features(node->features())
  88. , m_functionNameIsInScopeToggle(node->functionNameIsInScopeToggle())
  89. {
  90. }
  91. size_t UnlinkedFunctionExecutable::parameterCount() const
  92. {
  93. return m_parameters->size();
  94. }
  95. void UnlinkedFunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
  96. {
  97. UnlinkedFunctionExecutable* thisObject = jsCast<UnlinkedFunctionExecutable*>(cell);
  98. ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
  99. COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
  100. ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
  101. Base::visitChildren(thisObject, visitor);
  102. visitor.append(&thisObject->m_codeBlockForCall);
  103. visitor.append(&thisObject->m_codeBlockForConstruct);
  104. visitor.append(&thisObject->m_nameValue);
  105. visitor.append(&thisObject->m_symbolTableForCall);
  106. visitor.append(&thisObject->m_symbolTableForConstruct);
  107. }
  108. FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& source, size_t lineOffset, size_t sourceOffset)
  109. {
  110. unsigned firstLine = lineOffset + m_firstLineOffset;
  111. unsigned startOffset = sourceOffset + m_startOffset;
  112. unsigned startColumn = m_functionStartColumn + 1; // startColumn should start from 1, not 0.
  113. SourceCode code(source.provider(), startOffset, startOffset + m_sourceLength, firstLine, startColumn);
  114. return FunctionExecutable::create(vm, code, this, firstLine, firstLine + m_lineCount, startColumn);
  115. }
  116. UnlinkedFunctionExecutable* UnlinkedFunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger*, const SourceCode& source, JSObject** exception)
  117. {
  118. ParserError error;
  119. CodeCache* codeCache = exec->vm().codeCache();
  120. UnlinkedFunctionExecutable* executable = codeCache->getFunctionExecutableFromGlobalCode(exec->vm(), name, source, error);
  121. if (exec->lexicalGlobalObject()->hasDebugger())
  122. exec->lexicalGlobalObject()->debugger()->sourceParsed(exec, source.provider(), error.m_line, error.m_message);
  123. if (error.m_type != ParserError::ErrorNone) {
  124. *exception = error.toErrorObject(exec->lexicalGlobalObject(), source);
  125. return 0;
  126. }
  127. return executable;
  128. }
  129. UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::codeBlockFor(VM& vm, JSScope* scope, const SourceCode& source, CodeSpecializationKind specializationKind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
  130. {
  131. switch (specializationKind) {
  132. case CodeForCall:
  133. if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForCall.get())
  134. return codeBlock;
  135. break;
  136. case CodeForConstruct:
  137. if (UnlinkedFunctionCodeBlock* codeBlock = m_codeBlockForConstruct.get())
  138. return codeBlock;
  139. break;
  140. }
  141. UnlinkedFunctionCodeBlock* result = generateFunctionCodeBlock(vm, scope, this, source, specializationKind, debuggerMode, profilerMode, error);
  142. if (error.m_type != ParserError::ErrorNone)
  143. return 0;
  144. switch (specializationKind) {
  145. case CodeForCall:
  146. m_codeBlockForCall.set(vm, this, result);
  147. m_symbolTableForCall.set(vm, this, result->symbolTable());
  148. break;
  149. case CodeForConstruct:
  150. m_codeBlockForConstruct.set(vm, this, result);
  151. m_symbolTableForConstruct.set(vm, this, result->symbolTable());
  152. break;
  153. }
  154. return result;
  155. }
  156. String UnlinkedFunctionExecutable::paramString() const
  157. {
  158. FunctionParameters& parameters = *m_parameters;
  159. StringBuilder builder;
  160. for (size_t pos = 0; pos < parameters.size(); ++pos) {
  161. if (!builder.isEmpty())
  162. builder.appendLiteral(", ");
  163. builder.append(parameters.at(pos).string());
  164. }
  165. return builder.toString();
  166. }
  167. UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
  168. : Base(*vm, structure)
  169. , m_numVars(0)
  170. , m_numCalleeRegisters(0)
  171. , m_numParameters(0)
  172. , m_vm(vm)
  173. , m_argumentsRegister(-1)
  174. , m_globalObjectRegister(-1)
  175. , m_needsFullScopeChain(info.m_needsActivation)
  176. , m_usesEval(info.m_usesEval)
  177. , m_isNumericCompareFunction(false)
  178. , m_isStrictMode(info.m_isStrictMode)
  179. , m_isConstructor(info.m_isConstructor)
  180. , m_hasCapturedVariables(false)
  181. , m_firstLine(0)
  182. , m_lineCount(0)
  183. , m_features(0)
  184. , m_codeType(codeType)
  185. , m_resolveOperationCount(0)
  186. , m_putToBaseOperationCount(1)
  187. , m_arrayProfileCount(0)
  188. , m_arrayAllocationProfileCount(0)
  189. , m_objectAllocationProfileCount(0)
  190. , m_valueProfileCount(0)
  191. , m_llintCallLinkInfoCount(0)
  192. #if ENABLE(BYTECODE_COMMENTS)
  193. , m_bytecodeCommentIterator(0)
  194. #endif
  195. {
  196. }
  197. void UnlinkedCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
  198. {
  199. UnlinkedCodeBlock* thisObject = jsCast<UnlinkedCodeBlock*>(cell);
  200. ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
  201. COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
  202. ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
  203. Base::visitChildren(thisObject, visitor);
  204. visitor.append(&thisObject->m_symbolTable);
  205. for (FunctionExpressionVector::iterator ptr = thisObject->m_functionDecls.begin(), end = thisObject->m_functionDecls.end(); ptr != end; ++ptr)
  206. visitor.append(ptr);
  207. for (FunctionExpressionVector::iterator ptr = thisObject->m_functionExprs.begin(), end = thisObject->m_functionExprs.end(); ptr != end; ++ptr)
  208. visitor.append(ptr);
  209. visitor.appendValues(thisObject->m_constantRegisters.data(), thisObject->m_constantRegisters.size());
  210. if (thisObject->m_rareData) {
  211. for (size_t i = 0, end = thisObject->m_rareData->m_regexps.size(); i != end; i++)
  212. visitor.append(&thisObject->m_rareData->m_regexps[i]);
  213. }
  214. }
  215. int UnlinkedCodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
  216. {
  217. ASSERT(bytecodeOffset < instructions().size());
  218. int divot;
  219. int startOffset;
  220. int endOffset;
  221. unsigned line;
  222. unsigned column;
  223. expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
  224. return line;
  225. }
  226. void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset,
  227. int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
  228. {
  229. ASSERT(bytecodeOffset < instructions().size());
  230. if (!m_expressionInfo.size()) {
  231. startOffset = 0;
  232. endOffset = 0;
  233. divot = 0;
  234. line = 0;
  235. column = 0;
  236. return;
  237. }
  238. Vector<ExpressionRangeInfo>& expressionInfo = m_expressionInfo;
  239. int low = 0;
  240. int high = expressionInfo.size();
  241. while (low < high) {
  242. int mid = low + (high - low) / 2;
  243. if (expressionInfo[mid].instructionOffset <= bytecodeOffset)
  244. low = mid + 1;
  245. else
  246. high = mid;
  247. }
  248. if (!low)
  249. low = 1;
  250. ExpressionRangeInfo& info = expressionInfo[low - 1];
  251. startOffset = info.startOffset;
  252. endOffset = info.endOffset;
  253. divot = info.divotPoint;
  254. switch (info.mode) {
  255. case ExpressionRangeInfo::FatLineMode:
  256. info.decodeFatLineMode(line, column);
  257. break;
  258. case ExpressionRangeInfo::FatColumnMode:
  259. info.decodeFatColumnMode(line, column);
  260. break;
  261. case ExpressionRangeInfo::FatLineAndColumnMode: {
  262. unsigned fatIndex = info.position;
  263. ExpressionRangeInfo::FatPosition& fatPos = m_rareData->m_expressionInfoFatPositions[fatIndex];
  264. line = fatPos.line;
  265. column = fatPos.column;
  266. break;
  267. }
  268. } // switch
  269. }
  270. void UnlinkedCodeBlock::addExpressionInfo(unsigned instructionOffset,
  271. int divot, int startOffset, int endOffset, unsigned line, unsigned column)
  272. {
  273. if (divot > ExpressionRangeInfo::MaxDivot) {
  274. // Overflow has occurred, we can only give line number info for errors for this region
  275. divot = 0;
  276. startOffset = 0;
  277. endOffset = 0;
  278. } else if (startOffset > ExpressionRangeInfo::MaxOffset) {
  279. // If the start offset is out of bounds we clear both offsets
  280. // so we only get the divot marker. Error message will have to be reduced
  281. // to line and charPosition number.
  282. startOffset = 0;
  283. endOffset = 0;
  284. } else if (endOffset > ExpressionRangeInfo::MaxOffset) {
  285. // The end offset is only used for additional context, and is much more likely
  286. // to overflow (eg. function call arguments) so we are willing to drop it without
  287. // dropping the rest of the range.
  288. endOffset = 0;
  289. }
  290. unsigned positionMode =
  291. (line <= ExpressionRangeInfo::MaxFatLineModeLine && column <= ExpressionRangeInfo::MaxFatLineModeColumn)
  292. ? ExpressionRangeInfo::FatLineMode
  293. : (line <= ExpressionRangeInfo::MaxFatColumnModeLine && column <= ExpressionRangeInfo::MaxFatColumnModeColumn)
  294. ? ExpressionRangeInfo::FatColumnMode
  295. : ExpressionRangeInfo::FatLineAndColumnMode;
  296. ExpressionRangeInfo info;
  297. info.instructionOffset = instructionOffset;
  298. info.divotPoint = divot;
  299. info.startOffset = startOffset;
  300. info.endOffset = endOffset;
  301. info.mode = positionMode;
  302. switch (positionMode) {
  303. case ExpressionRangeInfo::FatLineMode:
  304. info.encodeFatLineMode(line, column);
  305. break;
  306. case ExpressionRangeInfo::FatColumnMode:
  307. info.encodeFatColumnMode(line, column);
  308. break;
  309. case ExpressionRangeInfo::FatLineAndColumnMode: {
  310. createRareDataIfNecessary();
  311. unsigned fatIndex = m_rareData->m_expressionInfoFatPositions.size();
  312. ExpressionRangeInfo::FatPosition fatPos = { line, column };
  313. m_rareData->m_expressionInfoFatPositions.append(fatPos);
  314. info.position = fatIndex;
  315. }
  316. } // switch
  317. m_expressionInfo.append(info);
  318. }
  319. void UnlinkedProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
  320. {
  321. UnlinkedProgramCodeBlock* thisObject = jsCast<UnlinkedProgramCodeBlock*>(cell);
  322. ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
  323. COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
  324. ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
  325. Base::visitChildren(thisObject, visitor);
  326. for (size_t i = 0, end = thisObject->m_functionDeclarations.size(); i != end; i++)
  327. visitor.append(&thisObject->m_functionDeclarations[i].second);
  328. }
  329. UnlinkedCodeBlock::~UnlinkedCodeBlock()
  330. {
  331. }
  332. void UnlinkedProgramCodeBlock::destroy(JSCell* cell)
  333. {
  334. jsCast<UnlinkedProgramCodeBlock*>(cell)->~UnlinkedProgramCodeBlock();
  335. }
  336. void UnlinkedEvalCodeBlock::destroy(JSCell* cell)
  337. {
  338. jsCast<UnlinkedEvalCodeBlock*>(cell)->~UnlinkedEvalCodeBlock();
  339. }
  340. void UnlinkedFunctionCodeBlock::destroy(JSCell* cell)
  341. {
  342. jsCast<UnlinkedFunctionCodeBlock*>(cell)->~UnlinkedFunctionCodeBlock();
  343. }
  344. void UnlinkedFunctionExecutable::destroy(JSCell* cell)
  345. {
  346. jsCast<UnlinkedFunctionExecutable*>(cell)->~UnlinkedFunctionExecutable();
  347. }
  348. }