UnlinkedCodeBlockGenerator.h
1 /* 2 * Copyright (C) 2019 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 27 #pragma once 28 29 #include "UnlinkedCodeBlock.h" 30 #include <wtf/Vector.h> 31 32 namespace JSC { 33 34 // FIXME: Create UnlinkedCodeBlock inside UnlinkedCodeBlockGenerator. 35 // https://bugs.webkit.org/show_bug.cgi?id=207212 36 class UnlinkedCodeBlockGenerator { 37 WTF_MAKE_FAST_ALLOCATED; 38 WTF_MAKE_NONCOPYABLE(UnlinkedCodeBlockGenerator) 39 public: 40 UnlinkedCodeBlockGenerator(VM& vm, UnlinkedCodeBlock* codeBlock) 41 : m_vm(vm) 42 , m_codeBlock(vm, codeBlock) 43 { 44 } 45 46 VM& vm() { return m_vm; } 47 48 bool isConstructor() const { return m_codeBlock->isConstructor(); } 49 ConstructorKind constructorKind() const { return m_codeBlock->constructorKind(); } 50 SuperBinding superBinding() const { return m_codeBlock->superBinding(); } 51 JSParserScriptMode scriptMode() const { return m_codeBlock->scriptMode(); } 52 NeedsClassFieldInitializer needsClassFieldInitializer() const { return m_codeBlock->needsClassFieldInitializer(); } 53 bool usesEval() const { return m_codeBlock->usesEval(); } 54 SourceParseMode parseMode() const { return m_codeBlock->parseMode(); } 55 bool isArrowFunction() { return m_codeBlock->isArrowFunction(); } 56 DerivedContextType derivedContextType() const { return m_codeBlock->derivedContextType(); } 57 EvalContextType evalContextType() const { return m_codeBlock->evalContextType(); } 58 bool isArrowFunctionContext() const { return m_codeBlock->isArrowFunctionContext(); } 59 bool isClassContext() const { return m_codeBlock->isClassContext(); } 60 unsigned numCalleeLocals() const { return m_codeBlock->m_numCalleeLocals; } 61 unsigned numVars() const { return m_codeBlock->m_numVars; } 62 unsigned numParameters() const { return m_codeBlock->numParameters(); } 63 VirtualRegister thisRegister() const { return m_codeBlock->thisRegister(); } 64 VirtualRegister scopeRegister() const { return m_codeBlock->scopeRegister(); } 65 bool wasCompiledWithDebuggingOpcodes() const { return m_codeBlock->wasCompiledWithDebuggingOpcodes(); } 66 bool hasCheckpoints() const { return m_codeBlock->hasCheckpoints(); } 67 bool hasTailCalls() const { return m_codeBlock->hasTailCalls(); } 68 69 // Updating UnlinkedCodeBlock. 70 void setHasCheckpoints() { m_codeBlock->setHasCheckpoints(); } 71 void setHasTailCalls() { m_codeBlock->setHasTailCalls(); } 72 void setNumCalleeLocals(unsigned numCalleeLocals) { m_codeBlock->m_numCalleeLocals = numCalleeLocals; } 73 void setNumVars(unsigned numVars) { m_codeBlock->m_numVars = numVars; } 74 void setThisRegister(VirtualRegister thisRegister) { m_codeBlock->setThisRegister(thisRegister); } 75 void setScopeRegister(VirtualRegister thisRegister) { m_codeBlock->setScopeRegister(thisRegister); } 76 void setNumParameters(unsigned newValue) { m_codeBlock->setNumParameters(newValue); } 77 78 UnlinkedMetadataTable& metadata() { return m_codeBlock->metadata(); } 79 void addExpressionInfo(unsigned instructionOffset, int divot, int startOffset, int endOffset, unsigned line, unsigned column); 80 void addTypeProfilerExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot); 81 void addOpProfileControlFlowBytecodeOffset(InstructionStream::Offset offset) 82 { 83 m_opProfileControlFlowBytecodeOffsets.append(offset); 84 } 85 86 size_t numberOfJumpTargets() const { return m_jumpTargets.size(); } 87 void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); } 88 unsigned jumpTarget(int index) const { return m_jumpTargets[index]; } 89 unsigned lastJumpTarget() const { return m_jumpTargets.last(); } 90 91 size_t numberOfSwitchJumpTables() const { return m_switchJumpTables.size(); } 92 UnlinkedSimpleJumpTable& addSwitchJumpTable() { m_switchJumpTables.append(UnlinkedSimpleJumpTable()); return m_switchJumpTables.last(); } 93 UnlinkedSimpleJumpTable& switchJumpTable(int tableIndex) { return m_switchJumpTables[tableIndex]; } 94 95 size_t numberOfStringSwitchJumpTables() const { return m_stringSwitchJumpTables.size(); } 96 UnlinkedStringJumpTable& addStringSwitchJumpTable() { m_stringSwitchJumpTables.append(UnlinkedStringJumpTable()); return m_stringSwitchJumpTables.last(); } 97 UnlinkedStringJumpTable& stringSwitchJumpTable(int tableIndex) { return m_stringSwitchJumpTables[tableIndex]; } 98 99 size_t numberOfExceptionHandlers() const { return m_exceptionHandlers.size(); } 100 UnlinkedHandlerInfo& exceptionHandler(int index) { return m_exceptionHandlers[index]; } 101 void addExceptionHandler(const UnlinkedHandlerInfo& handler) { m_exceptionHandlers.append(handler); } 102 UnlinkedHandlerInfo* handlerForBytecodeIndex(BytecodeIndex, RequiredHandler = RequiredHandler::AnyHandler); 103 UnlinkedHandlerInfo* handlerForIndex(unsigned, RequiredHandler = RequiredHandler::AnyHandler); 104 105 BitVector& bitVector(size_t i) { return m_bitVectors[i]; } 106 unsigned addBitVector(BitVector&& bitVector) 107 { 108 m_bitVectors.append(WTFMove(bitVector)); 109 return m_bitVectors.size() - 1; 110 } 111 112 unsigned numberOfConstantIdentifierSets() const { return m_constantIdentifierSets.size(); } 113 const Vector<ConstantIdentifierSetEntry>& constantIdentifierSets() { return m_constantIdentifierSets; } 114 void addSetConstant(IdentifierSet& set) 115 { 116 ASSERT(m_vm.heap.isDeferred()); 117 unsigned result = m_constantRegisters.size(); 118 m_constantRegisters.append(WriteBarrier<Unknown>()); 119 m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other); 120 m_constantIdentifierSets.append(ConstantIdentifierSetEntry(set, result)); 121 } 122 123 const WriteBarrier<Unknown>& constantRegister(VirtualRegister reg) const { return m_constantRegisters[reg.toConstantIndex()]; } 124 const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; } 125 ALWAYS_INLINE JSValue getConstant(VirtualRegister reg) const { return m_constantRegisters[reg.toConstantIndex()].get(); } 126 const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation() { return m_constantsSourceCodeRepresentation; } 127 128 unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other) 129 { 130 ASSERT(m_vm.heap.isDeferred()); 131 unsigned result = m_constantRegisters.size(); 132 m_constantRegisters.append(WriteBarrier<Unknown>()); 133 m_constantRegisters.last().setWithoutWriteBarrier(v); 134 m_constantsSourceCodeRepresentation.append(sourceCodeRepresentation); 135 return result; 136 } 137 unsigned addConstant(LinkTimeConstant linkTimeConstant) 138 { 139 ASSERT(m_vm.heap.isDeferred()); 140 unsigned result = m_constantRegisters.size(); 141 m_constantRegisters.append(WriteBarrier<Unknown>()); 142 m_constantRegisters.last().setWithoutWriteBarrier(jsNumber(static_cast<int32_t>(linkTimeConstant))); 143 m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::LinkTimeConstant); 144 return result; 145 } 146 147 unsigned addFunctionDecl(UnlinkedFunctionExecutable* n) 148 { 149 ASSERT(m_vm.heap.isDeferred()); 150 unsigned size = m_functionDecls.size(); 151 m_functionDecls.append(WriteBarrier<UnlinkedFunctionExecutable>()); 152 m_functionDecls.last().setWithoutWriteBarrier(n); 153 return size; 154 } 155 156 unsigned addFunctionExpr(UnlinkedFunctionExecutable* n) 157 { 158 unsigned size = m_functionExprs.size(); 159 m_functionExprs.append(WriteBarrier<UnlinkedFunctionExecutable>()); 160 m_functionExprs.last().setWithoutWriteBarrier(n); 161 return size; 162 } 163 164 size_t numberOfIdentifiers() const { return m_identifiers.size(); } 165 const Identifier& identifier(int index) const { return m_identifiers[index]; } 166 void addIdentifier(const Identifier& i) { return m_identifiers.append(i); } 167 168 using OutOfLineJumpTargets = HashMap<InstructionStream::Offset, int>; 169 void addOutOfLineJumpTarget(InstructionStream::Offset, int target); 170 int outOfLineJumpOffset(InstructionStream::Offset); 171 int outOfLineJumpOffset(const InstructionStream::Ref& instruction) 172 { 173 return outOfLineJumpOffset(instruction.offset()); 174 } 175 OutOfLineJumpTargets replaceOutOfLineJumpTargets() 176 { 177 OutOfLineJumpTargets newJumpTargets; 178 std::swap(m_outOfLineJumpTargets, newJumpTargets); 179 return newJumpTargets; 180 } 181 182 size_t metadataSizeInBytes() { return m_codeBlock->metadataSizeInBytes(); } 183 184 void getLineAndColumn(const ExpressionRangeInfo&, unsigned& line, unsigned& column) const; 185 186 void applyModification(BytecodeRewriter&, InstructionStreamWriter&); 187 188 void finalize(std::unique_ptr<InstructionStream>); 189 190 void dump(PrintStream&) const; 191 192 private: 193 VM& m_vm; 194 Strong<UnlinkedCodeBlock> m_codeBlock; 195 // In non-RareData. 196 Vector<InstructionStream::Offset> m_jumpTargets; 197 Vector<Identifier> m_identifiers; 198 Vector<WriteBarrier<Unknown>> m_constantRegisters; 199 Vector<SourceCodeRepresentation> m_constantsSourceCodeRepresentation; 200 Vector<WriteBarrier<UnlinkedFunctionExecutable>> m_functionDecls; 201 Vector<WriteBarrier<UnlinkedFunctionExecutable>> m_functionExprs; 202 Vector<ExpressionRangeInfo> m_expressionInfo; 203 OutOfLineJumpTargets m_outOfLineJumpTargets; 204 // In RareData. 205 Vector<UnlinkedHandlerInfo> m_exceptionHandlers; 206 Vector<UnlinkedSimpleJumpTable> m_switchJumpTables; 207 Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables; 208 Vector<ExpressionRangeInfo::FatPosition> m_expressionInfoFatPositions; 209 HashMap<unsigned, UnlinkedCodeBlock::RareData::TypeProfilerExpressionRange> m_typeProfilerInfoMap; 210 Vector<InstructionStream::Offset> m_opProfileControlFlowBytecodeOffsets; 211 Vector<BitVector> m_bitVectors; 212 Vector<ConstantIdentifierSetEntry> m_constantIdentifierSets; 213 }; 214 215 } // namespace JSC