1/* 2 * Copyright (C) 2012, 2013, 2014 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#ifndef UnlinkedCodeBlock_h 27#define UnlinkedCodeBlock_h 28 29#include "BytecodeConventions.h" 30#include "CodeSpecializationKind.h" 31#include "CodeType.h" 32#include "ExpressionRangeInfo.h" 33#include "Identifier.h" 34#include "JSCell.h" 35#include "JSString.h" 36#include "ParserModes.h" 37#include "RegExp.h" 38#include "SpecialPointer.h" 39#include "SymbolTable.h" 40#include "VirtualRegister.h" 41 42#include <wtf/Compression.h> 43#include <wtf/RefCountedArray.h> 44#include <wtf/Vector.h> 45 46namespace JSC { 47 48class Debugger; 49class FunctionBodyNode; 50class FunctionExecutable; 51class FunctionParameters; 52class JSScope; 53struct ParserError; 54class ScriptExecutable; 55class SourceCode; 56class SourceProvider; 57class SymbolTable; 58class UnlinkedCodeBlock; 59class UnlinkedFunctionCodeBlock; 60class UnlinkedInstructionStream; 61 62typedef unsigned UnlinkedValueProfile; 63typedef unsigned UnlinkedArrayProfile; 64typedef unsigned UnlinkedArrayAllocationProfile; 65typedef unsigned UnlinkedObjectAllocationProfile; 66typedef unsigned UnlinkedLLIntCallLinkInfo; 67 68struct ExecutableInfo { 69 ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction) 70 : m_needsActivation(needsActivation) 71 , m_usesEval(usesEval) 72 , m_isStrictMode(isStrictMode) 73 , m_isConstructor(isConstructor) 74 , m_isBuiltinFunction(isBuiltinFunction) 75 { 76 } 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 84enum UnlinkedFunctionKind { 85 UnlinkedNormalFunction, 86 UnlinkedBuiltinFunction, 87}; 88 89class UnlinkedFunctionExecutable : public JSCell { 90public: 91 friend class BuiltinExecutables; 92 friend class CodeCache; 93 friend class VM; 94 typedef JSCell Base; 95 static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionBodyNode* node, UnlinkedFunctionKind unlinkedFunctionKind) 96 { 97 UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap)) UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node, unlinkedFunctionKind); 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(); } 105 SymbolTable* symbolTable(CodeSpecializationKind kind) 106 { 107 return (kind == CodeForCall) ? m_symbolTableForCall.get() : m_symbolTableForConstruct.get(); 108 } 109 size_t parameterCount() const; 110 bool isInStrictContext() const { return m_isInStrictContext; } 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 } 120 121 unsigned firstLineOffset() const { return m_firstLineOffset; } 122 unsigned lineCount() const { return m_lineCount; } 123 unsigned unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; } 124 unsigned unlinkedBodyStartColumn() const { return m_unlinkedBodyStartColumn; } 125 unsigned unlinkedBodyEndColumn() const { return m_unlinkedBodyEndColumn; } 126 unsigned startOffset() const { return m_startOffset; } 127 unsigned sourceLength() { return m_sourceLength; } 128 129 String paramString() const; 130 131 UnlinkedFunctionCodeBlock* codeBlockFor(VM&, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, bool bodyIncludesBraces, ParserError&); 132 133 static UnlinkedFunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception); 134 135 FunctionExecutable* link(VM&, const SourceCode&, size_t lineOffset); 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 147 void recordParse(CodeFeatures features, bool hasCapturedVariables) 148 { 149 m_features = features; 150 m_hasCapturedVariables = hasCapturedVariables; 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 162 bool isBuiltinFunction() const { return m_isBuiltinFunction; } 163 164private: 165 UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionBodyNode*, UnlinkedFunctionKind); 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; 173 bool m_isBuiltinFunction : 1; 174 175 Identifier m_name; 176 Identifier m_inferredName; 177 WriteBarrier<JSString> m_nameValue; 178 WriteBarrier<SymbolTable> m_symbolTableForCall; 179 WriteBarrier<SymbolTable> m_symbolTableForConstruct; 180 RefPtr<FunctionParameters> m_parameters; 181 unsigned m_firstLineOffset; 182 unsigned m_lineCount; 183 unsigned m_unlinkedFunctionNameStart; 184 unsigned m_unlinkedBodyStartColumn; 185 unsigned m_unlinkedBodyEndColumn; 186 unsigned m_startOffset; 187 unsigned m_sourceLength; 188 189 CodeFeatures m_features; 190 191 FunctionMode m_functionMode; 192 193protected: 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 202public: 203 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) 204 { 205 return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionExecutableType, StructureFlags), info()); 206 } 207 208 static const unsigned StructureFlags = OverridesVisitChildren | StructureIsImmortal | JSCell::StructureFlags; 209 210 DECLARE_EXPORT_INFO; 211}; 212 213struct 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 228struct 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 240struct UnlinkedHandlerInfo { 241 uint32_t start; 242 uint32_t end; 243 uint32_t target; 244 uint32_t scopeDepth; 245}; 246 247struct 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; 254 unsigned index; 255 } u; 256}; 257 258class UnlinkedCodeBlock : public JSCell { 259public: 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; } 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 278 void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; } 279 void setActivationRegister(VirtualRegister activationRegister) { m_activationRegister = activationRegister; } 280 281 void setArgumentsRegister(VirtualRegister argumentsRegister) { m_argumentsRegister = argumentsRegister; } 282 bool usesArguments() const { return m_argumentsRegister.isValid(); } 283 VirtualRegister argumentsRegister() const { return m_argumentsRegister; } 284 285 286 bool usesGlobalObject() const { return m_globalObjectRegister.isValid(); } 287 void setGlobalObjectRegister(VirtualRegister globalObjectRegister) { m_globalObjectRegister = globalObjectRegister; } 288 VirtualRegister globalObjectRegister() const { return m_globalObjectRegister; } 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); 326 const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; } 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 340 bool isBuiltinFunction() const { return m_isBuiltinFunction; } 341 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(); 359 m_rareData->m_switchJumpTables.shrinkToFit(); 360 m_rareData->m_stringSwitchJumpTables.shrinkToFit(); 361 m_rareData->m_expressionInfoFatPositions.shrinkToFit(); 362 } 363 } 364 365 void setInstructions(std::unique_ptr<UnlinkedInstructionStream>); 366 const UnlinkedInstructionStream& instructions() const; 367 368 int m_numVars; 369 int m_numCapturedVars; 370 int m_numCalleeRegisters; 371 372 // Jump Tables 373 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]; } 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 406 SymbolTable* symbolTable() const { return m_symbolTable.get(); } 407 void setSymbolTable(SymbolTable* table) { m_symbolTable.set(*m_vm, this, table); } 408 409 VM* vm() const { return m_vm; } 410 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 425 VirtualRegister thisRegister() const { return m_thisRegister; } 426 VirtualRegister activationRegister() const { return m_activationRegister; } 427 bool hasActivationRegister() const { return m_activationRegister.isValid(); } 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 467 void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount, unsigned endColumn) 468 { 469 m_features = features; 470 m_hasCapturedVariables = hasCapturedVariables; 471 m_firstLine = firstLine; 472 m_lineCount = lineCount; 473 // For the UnlinkedCodeBlock, startColumn is always 0. 474 m_endColumn = endColumn; 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; } 481 ALWAYS_INLINE unsigned startColumn() const { return 0; } 482 unsigned endColumn() const { return m_endColumn; } 483 484 void dumpExpressionRangeInfo(); // For debugging purpose only. 485 486protected: 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; 495 m_symbolTable.set(vm, this, SymbolTable::create(vm)); 496 } 497 498private: 499 500 void createRareDataIfNecessary() 501 { 502 if (!m_rareData) 503 m_rareData = adoptPtr(new RareData); 504 } 505 506 void getLineAndColumn(ExpressionRangeInfo&, unsigned& line, unsigned& column); 507 508 std::unique_ptr<UnlinkedInstructionStream> m_unlinkedInstructions; 509 510 int m_numParameters; 511 VM* m_vm; 512 513 VirtualRegister m_thisRegister; 514 VirtualRegister m_argumentsRegister; 515 VirtualRegister m_activationRegister; 516 VirtualRegister m_globalObjectRegister; 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; 524 bool m_isBuiltinFunction : 1; 525 unsigned m_firstLine; 526 unsigned m_lineCount; 527 unsigned m_endColumn; 528 529 CodeFeatures m_features; 530 CodeType m_codeType; 531 532 Vector<unsigned> m_jumpTargets; 533 534 // Constant Pools 535 Vector<Identifier> m_identifiers; 536 Vector<WriteBarrier<Unknown>> m_constantRegisters; 537 typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector; 538 FunctionExpressionVector m_functionDecls; 539 FunctionExpressionVector m_functionExprs; 540 541 WriteBarrier<SymbolTable> m_symbolTable; 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 550 unsigned m_arrayProfileCount; 551 unsigned m_arrayAllocationProfileCount; 552 unsigned m_objectAllocationProfileCount; 553 unsigned m_valueProfileCount; 554 unsigned m_llintCallLinkInfoCount; 555 556public: 557 struct RareData { 558 WTF_MAKE_FAST_ALLOCATED; 559 public: 560 Vector<UnlinkedHandlerInfo> m_exceptionHandlers; 561 562 // Rare Constants 563 Vector<WriteBarrier<RegExp>> m_regexps; 564 565 // Buffers used for large array literals 566 Vector<ConstantBuffer> m_constantBuffers; 567 568 // Jump Tables 569 Vector<UnlinkedSimpleJumpTable> m_switchJumpTables; 570 Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables; 571 572 Vector<ExpressionRangeInfo::FatPosition> m_expressionInfoFatPositions; 573 }; 574 575private: 576 OwnPtr<RareData> m_rareData; 577 Vector<ExpressionRangeInfo> m_expressionInfo; 578 579protected: 580 581 static const unsigned StructureFlags = OverridesVisitChildren | StructureIsImmortal | Base::StructureFlags; 582 static void visitChildren(JSCell*, SlotVisitor&); 583 584public: 585 DECLARE_INFO; 586}; 587 588class UnlinkedGlobalCodeBlock : public UnlinkedCodeBlock { 589public: 590 typedef UnlinkedCodeBlock Base; 591 592protected: 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 600 DECLARE_INFO; 601}; 602 603class UnlinkedProgramCodeBlock : public UnlinkedGlobalCodeBlock { 604private: 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 613public: 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 627 typedef Vector<std::pair<Identifier, bool>> VariableDeclations; 628 typedef Vector<std::pair<Identifier, WriteBarrier<UnlinkedFunctionExecutable>> > FunctionDeclations; 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 635private: 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 644public: 645 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) 646 { 647 return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedProgramCodeBlockType, StructureFlags), info()); 648 } 649 650 static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags; 651 652 DECLARE_INFO; 653}; 654 655class UnlinkedEvalCodeBlock : public UnlinkedGlobalCodeBlock { 656private: 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 666public: 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 678private: 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 686public: 687 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) 688 { 689 return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedEvalCodeBlockType, StructureFlags), info()); 690 } 691 692 static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags; 693 694 DECLARE_INFO; 695}; 696 697class UnlinkedFunctionCodeBlock : public UnlinkedCodeBlock { 698public: 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 709private: 710 UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info) 711 : Base(vm, structure, codeType, info) 712 { 713 } 714 715public: 716 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) 717 { 718 return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionCodeBlockType, StructureFlags), info()); 719 } 720 721 static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags; 722 723 DECLARE_INFO; 724}; 725 726} 727 728#endif // UnlinkedCodeBlock_h 729