Changeset 208309 in webkit for trunk/Source/JavaScriptCore/bytecode/ProgramCodeBlock.h
- Timestamp:
- Nov 2, 2016, 3:19:39 PM (9 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/bytecode/ProgramCodeBlock.h
r208224 r208309 30 30 #pragma once 31 31 32 #include "ArrayProfile.h" 33 #include "ByValInfo.h" 34 #include "BytecodeConventions.h" 35 #include "CallLinkInfo.h" 36 #include "CallReturnOffsetToBytecodeOffset.h" 37 #include "CodeBlockHash.h" 38 #include "CodeOrigin.h" 39 #include "CodeType.h" 40 #include "CompactJITCodeMap.h" 41 #include "ConcurrentJITLock.h" 42 #include "DFGCommon.h" 43 #include "DFGExitProfile.h" 44 #include "DeferredCompilationCallback.h" 45 #include "EvalCodeCache.h" 46 #include "ExecutionCounter.h" 47 #include "ExpressionRangeInfo.h" 48 #include "FunctionExecutable.h" 49 #include "HandlerInfo.h" 50 #include "Instruction.h" 51 #include "JITCode.h" 52 #include "JITMathICForwards.h" 53 #include "JSCell.h" 54 #include "JSGlobalObject.h" 55 #include "JumpTable.h" 56 #include "LLIntCallLinkInfo.h" 57 #include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h" 58 #include "LazyOperandValueProfile.h" 59 #include "ModuleProgramExecutable.h" 60 #include "ObjectAllocationProfile.h" 61 #include "Options.h" 62 #include "ProfilerJettisonReason.h" 63 #include "ProgramExecutable.h" 64 #include "PutPropertySlot.h" 65 #include "UnconditionalFinalizer.h" 66 #include "ValueProfile.h" 67 #include "VirtualRegister.h" 68 #include "Watchpoint.h" 69 #include <wtf/Bag.h> 70 #include <wtf/FastBitVector.h> 71 #include <wtf/FastMalloc.h> 72 #include <wtf/RefCountedArray.h> 73 #include <wtf/RefPtr.h> 74 #include <wtf/SegmentedVector.h> 75 #include <wtf/Vector.h> 76 #include <wtf/text/WTFString.h> 32 #include "GlobalCodeBlock.h" 77 33 78 34 namespace JSC { 79 80 class BytecodeLivenessAnalysis;81 class CodeBlockSet;82 class ExecState;83 class JSModuleEnvironment;84 class LLIntOffsetsExtractor;85 class PCToCodeOriginMap;86 class RegisterAtOffsetList;87 class StructureStubInfo;88 89 enum class AccessType : int8_t;90 91 struct ArithProfile;92 93 typedef HashMap<CodeOrigin, StructureStubInfo*, CodeOriginApproximateHash> StubInfoMap;94 95 enum ReoptimizationMode { DontCountReoptimization, CountReoptimization };96 97 class CodeBlock : public JSCell {98 typedef JSCell Base;99 friend class BytecodeLivenessAnalysis;100 friend class JIT;101 friend class LLIntOffsetsExtractor;102 103 class UnconditionalFinalizer : public JSC::UnconditionalFinalizer {104 void finalizeUnconditionally() override;105 };106 107 class WeakReferenceHarvester : public JSC::WeakReferenceHarvester {108 void visitWeakReferences(SlotVisitor&) override;109 };110 111 public:112 enum CopyParsedBlockTag { CopyParsedBlock };113 114 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;115 116 DECLARE_INFO;117 118 protected:119 CodeBlock(VM*, Structure*, CopyParsedBlockTag, CodeBlock& other);120 CodeBlock(VM*, Structure*, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*, PassRefPtr<SourceProvider>, unsigned sourceOffset, unsigned firstLineColumnOffset);121 #if ENABLE(WEBASSEMBLY)122 CodeBlock(VM*, Structure*, WebAssemblyExecutable* ownerExecutable, JSGlobalObject*);123 #endif124 125 void finishCreation(VM&, CopyParsedBlockTag, CodeBlock& other);126 void finishCreation(VM&, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*);127 #if ENABLE(WEBASSEMBLY)128 void finishCreation(VM&, WebAssemblyExecutable* ownerExecutable, JSGlobalObject*);129 #endif130 131 WriteBarrier<JSGlobalObject> m_globalObject;132 133 public:134 JS_EXPORT_PRIVATE ~CodeBlock();135 136 UnlinkedCodeBlock* unlinkedCodeBlock() const { return m_unlinkedCode.get(); }137 138 CString inferredName() const;139 CodeBlockHash hash() const;140 bool hasHash() const;141 bool isSafeToComputeHash() const;142 CString hashAsStringIfPossible() const;143 CString sourceCodeForTools() const; // Not quite the actual source we parsed; this will do things like prefix the source for a function with a reified signature.144 CString sourceCodeOnOneLine() const; // As sourceCodeForTools(), but replaces all whitespace runs with a single space.145 void dumpAssumingJITType(PrintStream&, JITCode::JITType) const;146 JS_EXPORT_PRIVATE void dump(PrintStream&) const;147 148 int numParameters() const { return m_numParameters; }149 void setNumParameters(int newValue);150 151 int numCalleeLocals() const { return m_numCalleeLocals; }152 153 int* addressOfNumParameters() { return &m_numParameters; }154 static ptrdiff_t offsetOfNumParameters() { return OBJECT_OFFSETOF(CodeBlock, m_numParameters); }155 156 CodeBlock* alternative() const { return static_cast<CodeBlock*>(m_alternative.get()); }157 void setAlternative(VM&, CodeBlock*);158 159 template <typename Functor> void forEachRelatedCodeBlock(Functor&& functor)160 {161 Functor f(std::forward<Functor>(functor));162 Vector<CodeBlock*, 4> codeBlocks;163 codeBlocks.append(this);164 165 while (!codeBlocks.isEmpty()) {166 CodeBlock* currentCodeBlock = codeBlocks.takeLast();167 f(currentCodeBlock);168 169 if (CodeBlock* alternative = currentCodeBlock->alternative())170 codeBlocks.append(alternative);171 if (CodeBlock* osrEntryBlock = currentCodeBlock->specialOSREntryBlockOrNull())172 codeBlocks.append(osrEntryBlock);173 }174 }175 176 CodeSpecializationKind specializationKind() const177 {178 return specializationFromIsConstruct(m_isConstructor);179 }180 181 CodeBlock* alternativeForJettison();182 JS_EXPORT_PRIVATE CodeBlock* baselineAlternative();183 184 // FIXME: Get rid of this.185 // https://bugs.webkit.org/show_bug.cgi?id=123677186 CodeBlock* baselineVersion();187 188 static size_t estimatedSize(JSCell*);189 static void visitChildren(JSCell*, SlotVisitor&);190 void visitChildren(SlotVisitor&);191 void visitWeakly(SlotVisitor&);192 void clearVisitWeaklyHasBeenCalled();193 194 void dumpSource();195 void dumpSource(PrintStream&);196 197 void dumpBytecode();198 void dumpBytecode(PrintStream&);199 void dumpBytecode(200 PrintStream&, unsigned bytecodeOffset,201 const StubInfoMap& = StubInfoMap(), const CallLinkInfoMap& = CallLinkInfoMap());202 void dumpExceptionHandlers(PrintStream&);203 void printStructures(PrintStream&, const Instruction*);204 void printStructure(PrintStream&, const char* name, const Instruction*, int operand);205 206 void dumpMathICStats();207 208 bool isStrictMode() const { return m_isStrictMode; }209 ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; }210 211 inline bool isKnownNotImmediate(int index)212 {213 if (index == m_thisRegister.offset() && !m_isStrictMode)214 return true;215 216 if (isConstantRegisterIndex(index))217 return getConstant(index).isCell();218 219 return false;220 }221 222 ALWAYS_INLINE bool isTemporaryRegisterIndex(int index)223 {224 return index >= m_numVars;225 }226 227 HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler = RequiredHandler::AnyHandler);228 HandlerInfo* handlerForIndex(unsigned, RequiredHandler = RequiredHandler::AnyHandler);229 void removeExceptionHandlerForCallSite(CallSiteIndex);230 unsigned lineNumberForBytecodeOffset(unsigned bytecodeOffset);231 unsigned columnNumberForBytecodeOffset(unsigned bytecodeOffset);232 void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,233 int& startOffset, int& endOffset, unsigned& line, unsigned& column) const;234 235 Optional<unsigned> bytecodeOffsetFromCallSiteIndex(CallSiteIndex);236 237 void getStubInfoMap(const ConcurrentJITLocker&, StubInfoMap& result);238 void getStubInfoMap(StubInfoMap& result);239 240 void getCallLinkInfoMap(const ConcurrentJITLocker&, CallLinkInfoMap& result);241 void getCallLinkInfoMap(CallLinkInfoMap& result);242 243 void getByValInfoMap(const ConcurrentJITLocker&, ByValInfoMap& result);244 void getByValInfoMap(ByValInfoMap& result);245 246 #if ENABLE(JIT)247 StructureStubInfo* addStubInfo(AccessType);248 JITAddIC* addJITAddIC(ArithProfile*);249 JITMulIC* addJITMulIC(ArithProfile*);250 JITNegIC* addJITNegIC(ArithProfile*);251 JITSubIC* addJITSubIC(ArithProfile*);252 Bag<StructureStubInfo>::iterator stubInfoBegin() { return m_stubInfos.begin(); }253 Bag<StructureStubInfo>::iterator stubInfoEnd() { return m_stubInfos.end(); }254 255 // O(n) operation. Use getStubInfoMap() unless you really only intend to get one256 // stub info.257 StructureStubInfo* findStubInfo(CodeOrigin);258 259 ByValInfo* addByValInfo();260 261 CallLinkInfo* addCallLinkInfo();262 Bag<CallLinkInfo>::iterator callLinkInfosBegin() { return m_callLinkInfos.begin(); }263 Bag<CallLinkInfo>::iterator callLinkInfosEnd() { return m_callLinkInfos.end(); }264 265 // This is a slow function call used primarily for compiling OSR exits in the case266 // that there had been inlining. Chances are if you want to use this, you're really267 // looking for a CallLinkInfoMap to amortize the cost of calling this.268 CallLinkInfo* getCallLinkInfoForBytecodeIndex(unsigned bytecodeIndex);269 270 // We call this when we want to reattempt compiling something with the baseline JIT. Ideally271 // the baseline JIT would not add data to CodeBlock, but instead it would put its data into272 // a newly created JITCode, which could be thrown away if we bail on JIT compilation. Then we273 // would be able to get rid of this silly function.274 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=159061275 void resetJITData();276 #endif // ENABLE(JIT)277 278 void unlinkIncomingCalls();279 280 #if ENABLE(JIT)281 void linkIncomingCall(ExecState* callerFrame, CallLinkInfo*);282 void linkIncomingPolymorphicCall(ExecState* callerFrame, PolymorphicCallNode*);283 #endif // ENABLE(JIT)284 285 void linkIncomingCall(ExecState* callerFrame, LLIntCallLinkInfo*);286 287 void setJITCodeMap(std::unique_ptr<CompactJITCodeMap> jitCodeMap)288 {289 m_jitCodeMap = WTFMove(jitCodeMap);290 }291 CompactJITCodeMap* jitCodeMap()292 {293 return m_jitCodeMap.get();294 }295 296 static void clearLLIntGetByIdCache(Instruction*);297 298 unsigned bytecodeOffset(Instruction* returnAddress)299 {300 RELEASE_ASSERT(returnAddress >= instructions().begin() && returnAddress < instructions().end());301 return static_cast<Instruction*>(returnAddress) - instructions().begin();302 }303 304 typedef JSC::Instruction Instruction;305 typedef RefCountedArray<Instruction>& UnpackedInstructions;306 307 unsigned numberOfInstructions() const { return m_instructions.size(); }308 RefCountedArray<Instruction>& instructions() { return m_instructions; }309 const RefCountedArray<Instruction>& instructions() const { return m_instructions; }310 311 size_t predictedMachineCodeSize();312 313 bool usesOpcode(OpcodeID);314 315 unsigned instructionCount() const { return m_instructions.size(); }316 317 // Exactly equivalent to codeBlock->ownerExecutable()->newReplacementCodeBlockFor(codeBlock->specializationKind())318 CodeBlock* newReplacement();319 320 void setJITCode(PassRefPtr<JITCode> code)321 {322 ASSERT(heap()->isDeferred());323 heap()->reportExtraMemoryAllocated(code->size());324 ConcurrentJITLocker locker(m_lock);325 WTF::storeStoreFence(); // This is probably not needed because the lock will also do something similar, but it's good to be paranoid.326 m_jitCode = code;327 }328 PassRefPtr<JITCode> jitCode() { return m_jitCode; }329 static ptrdiff_t jitCodeOffset() { return OBJECT_OFFSETOF(CodeBlock, m_jitCode); }330 JITCode::JITType jitType() const331 {332 JITCode* jitCode = m_jitCode.get();333 WTF::loadLoadFence();334 JITCode::JITType result = JITCode::jitTypeFor(jitCode);335 WTF::loadLoadFence(); // This probably isn't needed. Oh well, paranoia is good.336 return result;337 }338 339 bool hasBaselineJITProfiling() const340 {341 return jitType() == JITCode::BaselineJIT;342 }343 344 #if ENABLE(JIT)345 CodeBlock* replacement();346 347 DFG::CapabilityLevel computeCapabilityLevel();348 DFG::CapabilityLevel capabilityLevel();349 DFG::CapabilityLevel capabilityLevelState() { return static_cast<DFG::CapabilityLevel>(m_capabilityLevelState); }350 351 bool hasOptimizedReplacement(JITCode::JITType typeToReplace);352 bool hasOptimizedReplacement(); // the typeToReplace is my JITType353 #endif354 355 void jettison(Profiler::JettisonReason, ReoptimizationMode = DontCountReoptimization, const FireDetail* = nullptr);356 357 ExecutableBase* ownerExecutable() const { return m_ownerExecutable.get(); }358 ScriptExecutable* ownerScriptExecutable() const { return jsCast<ScriptExecutable*>(m_ownerExecutable.get()); }359 360 VM* vm() const { return m_vm; }361 362 void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; }363 VirtualRegister thisRegister() const { return m_thisRegister; }364 365 bool usesEval() const { return m_unlinkedCode->usesEval(); }366 367 void setScopeRegister(VirtualRegister scopeRegister)368 {369 ASSERT(scopeRegister.isLocal() || !scopeRegister.isValid());370 m_scopeRegister = scopeRegister;371 }372 373 VirtualRegister scopeRegister() const374 {375 return m_scopeRegister;376 }377 378 CodeType codeType() const379 {380 return static_cast<CodeType>(m_codeType);381 }382 383 PutPropertySlot::Context putByIdContext() const384 {385 if (codeType() == EvalCode)386 return PutPropertySlot::PutByIdEval;387 return PutPropertySlot::PutById;388 }389 390 SourceProvider* source() const { return m_source.get(); }391 unsigned sourceOffset() const { return m_sourceOffset; }392 unsigned firstLineColumnOffset() const { return m_firstLineColumnOffset; }393 394 size_t numberOfJumpTargets() const { return m_unlinkedCode->numberOfJumpTargets(); }395 unsigned jumpTarget(int index) const { return m_unlinkedCode->jumpTarget(index); }396 397 String nameForRegister(VirtualRegister);398 399 unsigned numberOfArgumentValueProfiles()400 {401 ASSERT(m_numParameters >= 0);402 ASSERT(m_argumentValueProfiles.size() == static_cast<unsigned>(m_numParameters));403 return m_argumentValueProfiles.size();404 }405 ValueProfile* valueProfileForArgument(unsigned argumentIndex)406 {407 ValueProfile* result = &m_argumentValueProfiles[argumentIndex];408 ASSERT(result->m_bytecodeOffset == -1);409 return result;410 }411 412 unsigned numberOfValueProfiles() { return m_valueProfiles.size(); }413 ValueProfile* valueProfile(int index) { return &m_valueProfiles[index]; }414 ValueProfile* valueProfileForBytecodeOffset(int bytecodeOffset);415 SpeculatedType valueProfilePredictionForBytecodeOffset(const ConcurrentJITLocker& locker, int bytecodeOffset)416 {417 return valueProfileForBytecodeOffset(bytecodeOffset)->computeUpdatedPrediction(locker);418 }419 420 unsigned totalNumberOfValueProfiles()421 {422 return numberOfArgumentValueProfiles() + numberOfValueProfiles();423 }424 ValueProfile* getFromAllValueProfiles(unsigned index)425 {426 if (index < numberOfArgumentValueProfiles())427 return valueProfileForArgument(index);428 return valueProfile(index - numberOfArgumentValueProfiles());429 }430 431 RareCaseProfile* addRareCaseProfile(int bytecodeOffset);432 unsigned numberOfRareCaseProfiles() { return m_rareCaseProfiles.size(); }433 RareCaseProfile* rareCaseProfileForBytecodeOffset(int bytecodeOffset);434 unsigned rareCaseProfileCountForBytecodeOffset(int bytecodeOffset);435 436 bool likelyToTakeSlowCase(int bytecodeOffset)437 {438 if (!hasBaselineJITProfiling())439 return false;440 unsigned value = rareCaseProfileCountForBytecodeOffset(bytecodeOffset);441 return value >= Options::likelyToTakeSlowCaseMinimumCount();442 }443 444 bool couldTakeSlowCase(int bytecodeOffset)445 {446 if (!hasBaselineJITProfiling())447 return false;448 unsigned value = rareCaseProfileCountForBytecodeOffset(bytecodeOffset);449 return value >= Options::couldTakeSlowCaseMinimumCount();450 }451 452 ArithProfile* arithProfileForBytecodeOffset(int bytecodeOffset);453 ArithProfile* arithProfileForPC(Instruction*);454 455 bool couldTakeSpecialFastCase(int bytecodeOffset);456 457 unsigned numberOfArrayProfiles() const { return m_arrayProfiles.size(); }458 const ArrayProfileVector& arrayProfiles() { return m_arrayProfiles; }459 ArrayProfile* addArrayProfile(const ConcurrentJITLocker&, unsigned bytecodeOffset);460 ArrayProfile* addArrayProfile(unsigned bytecodeOffset);461 ArrayProfile* getArrayProfile(const ConcurrentJITLocker&, unsigned bytecodeOffset);462 ArrayProfile* getArrayProfile(unsigned bytecodeOffset);463 ArrayProfile* getOrAddArrayProfile(const ConcurrentJITLocker&, unsigned bytecodeOffset);464 ArrayProfile* getOrAddArrayProfile(unsigned bytecodeOffset);465 466 // Exception handling support467 468 size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }469 HandlerInfo& exceptionHandler(int index) { RELEASE_ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }470 471 bool hasExpressionInfo() { return m_unlinkedCode->hasExpressionInfo(); }472 473 #if ENABLE(DFG_JIT)474 Vector<CodeOrigin, 0, UnsafeVectorOverflow>& codeOrigins();475 476 // Having code origins implies that there has been some inlining.477 bool hasCodeOrigins()478 {479 return JITCode::isOptimizingJIT(jitType());480 }481 482 bool canGetCodeOrigin(CallSiteIndex index)483 {484 if (!hasCodeOrigins())485 return false;486 return index.bits() < codeOrigins().size();487 }488 489 CodeOrigin codeOrigin(CallSiteIndex index)490 {491 return codeOrigins()[index.bits()];492 }493 494 bool addFrequentExitSite(const DFG::FrequentExitSite& site)495 {496 ASSERT(JITCode::isBaselineCode(jitType()));497 ConcurrentJITLocker locker(m_lock);498 return m_exitProfile.add(locker, this, site);499 }500 501 bool hasExitSite(const ConcurrentJITLocker& locker, const DFG::FrequentExitSite& site) const502 {503 return m_exitProfile.hasExitSite(locker, site);504 }505 bool hasExitSite(const DFG::FrequentExitSite& site) const506 {507 ConcurrentJITLocker locker(m_lock);508 return hasExitSite(locker, site);509 }510 511 DFG::ExitProfile& exitProfile() { return m_exitProfile; }512 513 CompressedLazyOperandValueProfileHolder& lazyOperandValueProfiles()514 {515 return m_lazyOperandValueProfiles;516 }517 #endif // ENABLE(DFG_JIT)518 519 // Constant Pool520 #if ENABLE(DFG_JIT)521 size_t numberOfIdentifiers() const { return m_unlinkedCode->numberOfIdentifiers() + numberOfDFGIdentifiers(); }522 size_t numberOfDFGIdentifiers() const;523 const Identifier& identifier(int index) const;524 #else525 size_t numberOfIdentifiers() const { return m_unlinkedCode->numberOfIdentifiers(); }526 const Identifier& identifier(int index) const { return m_unlinkedCode->identifier(index); }527 #endif528 529 Vector<WriteBarrier<Unknown>>& constants() { return m_constantRegisters; }530 Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation() { return m_constantsSourceCodeRepresentation; }531 unsigned addConstant(JSValue v)532 {533 unsigned result = m_constantRegisters.size();534 m_constantRegisters.append(WriteBarrier<Unknown>());535 m_constantRegisters.last().set(m_globalObject->vm(), this, v);536 m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);537 return result;538 }539 540 unsigned addConstantLazily()541 {542 unsigned result = m_constantRegisters.size();543 m_constantRegisters.append(WriteBarrier<Unknown>());544 m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);545 return result;546 }547 548 WriteBarrier<Unknown>& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; }549 static ALWAYS_INLINE bool isConstantRegisterIndex(int index) { return index >= FirstConstantRegisterIndex; }550 ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }551 ALWAYS_INLINE SourceCodeRepresentation constantSourceCodeRepresentation(int index) const { return m_constantsSourceCodeRepresentation[index - FirstConstantRegisterIndex]; }552 553 FunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }554 int numberOfFunctionDecls() { return m_functionDecls.size(); }555 FunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }556 557 RegExp* regexp(int index) const { return m_unlinkedCode->regexp(index); }558 559 unsigned numberOfConstantBuffers() const560 {561 if (!m_rareData)562 return 0;563 return m_rareData->m_constantBuffers.size();564 }565 unsigned addConstantBuffer(const Vector<JSValue>& buffer)566 {567 createRareDataIfNecessary();568 unsigned size = m_rareData->m_constantBuffers.size();569 m_rareData->m_constantBuffers.append(buffer);570 return size;571 }572 573 Vector<JSValue>& constantBufferAsVector(unsigned index)574 {575 ASSERT(m_rareData);576 return m_rareData->m_constantBuffers[index];577 }578 JSValue* constantBuffer(unsigned index)579 {580 return constantBufferAsVector(index).data();581 }582 583 Heap* heap() const { return &m_vm->heap; }584 JSGlobalObject* globalObject() { return m_globalObject.get(); }585 586 JSGlobalObject* globalObjectFor(CodeOrigin);587 588 BytecodeLivenessAnalysis& livenessAnalysis()589 {590 {591 ConcurrentJITLocker locker(m_lock);592 if (!!m_livenessAnalysis)593 return *m_livenessAnalysis;594 }595 return livenessAnalysisSlow();596 }597 598 void validate();599 600 // Jump Tables601 602 size_t numberOfSwitchJumpTables() const { return m_rareData ? m_rareData->m_switchJumpTables.size() : 0; }603 SimpleJumpTable& addSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_switchJumpTables.append(SimpleJumpTable()); return m_rareData->m_switchJumpTables.last(); }604 SimpleJumpTable& switchJumpTable(int tableIndex) { RELEASE_ASSERT(m_rareData); return m_rareData->m_switchJumpTables[tableIndex]; }605 void clearSwitchJumpTables()606 {607 if (!m_rareData)608 return;609 m_rareData->m_switchJumpTables.clear();610 }611 612 size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }613 StringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(StringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }614 StringJumpTable& stringSwitchJumpTable(int tableIndex) { RELEASE_ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }615 616 EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; }617 618 enum ShrinkMode {619 // Shrink prior to generating machine code that may point directly into vectors.620 EarlyShrink,621 622 // Shrink after generating machine code, and after possibly creating new vectors623 // and appending to others. At this time it is not safe to shrink certain vectors624 // because we would have generated machine code that references them directly.625 LateShrink626 };627 void shrinkToFit(ShrinkMode);628 629 // Functions for controlling when JITting kicks in, in a mixed mode630 // execution world.631 632 bool checkIfJITThresholdReached()633 {634 return m_llintExecuteCounter.checkIfThresholdCrossedAndSet(this);635 }636 637 void dontJITAnytimeSoon()638 {639 m_llintExecuteCounter.deferIndefinitely();640 }641 642 int32_t thresholdForJIT(int32_t threshold);643 void jitAfterWarmUp();644 void jitSoon();645 646 const BaselineExecutionCounter& llintExecuteCounter() const647 {648 return m_llintExecuteCounter;649 }650 651 typedef HashMap<Structure*, Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint>> StructureWatchpointMap;652 StructureWatchpointMap& llintGetByIdWatchpointMap() { return m_llintGetByIdWatchpointMap; }653 654 // Functions for controlling when tiered compilation kicks in. This655 // controls both when the optimizing compiler is invoked and when OSR656 // entry happens. Two triggers exist: the loop trigger and the return657 // trigger. In either case, when an addition to m_jitExecuteCounter658 // causes it to become non-negative, the optimizing compiler is659 // invoked. This includes a fast check to see if this CodeBlock has660 // already been optimized (i.e. replacement() returns a CodeBlock661 // that was optimized with a higher tier JIT than this one). In the662 // case of the loop trigger, if the optimized compilation succeeds663 // (or has already succeeded in the past) then OSR is attempted to664 // redirect program flow into the optimized code.665 666 // These functions are called from within the optimization triggers,667 // and are used as a single point at which we define the heuristics668 // for how much warm-up is mandated before the next optimization669 // trigger files. All CodeBlocks start out with optimizeAfterWarmUp(),670 // as this is called from the CodeBlock constructor.671 672 // When we observe a lot of speculation failures, we trigger a673 // reoptimization. But each time, we increase the optimization trigger674 // to avoid thrashing.675 JS_EXPORT_PRIVATE unsigned reoptimizationRetryCounter() const;676 void countReoptimization();677 #if ENABLE(JIT)678 static unsigned numberOfLLIntBaselineCalleeSaveRegisters() { return RegisterSet::llintBaselineCalleeSaveRegisters().numberOfSetRegisters(); }679 static size_t llintBaselineCalleeSaveSpaceAsVirtualRegisters();680 size_t calleeSaveSpaceAsVirtualRegisters();681 682 unsigned numberOfDFGCompiles();683 684 int32_t codeTypeThresholdMultiplier() const;685 686 int32_t adjustedCounterValue(int32_t desiredThreshold);687 688 int32_t* addressOfJITExecuteCounter()689 {690 return &m_jitExecuteCounter.m_counter;691 }692 693 static ptrdiff_t offsetOfJITExecuteCounter() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(BaselineExecutionCounter, m_counter); }694 static ptrdiff_t offsetOfJITExecutionActiveThreshold() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(BaselineExecutionCounter, m_activeThreshold); }695 static ptrdiff_t offsetOfJITExecutionTotalCount() { return OBJECT_OFFSETOF(CodeBlock, m_jitExecuteCounter) + OBJECT_OFFSETOF(BaselineExecutionCounter, m_totalCount); }696 697 const BaselineExecutionCounter& jitExecuteCounter() const { return m_jitExecuteCounter; }698 699 unsigned optimizationDelayCounter() const { return m_optimizationDelayCounter; }700 701 // Check if the optimization threshold has been reached, and if not,702 // adjust the heuristics accordingly. Returns true if the threshold has703 // been reached.704 bool checkIfOptimizationThresholdReached();705 706 // Call this to force the next optimization trigger to fire. This is707 // rarely wise, since optimization triggers are typically more708 // expensive than executing baseline code.709 void optimizeNextInvocation();710 711 // Call this to prevent optimization from happening again. Note that712 // optimization will still happen after roughly 2^29 invocations,713 // so this is really meant to delay that as much as possible. This714 // is called if optimization failed, and we expect it to fail in715 // the future as well.716 void dontOptimizeAnytimeSoon();717 718 // Call this to reinitialize the counter to its starting state,719 // forcing a warm-up to happen before the next optimization trigger720 // fires. This is called in the CodeBlock constructor. It also721 // makes sense to call this if an OSR exit occurred. Note that722 // OSR exit code is code generated, so the value of the execute723 // counter that this corresponds to is also available directly.724 void optimizeAfterWarmUp();725 726 // Call this to force an optimization trigger to fire only after727 // a lot of warm-up.728 void optimizeAfterLongWarmUp();729 730 // Call this to cause an optimization trigger to fire soon, but731 // not necessarily the next one. This makes sense if optimization732 // succeeds. Successfuly optimization means that all calls are733 // relinked to the optimized code, so this only affects call734 // frames that are still executing this CodeBlock. The value here735 // is tuned to strike a balance between the cost of OSR entry736 // (which is too high to warrant making every loop back edge to737 // trigger OSR immediately) and the cost of executing baseline738 // code (which is high enough that we don't necessarily want to739 // have a full warm-up). The intuition for calling this instead of740 // optimizeNextInvocation() is for the case of recursive functions741 // with loops. Consider that there may be N call frames of some742 // recursive function, for a reasonably large value of N. The top743 // one triggers optimization, and then returns, and then all of744 // the others return. We don't want optimization to be triggered on745 // each return, as that would be superfluous. It only makes sense746 // to trigger optimization if one of those functions becomes hot747 // in the baseline code.748 void optimizeSoon();749 750 void forceOptimizationSlowPathConcurrently();751 752 void setOptimizationThresholdBasedOnCompilationResult(CompilationResult);753 754 uint32_t osrExitCounter() const { return m_osrExitCounter; }755 756 void countOSRExit() { m_osrExitCounter++; }757 758 uint32_t* addressOfOSRExitCounter() { return &m_osrExitCounter; }759 760 static ptrdiff_t offsetOfOSRExitCounter() { return OBJECT_OFFSETOF(CodeBlock, m_osrExitCounter); }761 762 uint32_t adjustedExitCountThreshold(uint32_t desiredThreshold);763 uint32_t exitCountThresholdForReoptimization();764 uint32_t exitCountThresholdForReoptimizationFromLoop();765 bool shouldReoptimizeNow();766 bool shouldReoptimizeFromLoopNow();767 768 void setCalleeSaveRegisters(RegisterSet);769 void setCalleeSaveRegisters(std::unique_ptr<RegisterAtOffsetList>);770 771 RegisterAtOffsetList* calleeSaveRegisters() const { return m_calleeSaveRegisters.get(); }772 #else // No JIT773 static unsigned numberOfLLIntBaselineCalleeSaveRegisters() { return 0; }774 static size_t llintBaselineCalleeSaveSpaceAsVirtualRegisters() { return 0; };775 void optimizeAfterWarmUp() { }776 unsigned numberOfDFGCompiles() { return 0; }777 #endif778 779 bool shouldOptimizeNow();780 void updateAllValueProfilePredictions();781 void updateAllArrayPredictions();782 void updateAllPredictions();783 784 unsigned frameRegisterCount();785 int stackPointerOffset();786 787 bool hasOpDebugForLineAndColumn(unsigned line, unsigned column);788 789 bool hasDebuggerRequests() const { return m_debuggerRequests; }790 void* debuggerRequestsAddress() { return &m_debuggerRequests; }791 792 void addBreakpoint(unsigned numBreakpoints);793 void removeBreakpoint(unsigned numBreakpoints)794 {795 ASSERT(m_numBreakpoints >= numBreakpoints);796 m_numBreakpoints -= numBreakpoints;797 }798 799 enum SteppingMode {800 SteppingModeDisabled,801 SteppingModeEnabled802 };803 void setSteppingMode(SteppingMode);804 805 void clearDebuggerRequests()806 {807 m_steppingMode = SteppingModeDisabled;808 m_numBreakpoints = 0;809 }810 811 bool wasCompiledWithDebuggingOpcodes() const { return m_unlinkedCode->wasCompiledWithDebuggingOpcodes(); }812 813 // FIXME: Make these remaining members private.814 815 int m_numCalleeLocals;816 int m_numVars;817 818 // This is intentionally public; it's the responsibility of anyone doing any819 // of the following to hold the lock:820 //821 // - Modifying any inline cache in this code block.822 //823 // - Quering any inline cache in this code block, from a thread other than824 // the main thread.825 //826 // Additionally, it's only legal to modify the inline cache on the main827 // thread. This means that the main thread can query the inline cache without828 // locking. This is crucial since executing the inline cache is effectively829 // "querying" it.830 //831 // Another exception to the rules is that the GC can do whatever it wants832 // without holding any locks, because the GC is guaranteed to wait until any833 // concurrent compilation threads finish what they're doing.834 mutable ConcurrentJITLock m_lock;835 836 Atomic<bool> m_visitWeaklyHasBeenCalled;837 838 bool m_shouldAlwaysBeInlined; // Not a bitfield because the JIT wants to store to it.839 840 #if ENABLE(JIT)841 unsigned m_capabilityLevelState : 2; // DFG::CapabilityLevel842 #endif843 844 bool m_allTransitionsHaveBeenMarked : 1; // Initialized and used on every GC.845 846 bool m_didFailJITCompilation : 1;847 bool m_didFailFTLCompilation : 1;848 bool m_hasBeenCompiledWithFTL : 1;849 bool m_isConstructor : 1;850 bool m_isStrictMode : 1;851 unsigned m_codeType : 2; // CodeType852 853 // Internal methods for use by validation code. It would be private if it wasn't854 // for the fact that we use it from anonymous namespaces.855 void beginValidationDidFail();856 NO_RETURN_DUE_TO_CRASH void endValidationDidFail();857 858 struct RareData {859 WTF_MAKE_FAST_ALLOCATED;860 public:861 Vector<HandlerInfo> m_exceptionHandlers;862 863 // Buffers used for large array literals864 Vector<Vector<JSValue>> m_constantBuffers;865 866 // Jump Tables867 Vector<SimpleJumpTable> m_switchJumpTables;868 Vector<StringJumpTable> m_stringSwitchJumpTables;869 870 EvalCodeCache m_evalCodeCache;871 };872 873 void clearExceptionHandlers()874 {875 if (m_rareData)876 m_rareData->m_exceptionHandlers.clear();877 }878 879 void appendExceptionHandler(const HandlerInfo& handler)880 {881 createRareDataIfNecessary(); // We may be handling the exception of an inlined call frame.882 m_rareData->m_exceptionHandlers.append(handler);883 }884 885 CallSiteIndex newExceptionHandlingCallSiteIndex(CallSiteIndex originalCallSite);886 887 #if ENABLE(JIT)888 void setPCToCodeOriginMap(std::unique_ptr<PCToCodeOriginMap>&&);889 Optional<CodeOrigin> findPC(void* pc);890 #endif891 892 protected:893 void finalizeLLIntInlineCaches();894 void finalizeBaselineJITInlineCaches();895 896 #if ENABLE(DFG_JIT)897 void tallyFrequentExitSites();898 #else899 void tallyFrequentExitSites() { }900 #endif901 902 private:903 friend class CodeBlockSet;904 905 BytecodeLivenessAnalysis& livenessAnalysisSlow();906 907 CodeBlock* specialOSREntryBlockOrNull();908 909 void noticeIncomingCall(ExecState* callerFrame);910 911 double optimizationThresholdScalingFactor();912 913 void updateAllPredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles);914 915 void setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation);916 917 void replaceConstant(int index, JSValue value)918 {919 ASSERT(isConstantRegisterIndex(index) && static_cast<size_t>(index - FirstConstantRegisterIndex) < m_constantRegisters.size());920 m_constantRegisters[index - FirstConstantRegisterIndex].set(m_globalObject->vm(), this, value);921 }922 923 void dumpBytecode(924 PrintStream&, ExecState*, const Instruction* begin, const Instruction*&,925 const StubInfoMap& = StubInfoMap(), const CallLinkInfoMap& = CallLinkInfoMap());926 927 CString registerName(int r) const;928 CString constantName(int index) const;929 void printUnaryOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);930 void printBinaryOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);931 void printConditionalJump(PrintStream&, ExecState*, const Instruction*, const Instruction*&, int location, const char* op);932 void printGetByIdOp(PrintStream&, ExecState*, int location, const Instruction*&);933 void printGetByIdCacheStatus(PrintStream&, ExecState*, int location, const StubInfoMap&);934 enum CacheDumpMode { DumpCaches, DontDumpCaches };935 void printCallOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op, CacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap&);936 void printPutByIdOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);937 void printPutByIdCacheStatus(PrintStream&, int location, const StubInfoMap&);938 void printLocationAndOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);939 void printLocationOpAndRegisterOperand(PrintStream&, ExecState*, int location, const Instruction*& it, const char* op, int operand);940 941 void beginDumpProfiling(PrintStream&, bool& hasPrintedProfiling);942 void dumpValueProfiling(PrintStream&, const Instruction*&, bool& hasPrintedProfiling);943 void dumpArrayProfiling(PrintStream&, const Instruction*&, bool& hasPrintedProfiling);944 void dumpRareCaseProfile(PrintStream&, const char* name, RareCaseProfile*, bool& hasPrintedProfiling);945 void dumpArithProfile(PrintStream&, ArithProfile*, bool& hasPrintedProfiling);946 947 bool shouldVisitStrongly();948 bool shouldJettisonDueToWeakReference();949 bool shouldJettisonDueToOldAge();950 951 void propagateTransitions(SlotVisitor&);952 void determineLiveness(SlotVisitor&);953 954 void stronglyVisitStrongReferences(SlotVisitor&);955 void stronglyVisitWeakReferences(SlotVisitor&);956 void visitOSRExitTargets(SlotVisitor&);957 958 std::chrono::milliseconds timeSinceCreation()959 {960 return std::chrono::duration_cast<std::chrono::milliseconds>(961 std::chrono::steady_clock::now() - m_creationTime);962 }963 964 void createRareDataIfNecessary()965 {966 if (!m_rareData)967 m_rareData = std::make_unique<RareData>();968 }969 970 void insertBasicBlockBoundariesForControlFlowProfiler(RefCountedArray<Instruction>&);971 972 WriteBarrier<UnlinkedCodeBlock> m_unlinkedCode;973 int m_numParameters;974 union {975 unsigned m_debuggerRequests;976 struct {977 unsigned m_hasDebuggerStatement : 1;978 unsigned m_steppingMode : 1;979 unsigned m_numBreakpoints : 30;980 };981 };982 WriteBarrier<ExecutableBase> m_ownerExecutable;983 VM* m_vm;984 985 RefCountedArray<Instruction> m_instructions;986 VirtualRegister m_thisRegister;987 VirtualRegister m_scopeRegister;988 mutable CodeBlockHash m_hash;989 990 RefPtr<SourceProvider> m_source;991 unsigned m_sourceOffset;992 unsigned m_firstLineColumnOffset;993 994 RefCountedArray<LLIntCallLinkInfo> m_llintCallLinkInfos;995 SentinelLinkedList<LLIntCallLinkInfo, BasicRawSentinelNode<LLIntCallLinkInfo>> m_incomingLLIntCalls;996 StructureWatchpointMap m_llintGetByIdWatchpointMap;997 RefPtr<JITCode> m_jitCode;998 #if ENABLE(JIT)999 std::unique_ptr<RegisterAtOffsetList> m_calleeSaveRegisters;1000 Bag<StructureStubInfo> m_stubInfos;1001 Bag<JITAddIC> m_addICs;1002 Bag<JITMulIC> m_mulICs;1003 Bag<JITNegIC> m_negICs;1004 Bag<JITSubIC> m_subICs;1005 Bag<ByValInfo> m_byValInfos;1006 Bag<CallLinkInfo> m_callLinkInfos;1007 SentinelLinkedList<CallLinkInfo, BasicRawSentinelNode<CallLinkInfo>> m_incomingCalls;1008 SentinelLinkedList<PolymorphicCallNode, BasicRawSentinelNode<PolymorphicCallNode>> m_incomingPolymorphicCalls;1009 std::unique_ptr<PCToCodeOriginMap> m_pcToCodeOriginMap;1010 #endif1011 std::unique_ptr<CompactJITCodeMap> m_jitCodeMap;1012 #if ENABLE(DFG_JIT)1013 // This is relevant to non-DFG code blocks that serve as the profiled code block1014 // for DFG code blocks.1015 DFG::ExitProfile m_exitProfile;1016 CompressedLazyOperandValueProfileHolder m_lazyOperandValueProfiles;1017 #endif1018 RefCountedArray<ValueProfile> m_argumentValueProfiles;1019 RefCountedArray<ValueProfile> m_valueProfiles;1020 SegmentedVector<RareCaseProfile, 8> m_rareCaseProfiles;1021 RefCountedArray<ArrayAllocationProfile> m_arrayAllocationProfiles;1022 ArrayProfileVector m_arrayProfiles;1023 RefCountedArray<ObjectAllocationProfile> m_objectAllocationProfiles;1024 1025 // Constant Pool1026 COMPILE_ASSERT(sizeof(Register) == sizeof(WriteBarrier<Unknown>), Register_must_be_same_size_as_WriteBarrier_Unknown);1027 // TODO: This could just be a pointer to m_unlinkedCodeBlock's data, but the DFG mutates1028 // it, so we're stuck with it for now.1029 Vector<WriteBarrier<Unknown>> m_constantRegisters;1030 Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation;1031 RefCountedArray<WriteBarrier<FunctionExecutable>> m_functionDecls;1032 RefCountedArray<WriteBarrier<FunctionExecutable>> m_functionExprs;1033 1034 WriteBarrier<CodeBlock> m_alternative;1035 1036 BaselineExecutionCounter m_llintExecuteCounter;1037 1038 BaselineExecutionCounter m_jitExecuteCounter;1039 uint32_t m_osrExitCounter;1040 uint16_t m_optimizationDelayCounter;1041 uint16_t m_reoptimizationRetryCounter;1042 1043 std::chrono::steady_clock::time_point m_creationTime;1044 1045 std::unique_ptr<BytecodeLivenessAnalysis> m_livenessAnalysis;1046 1047 std::unique_ptr<RareData> m_rareData;1048 1049 UnconditionalFinalizer m_unconditionalFinalizer;1050 WeakReferenceHarvester m_weakReferenceHarvester;1051 };1052 1053 // Program code is not marked by any function, so we make the global object1054 // responsible for marking it.1055 1056 class GlobalCodeBlock : public CodeBlock {1057 typedef CodeBlock Base;1058 DECLARE_INFO;1059 1060 protected:1061 GlobalCodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, GlobalCodeBlock& other)1062 : CodeBlock(vm, structure, CopyParsedBlock, other)1063 {1064 }1065 1066 GlobalCodeBlock(VM* vm, Structure* structure, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)1067 : CodeBlock(vm, structure, ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, sourceOffset, firstLineColumnOffset)1068 {1069 }1070 };1071 35 1072 36 class ProgramCodeBlock : public GlobalCodeBlock { … … 1112 76 }; 1113 77 1114 class ModuleProgramCodeBlock : public GlobalCodeBlock {1115 public:1116 typedef GlobalCodeBlock Base;1117 DECLARE_INFO;1118 1119 static ModuleProgramCodeBlock* create(VM* vm, CopyParsedBlockTag, ModuleProgramCodeBlock& other)1120 {1121 ModuleProgramCodeBlock* instance = new (NotNull, allocateCell<ModuleProgramCodeBlock>(vm->heap))1122 ModuleProgramCodeBlock(vm, vm->moduleProgramCodeBlockStructure.get(), CopyParsedBlock, other);1123 instance->finishCreation(*vm, CopyParsedBlock, other);1124 return instance;1125 }1126 1127 static ModuleProgramCodeBlock* create(VM* vm, ModuleProgramExecutable* ownerExecutable, UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock,1128 JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset)1129 {1130 ModuleProgramCodeBlock* instance = new (NotNull, allocateCell<ModuleProgramCodeBlock>(vm->heap))1131 ModuleProgramCodeBlock(vm, vm->moduleProgramCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, firstLineColumnOffset);1132 instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);1133 return instance;1134 }1135 1136 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)1137 {1138 return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());1139 }1140 1141 private:1142 ModuleProgramCodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, ModuleProgramCodeBlock& other)1143 : GlobalCodeBlock(vm, structure, CopyParsedBlock, other)1144 {1145 }1146 1147 ModuleProgramCodeBlock(VM* vm, Structure* structure, ModuleProgramExecutable* ownerExecutable, UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock,1148 JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset)1149 : GlobalCodeBlock(vm, structure, ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, 0, firstLineColumnOffset)1150 {1151 }1152 1153 static void destroy(JSCell*);1154 };1155 1156 class EvalCodeBlock : public GlobalCodeBlock {1157 public:1158 typedef GlobalCodeBlock Base;1159 DECLARE_INFO;1160 1161 static EvalCodeBlock* create(VM* vm, CopyParsedBlockTag, EvalCodeBlock& other)1162 {1163 EvalCodeBlock* instance = new (NotNull, allocateCell<EvalCodeBlock>(vm->heap))1164 EvalCodeBlock(vm, vm->evalCodeBlockStructure.get(), CopyParsedBlock, other);1165 instance->finishCreation(*vm, CopyParsedBlock, other);1166 return instance;1167 }1168 1169 static EvalCodeBlock* create(VM* vm, EvalExecutable* ownerExecutable, UnlinkedEvalCodeBlock* unlinkedCodeBlock,1170 JSScope* scope, PassRefPtr<SourceProvider> sourceProvider)1171 {1172 EvalCodeBlock* instance = new (NotNull, allocateCell<EvalCodeBlock>(vm->heap))1173 EvalCodeBlock(vm, vm->evalCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, sourceProvider);1174 instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);1175 return instance;1176 }1177 1178 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)1179 {1180 return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());1181 }1182 1183 const Identifier& variable(unsigned index) { return unlinkedEvalCodeBlock()->variable(index); }1184 unsigned numVariables() { return unlinkedEvalCodeBlock()->numVariables(); }1185 1186 private:1187 EvalCodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, EvalCodeBlock& other)1188 : GlobalCodeBlock(vm, structure, CopyParsedBlock, other)1189 {1190 }1191 1192 EvalCodeBlock(VM* vm, Structure* structure, EvalExecutable* ownerExecutable, UnlinkedEvalCodeBlock* unlinkedCodeBlock,1193 JSScope* scope, PassRefPtr<SourceProvider> sourceProvider)1194 : GlobalCodeBlock(vm, structure, ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, 0, 1)1195 {1196 }1197 1198 static void destroy(JSCell*);1199 1200 private:1201 UnlinkedEvalCodeBlock* unlinkedEvalCodeBlock() const { return jsCast<UnlinkedEvalCodeBlock*>(unlinkedCodeBlock()); }1202 };1203 1204 class FunctionCodeBlock : public CodeBlock {1205 public:1206 typedef CodeBlock Base;1207 DECLARE_INFO;1208 1209 static FunctionCodeBlock* create(VM* vm, CopyParsedBlockTag, FunctionCodeBlock& other)1210 {1211 FunctionCodeBlock* instance = new (NotNull, allocateCell<FunctionCodeBlock>(vm->heap))1212 FunctionCodeBlock(vm, vm->functionCodeBlockStructure.get(), CopyParsedBlock, other);1213 instance->finishCreation(*vm, CopyParsedBlock, other);1214 return instance;1215 }1216 1217 static FunctionCodeBlock* create(VM* vm, FunctionExecutable* ownerExecutable, UnlinkedFunctionCodeBlock* unlinkedCodeBlock, JSScope* scope,1218 PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)1219 {1220 FunctionCodeBlock* instance = new (NotNull, allocateCell<FunctionCodeBlock>(vm->heap))1221 FunctionCodeBlock(vm, vm->functionCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, sourceOffset, firstLineColumnOffset);1222 instance->finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);1223 return instance;1224 }1225 1226 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)1227 {1228 return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());1229 }1230 1231 private:1232 FunctionCodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, FunctionCodeBlock& other)1233 : CodeBlock(vm, structure, CopyParsedBlock, other)1234 {1235 }1236 1237 FunctionCodeBlock(VM* vm, Structure* structure, FunctionExecutable* ownerExecutable, UnlinkedFunctionCodeBlock* unlinkedCodeBlock, JSScope* scope,1238 PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)1239 : CodeBlock(vm, structure, ownerExecutable, unlinkedCodeBlock, scope, sourceProvider, sourceOffset, firstLineColumnOffset)1240 {1241 }1242 1243 static void destroy(JSCell*);1244 };1245 1246 #if ENABLE(WEBASSEMBLY)1247 class WebAssemblyCodeBlock : public CodeBlock {1248 public:1249 typedef CodeBlock Base;1250 DECLARE_INFO;1251 1252 static WebAssemblyCodeBlock* create(VM* vm, CopyParsedBlockTag, WebAssemblyCodeBlock& other)1253 {1254 WebAssemblyCodeBlock* instance = new (NotNull, allocateCell<WebAssemblyCodeBlock>(vm->heap))1255 WebAssemblyCodeBlock(vm, vm->webAssemblyCodeBlockStructure.get(), CopyParsedBlock, other);1256 instance->finishCreation(*vm, CopyParsedBlock, other);1257 return instance;1258 }1259 1260 static WebAssemblyCodeBlock* create(VM* vm, WebAssemblyExecutable* ownerExecutable, JSGlobalObject* globalObject)1261 {1262 WebAssemblyCodeBlock* instance = new (NotNull, allocateCell<WebAssemblyCodeBlock>(vm->heap))1263 WebAssemblyCodeBlock(vm, vm->webAssemblyCodeBlockStructure.get(), ownerExecutable, globalObject);1264 instance->finishCreation(*vm, ownerExecutable, globalObject);1265 return instance;1266 }1267 1268 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)1269 {1270 return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());1271 }1272 1273 private:1274 WebAssemblyCodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, WebAssemblyCodeBlock& other)1275 : CodeBlock(vm, structure, CopyParsedBlock, other)1276 {1277 }1278 1279 WebAssemblyCodeBlock(VM* vm, Structure* structure, WebAssemblyExecutable* ownerExecutable, JSGlobalObject* globalObject)1280 : CodeBlock(vm, structure, ownerExecutable, globalObject)1281 {1282 }1283 1284 static void destroy(JSCell*);1285 };1286 #endif1287 1288 inline Register& ExecState::r(int index)1289 {1290 CodeBlock* codeBlock = this->codeBlock();1291 if (codeBlock->isConstantRegisterIndex(index))1292 return *reinterpret_cast<Register*>(&codeBlock->constantRegister(index));1293 return this[index];1294 }1295 1296 inline Register& ExecState::r(VirtualRegister reg)1297 {1298 return r(reg.offset());1299 }1300 1301 inline Register& ExecState::uncheckedR(int index)1302 {1303 RELEASE_ASSERT(index < FirstConstantRegisterIndex);1304 return this[index];1305 }1306 1307 inline Register& ExecState::uncheckedR(VirtualRegister reg)1308 {1309 return uncheckedR(reg.offset());1310 }1311 1312 inline void CodeBlock::clearVisitWeaklyHasBeenCalled()1313 {1314 m_visitWeaklyHasBeenCalled.store(false, std::memory_order_relaxed);1315 }1316 1317 template <typename Functor> inline void ScriptExecutable::forEachCodeBlock(Functor&& functor)1318 {1319 switch (type()) {1320 case ProgramExecutableType: {1321 if (CodeBlock* codeBlock = static_cast<CodeBlock*>(jsCast<ProgramExecutable*>(this)->m_programCodeBlock.get()))1322 codeBlock->forEachRelatedCodeBlock(std::forward<Functor>(functor));1323 break;1324 }1325 1326 case EvalExecutableType: {1327 if (CodeBlock* codeBlock = static_cast<CodeBlock*>(jsCast<EvalExecutable*>(this)->m_evalCodeBlock.get()))1328 codeBlock->forEachRelatedCodeBlock(std::forward<Functor>(functor));1329 break;1330 }1331 1332 case FunctionExecutableType: {1333 Functor f(std::forward<Functor>(functor));1334 FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);1335 if (CodeBlock* codeBlock = static_cast<CodeBlock*>(executable->m_codeBlockForCall.get()))1336 codeBlock->forEachRelatedCodeBlock(f);1337 if (CodeBlock* codeBlock = static_cast<CodeBlock*>(executable->m_codeBlockForConstruct.get()))1338 codeBlock->forEachRelatedCodeBlock(f);1339 break;1340 }1341 1342 case ModuleProgramExecutableType: {1343 if (CodeBlock* codeBlock = static_cast<CodeBlock*>(jsCast<ModuleProgramExecutable*>(this)->m_moduleProgramCodeBlock.get()))1344 codeBlock->forEachRelatedCodeBlock(std::forward<Functor>(functor));1345 break;1346 }1347 1348 default:1349 RELEASE_ASSERT_NOT_REACHED();1350 }1351 }1352 1353 template <typename ExecutableType>1354 JSObject* ScriptExecutable::prepareForExecution(VM& vm, JSFunction* function, JSScope* scope, CodeSpecializationKind kind, CodeBlock*& resultCodeBlock)1355 {1356 if (hasJITCodeFor(kind)) {1357 if (std::is_same<ExecutableType, EvalExecutable>::value)1358 resultCodeBlock = jsCast<CodeBlock*>(jsCast<EvalExecutable*>(this)->codeBlock());1359 else if (std::is_same<ExecutableType, ProgramExecutable>::value)1360 resultCodeBlock = jsCast<CodeBlock*>(jsCast<ProgramExecutable*>(this)->codeBlock());1361 else if (std::is_same<ExecutableType, ModuleProgramExecutable>::value)1362 resultCodeBlock = jsCast<CodeBlock*>(jsCast<ModuleProgramExecutable*>(this)->codeBlock());1363 else if (std::is_same<ExecutableType, FunctionExecutable>::value)1364 resultCodeBlock = jsCast<CodeBlock*>(jsCast<FunctionExecutable*>(this)->codeBlockFor(kind));1365 else1366 RELEASE_ASSERT_NOT_REACHED();1367 return nullptr;1368 }1369 return prepareForExecutionImpl(vm, function, scope, kind, resultCodeBlock);1370 }1371 1372 #define CODEBLOCK_LOG_EVENT(codeBlock, summary, details) \1373 (codeBlock->vm()->logEvent(codeBlock, summary, [&] () { return toCString details; }))1374 1375 78 } // namespace JSC
Note:
See TracChangeset
for help on using the changeset viewer.