Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (255458 => 255459)
--- trunk/Source/_javascript_Core/ChangeLog 2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/ChangeLog 2020-01-30 22:32:43 UTC (rev 255459)
@@ -1,3 +1,79 @@
+2020-01-30 Yusuke Suzuki <[email protected]>
+
+ [JSC] Remove unnecessary allocations in BytecodeBasicBlock
+ https://bugs.webkit.org/show_bug.cgi?id=206986
+
+ Reviewed by Mark Lam.
+
+ We know that BytecodeBasicBlock itself takes 2MB in Gmail. And each BytecodeBasicBlock has Vector<unsigned>
+ and Vector<BytecodeBasicBlock*>.
+
+ BytecodeBasicBlock holds all the offset per bytecode as unsigned in m_offsets. But this offset is
+ only used when reverse iterating a bytecode in a BytecodeBasicBlock. We can hold a length of each
+ bytecode instead, which is much smaller (unsigned v.s. uint8_t).
+
+ Since each BytecodeBasicBlock has index, we should hold successors in Vector<unsigned> instead of Vector<BytecodeBasicBlock*>.
+
+ We are also allocating BytecodeBasicBlock in makeUnique<> and having them in Vector<std::unique_ptr<BytecodeBasicBlock>>.
+ But this is not necessary since only BytecodeBasicBlock::compute can modify this vector. We should generate Vector<BytecodeBasicBlock>
+ from BytecodeBasicBlock::compute.
+
+ We are also planning purging BytecodeBasicBlock in UnlinkedCodeBlock if it is not used so much. But this will be done in a separate patch.
+
+ * bytecode/BytecodeBasicBlock.cpp:
+ (JSC::BytecodeBasicBlock::BytecodeBasicBlock):
+ (JSC::BytecodeBasicBlock::addLength):
+ (JSC::BytecodeBasicBlock::shrinkToFit):
+ (JSC::BytecodeBasicBlock::computeImpl):
+ (JSC::BytecodeBasicBlock::compute):
+ * bytecode/BytecodeBasicBlock.h:
+ (JSC::BytecodeBasicBlock::delta const):
+ (JSC::BytecodeBasicBlock::successors const):
+ (JSC::BytecodeBasicBlock::operator bool const):
+ (JSC::BytecodeBasicBlock::addSuccessor):
+ (JSC::BytecodeBasicBlock::offsets const): Deleted.
+ (JSC::BytecodeBasicBlock:: const): Deleted.
+ (JSC::BytecodeBasicBlock::BytecodeBasicBlock): Deleted.
+ (JSC::BytecodeBasicBlock::addLength): Deleted.
+ * bytecode/BytecodeGeneratorification.cpp:
+ (JSC::BytecodeGeneratorification::BytecodeGeneratorification):
+ * bytecode/BytecodeGraph.h:
+ (JSC::BytecodeGraph::blockContainsBytecodeOffset):
+ (JSC::BytecodeGraph::findBasicBlockForBytecodeOffset):
+ (JSC::BytecodeGraph::findBasicBlockWithLeaderOffset):
+ (JSC::BytecodeGraph::at const):
+ (JSC::BytecodeGraph::operator[] const):
+ (JSC::BytecodeGraph::begin):
+ (JSC::BytecodeGraph::end):
+ (JSC::BytecodeGraph::first):
+ (JSC::BytecodeGraph::last):
+ (JSC::BytecodeGraph::BytecodeGraph):
+ (JSC::BytecodeGraph::begin const): Deleted.
+ (JSC::BytecodeGraph::end const): Deleted.
+ * bytecode/BytecodeLivenessAnalysis.cpp:
+ (JSC::BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeIndex):
+ (JSC::BytecodeLivenessAnalysis::computeFullLiveness):
+ (JSC::BytecodeLivenessAnalysis::computeKills):
+ (JSC::BytecodeLivenessAnalysis::dumpResults):
+ * bytecode/BytecodeLivenessAnalysis.h:
+ * bytecode/BytecodeLivenessAnalysisInlines.h:
+ (JSC::BytecodeLivenessPropagation::computeLocalLivenessForBytecodeIndex):
+ (JSC::BytecodeLivenessPropagation::computeLocalLivenessForBlock):
+ (JSC::BytecodeLivenessPropagation::getLivenessInfoAtBytecodeIndex):
+ (JSC::BytecodeLivenessPropagation::runLivenessFixpoint):
+ * bytecode/InstructionStream.h:
+ (JSC::InstructionStream::MutableRef::operator-> const):
+ (JSC::InstructionStream::MutableRef::ptr const):
+ (JSC::InstructionStream::MutableRef::unwrap const):
+ * bytecode/Opcode.h:
+ * generator/Section.rb:
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ * llint/LLIntData.cpp:
+ (JSC::LLInt::initialize):
+ * llint/LowLevelInterpreter.cpp:
+ (JSC::CLoop::execute):
+
2020-01-30 Alexey Shvayka <[email protected]>
Incomplete braced quantifiers should be banned in Unicode patterns only
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeBasicBlock.cpp (255458 => 255459)
--- trunk/Source/_javascript_Core/bytecode/BytecodeBasicBlock.cpp 2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeBasicBlock.cpp 2020-01-30 22:32:43 UTC (rev 255459)
@@ -35,9 +35,30 @@
DEFINE_ALLOCATOR_WITH_HEAP_IDENTIFIER(BytecodeBasicBlock);
+BytecodeBasicBlock::BytecodeBasicBlock(const InstructionStream::Ref& instruction, unsigned blockIndex)
+ : m_leaderOffset(instruction.offset())
+ , m_totalLength(0)
+ , m_index(blockIndex)
+{
+ addLength(instruction->size());
+}
+
+BytecodeBasicBlock::BytecodeBasicBlock(BytecodeBasicBlock::SpecialBlockType blockType, unsigned blockIndex)
+ : m_leaderOffset(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX)
+ , m_totalLength(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX)
+ , m_index(blockIndex)
+{
+}
+
+void BytecodeBasicBlock::addLength(unsigned bytecodeLength)
+{
+ m_delta.append(bytecodeLength);
+ m_totalLength += bytecodeLength;
+}
+
void BytecodeBasicBlock::shrinkToFit()
{
- m_offsets.shrinkToFit();
+ m_delta.shrinkToFit();
m_successors.shrinkToFit();
}
@@ -50,76 +71,80 @@
}
template<typename Block>
-void BytecodeBasicBlock::computeImpl(Block* codeBlock, const InstructionStream& instructions, Vector<std::unique_ptr<BytecodeBasicBlock>>& basicBlocks)
+auto BytecodeBasicBlock::computeImpl(Block* codeBlock, const InstructionStream& instructions) -> BasicBlockVector
{
+ BasicBlockVector basicBlocks;
Vector<InstructionStream::Offset, 32> jumpTargets;
computePreciseJumpTargets(codeBlock, instructions, jumpTargets);
- auto appendBlock = [&] (std::unique_ptr<BytecodeBasicBlock>&& block) {
- block->m_index = basicBlocks.size();
- basicBlocks.append(WTFMove(block));
+ auto linkBlocks = [&] (BytecodeBasicBlock& from, BytecodeBasicBlock& to) {
+ from.addSuccessor(to);
};
- auto linkBlocks = [&] (BytecodeBasicBlock* from, BytecodeBasicBlock* to) {
- from->addSuccessor(to);
- };
+ {
+ // Create the entry and exit basic blocks.
+ basicBlocks.reserveCapacity(jumpTargets.size() + 2);
+ {
+ // Entry block.
+ basicBlocks.constructAndAppend(BytecodeBasicBlock::EntryBlock, basicBlocks.size());
+ // First block.
+ basicBlocks.constructAndAppend(BytecodeBasicBlock::EntryBlock, basicBlocks.size());
+ linkBlocks(basicBlocks[0], basicBlocks[1]);
+ }
- // Create the entry and exit basic blocks.
- basicBlocks.reserveCapacity(jumpTargets.size() + 2);
+ BytecodeBasicBlock* current = &basicBlocks.last();
+ auto appendBlock = [&] (const InstructionStream::Ref& instruction) -> BytecodeBasicBlock* {
+ basicBlocks.constructAndAppend(instruction, basicBlocks.size());
+ return &basicBlocks.last();
+ };
+ bool nextInstructionIsLeader = false;
+ for (const auto& instruction : instructions) {
+ auto bytecodeOffset = instruction.offset();
+ OpcodeID opcodeID = instruction->opcodeID();
- auto entry = makeUnique<BytecodeBasicBlock>(BytecodeBasicBlock::EntryBlock);
- auto firstBlock = makeUnique<BytecodeBasicBlock>(BytecodeBasicBlock::EntryBlock);
- linkBlocks(entry.get(), firstBlock.get());
+ bool createdBlock = false;
+ // If the current bytecode is a jump target, then it's the leader of its own basic block.
+ if (nextInstructionIsLeader || isJumpTarget(opcodeID, jumpTargets, bytecodeOffset)) {
+ current = appendBlock(instruction);
+ createdBlock = true;
+ nextInstructionIsLeader = false;
+ }
- appendBlock(WTFMove(entry));
- BytecodeBasicBlock* current = firstBlock.get();
- appendBlock(WTFMove(firstBlock));
+ // If the current bytecode is a branch or a return, then the next instruction is the leader of its own basic block.
+ if (isBranch(opcodeID) || isTerminal(opcodeID) || isThrow(opcodeID))
+ nextInstructionIsLeader = true;
- auto exit = makeUnique<BytecodeBasicBlock>(BytecodeBasicBlock::ExitBlock);
+ if (createdBlock)
+ continue;
- bool nextInstructionIsLeader = false;
-
- for (const auto& instruction : instructions) {
- auto bytecodeOffset = instruction.offset();
- OpcodeID opcodeID = instruction->opcodeID();
-
- bool createdBlock = false;
- // If the current bytecode is a jump target, then it's the leader of its own basic block.
- if (isJumpTarget(opcodeID, jumpTargets, bytecodeOffset) || nextInstructionIsLeader) {
- auto newBlock = makeUnique<BytecodeBasicBlock>(instruction);
- current = newBlock.get();
- appendBlock(WTFMove(newBlock));
- createdBlock = true;
- nextInstructionIsLeader = false;
+ // Otherwise, just add to the length of the current block.
+ current->addLength(instruction->size());
}
-
- // If the current bytecode is a branch or a return, then the next instruction is the leader of its own basic block.
- if (isBranch(opcodeID) || isTerminal(opcodeID) || isThrow(opcodeID))
- nextInstructionIsLeader = true;
-
- if (createdBlock)
- continue;
-
- // Otherwise, just add to the length of the current block.
- current->addLength(instruction->size());
+ // Exit block.
+ basicBlocks.constructAndAppend(BytecodeBasicBlock::ExitBlock, basicBlocks.size());
+ basicBlocks.shrinkToFit();
+ ASSERT(basicBlocks.last().isExitBlock());
}
+ // After this point, we never change basicBlocks.
// Link basic blocks together.
for (unsigned i = 0; i < basicBlocks.size(); i++) {
- BytecodeBasicBlock* block = basicBlocks[i].get();
+ BytecodeBasicBlock& block = basicBlocks[i];
- if (block->isEntryBlock() || block->isExitBlock())
+ if (block.isEntryBlock() || block.isExitBlock())
continue;
bool fallsThrough = true;
- for (auto bytecodeOffset : block->offsets()) {
- auto instruction = instructions.at(bytecodeOffset);
+ for (unsigned visitedLength = 0; visitedLength < block.totalLength();) {
+ InstructionStream::Ref instruction = instructions.at(block.leaderOffset() + visitedLength);
OpcodeID opcodeID = instruction->opcodeID();
+ visitedLength += instruction->size();
+
// If we found a terminal bytecode, link to the exit block.
if (isTerminal(opcodeID)) {
- ASSERT(bytecodeOffset + instruction->size() == block->leaderOffset() + block->totalLength());
- linkBlocks(block, exit.get());
+ ASSERT(instruction.offset() + instruction->size() == block.leaderOffset() + block.totalLength());
+ linkBlocks(block, basicBlocks.last());
fallsThrough = false;
break;
}
@@ -128,16 +153,15 @@
// If there isn't one, treat this throw as a terminal. This is true even if we have a finally
// block because the finally block will create its own catch, which will generate a HandlerInfo.
if (isThrow(opcodeID)) {
- ASSERT(bytecodeOffset + instruction->size() == block->leaderOffset() + block->totalLength());
+ ASSERT(instruction.offset() + instruction->size() == block.leaderOffset() + block.totalLength());
auto* handler = codeBlock->handlerForBytecodeIndex(BytecodeIndex(instruction.offset()));
fallsThrough = false;
if (!handler) {
- linkBlocks(block, exit.get());
+ linkBlocks(block, basicBlocks.last());
break;
}
- for (unsigned i = 0; i < basicBlocks.size(); i++) {
- BytecodeBasicBlock* otherBlock = basicBlocks[i].get();
- if (handler->target == otherBlock->leaderOffset()) {
+ for (auto& otherBlock : basicBlocks) {
+ if (handler->target == otherBlock.leaderOffset()) {
linkBlocks(block, otherBlock);
break;
}
@@ -147,15 +171,14 @@
// If we found a branch, link to the block(s) that we jump to.
if (isBranch(opcodeID)) {
- ASSERT(bytecodeOffset + instruction->size() == block->leaderOffset() + block->totalLength());
+ ASSERT(instruction.offset() + instruction->size() == block.leaderOffset() + block.totalLength());
Vector<InstructionStream::Offset, 1> bytecodeOffsetsJumpedTo;
findJumpTargetsForInstruction(codeBlock, instruction, bytecodeOffsetsJumpedTo);
size_t numberOfJumpTargets = bytecodeOffsetsJumpedTo.size();
ASSERT(numberOfJumpTargets);
- for (unsigned i = 0; i < basicBlocks.size(); i++) {
- BytecodeBasicBlock* otherBlock = basicBlocks[i].get();
- if (bytecodeOffsetsJumpedTo.contains(otherBlock->leaderOffset())) {
+ for (auto& otherBlock : basicBlocks) {
+ if (bytecodeOffsetsJumpedTo.contains(otherBlock.leaderOffset())) {
linkBlocks(block, otherBlock);
--numberOfJumpTargets;
if (!numberOfJumpTargets)
@@ -178,25 +201,28 @@
// If we fall through then link to the next block in program order.
if (fallsThrough) {
ASSERT(i + 1 < basicBlocks.size());
- BytecodeBasicBlock* nextBlock = basicBlocks[i + 1].get();
+ BytecodeBasicBlock& nextBlock = basicBlocks[i + 1];
linkBlocks(block, nextBlock);
}
}
- appendBlock(WTFMove(exit));
+ unsigned index = 0;
+ for (auto& basicBlock : basicBlocks) {
+ basicBlock.shrinkToFit();
+ ASSERT_UNUSED(index, basicBlock.index() == index++);
+ }
- for (auto& basicBlock : basicBlocks)
- basicBlock->shrinkToFit();
+ return basicBlocks;
}
-void BytecodeBasicBlock::compute(CodeBlock* codeBlock, const InstructionStream& instructions, Vector<std::unique_ptr<BytecodeBasicBlock>>& basicBlocks)
+auto BytecodeBasicBlock::compute(CodeBlock* codeBlock, const InstructionStream& instructions) -> BasicBlockVector
{
- computeImpl(codeBlock, instructions, basicBlocks);
+ return computeImpl(codeBlock, instructions);
}
-void BytecodeBasicBlock::compute(UnlinkedCodeBlock* codeBlock, const InstructionStream& instructions, Vector<std::unique_ptr<BytecodeBasicBlock>>& basicBlocks)
+auto BytecodeBasicBlock::compute(UnlinkedCodeBlock* codeBlock, const InstructionStream& instructions) -> BasicBlockVector
{
- computeImpl(codeBlock, instructions, basicBlocks);
+ return computeImpl(codeBlock, instructions);
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeBasicBlock.h (255458 => 255459)
--- trunk/Source/_javascript_Core/bytecode/BytecodeBasicBlock.h 2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeBasicBlock.h 2020-01-30 22:32:43 UTC (rev 255459)
@@ -26,12 +26,15 @@
#pragma once
#include "InstructionStream.h"
+#include "Opcode.h"
#include <limits.h>
#include <wtf/FastBitVector.h>
+#include <wtf/PackedIntVector.h>
#include <wtf/Vector.h>
namespace JSC {
+class BytecodeGraph;
class CodeBlock;
class UnlinkedCodeBlock;
struct Instruction;
@@ -39,13 +42,18 @@
DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(BytecodeBasicBlock);
class BytecodeBasicBlock {
- WTF_MAKE_STRUCT_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(BytecodeBasicBlock);
+ WTF_MAKE_FAST_ALLOCATED(BytecodeBasicBlock);
+ WTF_MAKE_NONCOPYABLE(BytecodeBasicBlock);
+ friend class BytecodeGraph;
public:
+ using BasicBlockVector = Vector<BytecodeBasicBlock, 0, UnsafeVectorOverflow, 16, BytecodeBasicBlockMalloc>;
+ static_assert(maxOpcodeLength <= UINT8_MAX);
enum SpecialBlockType { EntryBlock, ExitBlock };
- BytecodeBasicBlock(const InstructionStream::Ref&);
- BytecodeBasicBlock(SpecialBlockType);
- void shrinkToFit();
+ inline BytecodeBasicBlock(const InstructionStream::Ref&, unsigned blockIndex);
+ inline BytecodeBasicBlock(SpecialBlockType, unsigned blockIndex);
+ BytecodeBasicBlock(BytecodeBasicBlock&&) = default;
+
bool isEntryBlock() { return !m_leaderOffset && !m_totalLength; }
bool isExitBlock() { return m_leaderOffset == UINT_MAX && m_totalLength == UINT_MAX; }
@@ -52,53 +60,36 @@
unsigned leaderOffset() const { return m_leaderOffset; }
unsigned totalLength() const { return m_totalLength; }
- const Vector<InstructionStream::Offset>& offsets() const { return m_offsets; }
+ const Vector<uint8_t>& delta() const { return m_delta; }
+ const Vector<unsigned>& successors() const { return m_successors; }
- const Vector<BytecodeBasicBlock*>& successors() const { return m_successors; }
-
FastBitVector& in() { return m_in; }
FastBitVector& out() { return m_out; }
unsigned index() const { return m_index; }
- static void compute(CodeBlock*, const InstructionStream& instructions, Vector<std::unique_ptr<BytecodeBasicBlock>>&);
- static void compute(UnlinkedCodeBlock*, const InstructionStream& instructions, Vector<std::unique_ptr<BytecodeBasicBlock>>&);
+ explicit operator bool() const { return true; }
private:
- template<typename Block> static void computeImpl(Block* codeBlock, const InstructionStream& instructions, Vector<std::unique_ptr<BytecodeBasicBlock>>& basicBlocks);
+ // Only called from BytecodeGraph.
+ static BasicBlockVector compute(CodeBlock*, const InstructionStream& instructions);
+ static BasicBlockVector compute(UnlinkedCodeBlock*, const InstructionStream& instructions);
+ template<typename Block> static BasicBlockVector computeImpl(Block* codeBlock, const InstructionStream& instructions);
+ void shrinkToFit();
- void addSuccessor(BytecodeBasicBlock* block) { m_successors.append(block); }
+ void addSuccessor(BytecodeBasicBlock& block) { m_successors.append(block.index()); }
- void addLength(unsigned);
+ inline void addLength(unsigned);
InstructionStream::Offset m_leaderOffset;
unsigned m_totalLength;
unsigned m_index;
- Vector<InstructionStream::Offset> m_offsets;
- Vector<BytecodeBasicBlock*> m_successors;
+ Vector<uint8_t> m_delta;
+ Vector<unsigned> m_successors;
FastBitVector m_in;
FastBitVector m_out;
};
-inline BytecodeBasicBlock::BytecodeBasicBlock(const InstructionStream::Ref& instruction)
- : m_leaderOffset(instruction.offset())
- , m_totalLength(instruction->size())
-{
- m_offsets.append(m_leaderOffset);
-}
-
-inline BytecodeBasicBlock::BytecodeBasicBlock(BytecodeBasicBlock::SpecialBlockType blockType)
- : m_leaderOffset(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX)
- , m_totalLength(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX)
-{
-}
-
-inline void BytecodeBasicBlock::addLength(unsigned bytecodeLength)
-{
- m_offsets.append(m_leaderOffset + m_totalLength);
- m_totalLength += bytecodeLength;
-}
-
} // namespace JSC
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeGeneratorification.cpp (255458 => 255459)
--- trunk/Source/_javascript_Core/bytecode/BytecodeGeneratorification.cpp 2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeGeneratorification.cpp 2020-01-30 22:32:43 UTC (rev 255459)
@@ -72,41 +72,38 @@
, m_generatorFrameSymbolTable(codeBlock->vm(), generatorFrameSymbolTable)
, m_generatorFrameSymbolTableIndex(generatorFrameSymbolTableIndex)
{
- for (BytecodeBasicBlock* block : m_graph) {
- for (const auto offset : block->offsets()) {
- const auto instruction = m_instructions.at(offset);
- switch (instruction->opcodeID()) {
- case op_enter: {
- m_enterPoint = instruction.offset();
- break;
- }
+ for (const auto& instruction : m_instructions) {
+ switch (instruction->opcodeID()) {
+ case op_enter: {
+ m_enterPoint = instruction.offset();
+ break;
+ }
- case op_yield: {
- auto bytecode = instruction->as<OpYield>();
- unsigned liveCalleeLocalsIndex = bytecode.m_yieldPoint;
- if (liveCalleeLocalsIndex >= m_yields.size())
- m_yields.resize(liveCalleeLocalsIndex + 1);
- YieldData& data = ""
- data.point = instruction.offset();
- data.argument = bytecode.m_argument;
- break;
- }
+ case op_yield: {
+ auto bytecode = instruction->as<OpYield>();
+ unsigned liveCalleeLocalsIndex = bytecode.m_yieldPoint;
+ if (liveCalleeLocalsIndex >= m_yields.size())
+ m_yields.resize(liveCalleeLocalsIndex + 1);
+ YieldData& data = ""
+ data.point = instruction.offset();
+ data.argument = bytecode.m_argument;
+ break;
+ }
- case op_create_generator_frame_environment: {
- auto bytecode = instruction->as<OpCreateGeneratorFrameEnvironment>();
- GeneratorFrameData data;
- data.m_point = instruction.offset();
- data.m_dst = bytecode.m_dst;
- data.m_scope = bytecode.m_scope;
- data.m_symbolTable = bytecode.m_symbolTable;
- data.m_initialValue = bytecode.m_initialValue;
- m_generatorFrameData = WTFMove(data);
- break;
- }
+ case op_create_generator_frame_environment: {
+ auto bytecode = instruction->as<OpCreateGeneratorFrameEnvironment>();
+ GeneratorFrameData data;
+ data.m_point = instruction.offset();
+ data.m_dst = bytecode.m_dst;
+ data.m_scope = bytecode.m_scope;
+ data.m_symbolTable = bytecode.m_symbolTable;
+ data.m_initialValue = bytecode.m_initialValue;
+ m_generatorFrameData = WTFMove(data);
+ break;
+ }
- default:
- break;
- }
+ default:
+ break;
}
}
}
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeGraph.h (255458 => 255459)
--- trunk/Source/_javascript_Core/bytecode/BytecodeGraph.h 2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeGraph.h 2020-01-30 22:32:43 UTC (rev 255459)
@@ -39,7 +39,7 @@
WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(BytecodeGraph);
public:
- typedef Vector<std::unique_ptr<BytecodeBasicBlock>> BasicBlocksVector;
+ using BasicBlocksVector = BytecodeBasicBlock::BasicBlockVector;
typedef WTF::IndexedContainerIterator<BytecodeGraph> iterator;
@@ -51,10 +51,10 @@
return WTF::makeIteratorRange(m_basicBlocks.rbegin(), m_basicBlocks.rend());
}
- static bool blockContainsBytecodeOffset(BytecodeBasicBlock* block, InstructionStream::Offset bytecodeOffset)
+ static bool blockContainsBytecodeOffset(const BytecodeBasicBlock& block, InstructionStream::Offset bytecodeOffset)
{
- unsigned leaderOffset = block->leaderOffset();
- return bytecodeOffset >= leaderOffset && bytecodeOffset < leaderOffset + block->totalLength();
+ unsigned leaderOffset = block.leaderOffset();
+ return bytecodeOffset >= leaderOffset && bytecodeOffset < leaderOffset + block.totalLength();
}
BytecodeBasicBlock* findBasicBlockForBytecodeOffset(InstructionStream::Offset bytecodeOffset)
@@ -61,43 +61,43 @@
{
/*
for (unsigned i = 0; i < m_basicBlocks.size(); i++) {
- if (blockContainsBytecodeOffset(m_basicBlocks[i].get(), bytecodeOffset))
- return m_basicBlocks[i].get();
+ if (blockContainsBytecodeOffset(m_basicBlocks[i], bytecodeOffset))
+ return &m_basicBlocks[i];
}
return 0;
*/
- std::unique_ptr<BytecodeBasicBlock>* basicBlock = approximateBinarySearch<std::unique_ptr<BytecodeBasicBlock>, unsigned>(m_basicBlocks, m_basicBlocks.size(), bytecodeOffset, [] (std::unique_ptr<BytecodeBasicBlock>* basicBlock) { return (*basicBlock)->leaderOffset(); });
+ BytecodeBasicBlock* basicBlock = approximateBinarySearch<BytecodeBasicBlock, unsigned>(m_basicBlocks, m_basicBlocks.size(), bytecodeOffset, [] (BytecodeBasicBlock* basicBlock) { return basicBlock->leaderOffset(); });
// We found the block we were looking for.
- if (blockContainsBytecodeOffset((*basicBlock).get(), bytecodeOffset))
- return (*basicBlock).get();
+ if (blockContainsBytecodeOffset(*basicBlock, bytecodeOffset))
+ return basicBlock;
// Basic block is to the left of the returned block.
- if (bytecodeOffset < (*basicBlock)->leaderOffset()) {
+ if (bytecodeOffset < basicBlock->leaderOffset()) {
ASSERT(basicBlock - 1 >= m_basicBlocks.data());
- ASSERT(blockContainsBytecodeOffset(basicBlock[-1].get(), bytecodeOffset));
- return basicBlock[-1].get();
+ ASSERT(blockContainsBytecodeOffset(basicBlock[-1], bytecodeOffset));
+ return &basicBlock[-1];
}
// Basic block is to the right of the returned block.
ASSERT(&basicBlock[1] <= &m_basicBlocks.last());
- ASSERT(blockContainsBytecodeOffset(basicBlock[1].get(), bytecodeOffset));
- return basicBlock[1].get();
+ ASSERT(blockContainsBytecodeOffset(basicBlock[1], bytecodeOffset));
+ return &basicBlock[1];
}
BytecodeBasicBlock* findBasicBlockWithLeaderOffset(InstructionStream::Offset leaderOffset)
{
- return (*tryBinarySearch<std::unique_ptr<BytecodeBasicBlock>, unsigned>(m_basicBlocks, m_basicBlocks.size(), leaderOffset, [] (std::unique_ptr<BytecodeBasicBlock>* basicBlock) { return (*basicBlock)->leaderOffset(); })).get();
+ return tryBinarySearch<BytecodeBasicBlock, unsigned>(m_basicBlocks, m_basicBlocks.size(), leaderOffset, [] (BytecodeBasicBlock* basicBlock) { return basicBlock->leaderOffset(); });
}
unsigned size() const { return m_basicBlocks.size(); }
- BytecodeBasicBlock* at(unsigned index) const { return m_basicBlocks[index].get(); }
- BytecodeBasicBlock* operator[](unsigned index) const { return at(index); }
+ BytecodeBasicBlock& at(unsigned index) const { return const_cast<BytecodeGraph*>(this)->m_basicBlocks[index]; }
+ BytecodeBasicBlock& operator[](unsigned index) const { return at(index); }
- iterator begin() const { return iterator(*this, 0); }
- iterator end() const { return iterator(*this, size()); }
- BytecodeBasicBlock* first() { return at(0); }
- BytecodeBasicBlock* last() { return at(size() - 1); }
+ iterator begin() { return iterator(*this, 0); }
+ iterator end() { return iterator(*this, size()); }
+ BytecodeBasicBlock& first() { return at(0); }
+ BytecodeBasicBlock& last() { return at(size() - 1); }
private:
BasicBlocksVector m_basicBlocks;
@@ -106,8 +106,8 @@
template<typename CodeBlockType>
BytecodeGraph::BytecodeGraph(CodeBlockType* codeBlock, const InstructionStream& instructions)
+ : m_basicBlocks(BytecodeBasicBlock::compute(codeBlock, instructions))
{
- BytecodeBasicBlock::compute(codeBlock, instructions, m_basicBlocks);
ASSERT(m_basicBlocks.size());
}
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.cpp (255458 => 255459)
--- trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.cpp 2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.cpp 2020-01-30 22:32:43 UTC (rev 255459)
@@ -53,7 +53,7 @@
ASSERT(!block->isEntryBlock());
ASSERT(!block->isExitBlock());
result.resize(block->out().numBits());
- computeLocalLivenessForBytecodeIndex(codeBlock, codeBlock->instructions(), m_graph, block, bytecodeIndex, result);
+ computeLocalLivenessForBytecodeIndex(codeBlock, codeBlock->instructions(), m_graph, *block, bytecodeIndex, result);
}
FastBitVector BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeIndex(CodeBlock* codeBlock, BytecodeIndex bytecodeIndex)
@@ -70,11 +70,11 @@
result.m_beforeUseVector.resize(codeBlock->instructions().size());
result.m_afterUseVector.resize(codeBlock->instructions().size());
- for (std::unique_ptr<BytecodeBasicBlock>& block : m_graph.basicBlocksInReverseOrder()) {
- if (block->isEntryBlock() || block->isExitBlock())
+ for (BytecodeBasicBlock& block : m_graph.basicBlocksInReverseOrder()) {
+ if (block.isEntryBlock() || block.isExitBlock())
continue;
- out = block->out();
+ out = block.out();
auto use = [&] (unsigned bitIndex) {
// This is the use functor, so we set the bit.
@@ -87,8 +87,10 @@
};
auto& instructions = codeBlock->instructions();
- for (unsigned i = block->offsets().size(); i--;) {
- BytecodeIndex bytecodeIndex = BytecodeIndex(block->offsets()[i]);
+ unsigned cursor = block.totalLength();
+ for (unsigned i = block.delta().size(); i--;) {
+ cursor -= block.delta()[i];
+ BytecodeIndex bytecodeIndex = BytecodeIndex(block.leaderOffset() + cursor);
stepOverInstructionDef(codeBlock, instructions, m_graph, bytecodeIndex, def);
stepOverInstructionUseInExceptionHandler(codeBlock, instructions, m_graph, bytecodeIndex, use);
@@ -107,21 +109,23 @@
result.m_codeBlock = codeBlock;
result.m_killSets = makeUniqueArray<BytecodeKills::KillSet>(codeBlock->instructions().size());
- for (std::unique_ptr<BytecodeBasicBlock>& block : m_graph.basicBlocksInReverseOrder()) {
- if (block->isEntryBlock() || block->isExitBlock())
+ for (BytecodeBasicBlock& block : m_graph.basicBlocksInReverseOrder()) {
+ if (block.isEntryBlock() || block.isExitBlock())
continue;
- out = block->out();
+ out = block.out();
- for (unsigned i = block->offsets().size(); i--;) {
- unsigned bytecodeOffset = block->offsets()[i];
+ unsigned cursor = block.totalLength();
+ for (unsigned i = block.delta().size(); i--;) {
+ cursor -= block.delta()[i];
+ BytecodeIndex bytecodeIndex = BytecodeIndex(block.leaderOffset() + cursor);
stepOverInstruction(
- codeBlock, codeBlock->instructions(), m_graph, BytecodeIndex(bytecodeOffset),
+ codeBlock, codeBlock->instructions(), m_graph, bytecodeIndex,
[&] (unsigned index) {
// This is for uses.
if (out[index])
return;
- result.m_killSets[bytecodeOffset].add(index);
+ result.m_killSets[bytecodeIndex.offset()].add(index);
out[index] = true;
},
[&] (unsigned index) {
@@ -140,12 +144,11 @@
unsigned numberOfBlocks = m_graph.size();
Vector<FastBitVector> predecessors(numberOfBlocks);
- for (BytecodeBasicBlock* block : m_graph)
- predecessors[block->index()].resize(numberOfBlocks);
- for (BytecodeBasicBlock* block : m_graph) {
- for (unsigned j = 0; j < block->successors().size(); j++) {
- unsigned blockIndex = block->index();
- unsigned successorIndex = block->successors()[j]->index();
+ for (BytecodeBasicBlock& block : m_graph)
+ predecessors[block.index()].resize(numberOfBlocks);
+ for (BytecodeBasicBlock& block : m_graph) {
+ for (unsigned successorIndex : block.successors()) {
+ unsigned blockIndex = block.index();
predecessors[successorIndex][blockIndex] = true;
}
}
@@ -157,32 +160,30 @@
}
};
- for (BytecodeBasicBlock* block : m_graph) {
- dataLogF("\nBytecode basic block %u: %p (offset: %u, length: %u)\n", i++, block, block->leaderOffset(), block->totalLength());
+ for (BytecodeBasicBlock& block : m_graph) {
+ dataLogF("\nBytecode basic block %u: %p (offset: %u, length: %u)\n", i++, &block, block.leaderOffset(), block.totalLength());
dataLogF("Predecessors:");
- dumpBitVector(predecessors[block->index()]);
+ dumpBitVector(predecessors[block.index()]);
dataLogF("\n");
dataLogF("Successors:");
FastBitVector successors;
successors.resize(numberOfBlocks);
- for (unsigned j = 0; j < block->successors().size(); j++) {
- BytecodeBasicBlock* successor = block->successors()[j];
- successors[successor->index()] = true;
- }
+ for (unsigned successorIndex : block.successors())
+ successors[successorIndex] = true;
dumpBitVector(successors); // Dump in sorted order.
dataLogF("\n");
- if (block->isEntryBlock()) {
- dataLogF("Entry block %p\n", block);
+ if (block.isEntryBlock()) {
+ dataLogF("Entry block %p\n", &block);
continue;
}
- if (block->isExitBlock()) {
- dataLogF("Exit block: %p\n", block);
+ if (block.isExitBlock()) {
+ dataLogF("Exit block: %p\n", &block);
continue;
}
- for (unsigned bytecodeOffset = block->leaderOffset(); bytecodeOffset < block->leaderOffset() + block->totalLength();) {
+ for (unsigned bytecodeOffset = block.leaderOffset(); bytecodeOffset < block.leaderOffset() + block.totalLength();) {
const auto currentInstruction = instructions.at(bytecodeOffset);
dataLogF("Live variables:");
@@ -195,7 +196,7 @@
}
dataLogF("Live variables:");
- FastBitVector liveAfter = block->out();
+ FastBitVector liveAfter = block.out();
dumpBitVector(liveAfter);
dataLogF("\n");
}
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.h (255458 => 255459)
--- trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.h 2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.h 2020-01-30 22:32:43 UTC (rev 255459)
@@ -64,10 +64,10 @@
static void stepOverInstruction(CodeBlockType*, const InstructionStream&, BytecodeGraph&, BytecodeIndex, FastBitVector& out);
template<typename CodeBlockType, typename Instructions>
- static bool computeLocalLivenessForBytecodeIndex(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeBasicBlock*, BytecodeIndex, FastBitVector& result);
+ static bool computeLocalLivenessForBytecodeIndex(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeBasicBlock&, BytecodeIndex, FastBitVector& result);
template<typename CodeBlockType, typename Instructions>
- static bool computeLocalLivenessForBlock(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeBasicBlock*);
+ static bool computeLocalLivenessForBlock(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeBasicBlock&);
template<typename CodeBlockType, typename Instructions>
static FastBitVector getLivenessInfoAtBytecodeIndex(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeIndex);
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysisInlines.h (255458 => 255459)
--- trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysisInlines.h 2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysisInlines.h 2020-01-30 22:32:43 UTC (rev 255459)
@@ -135,18 +135,20 @@
}
template<typename CodeBlockType, typename Instructions>
-inline bool BytecodeLivenessPropagation::computeLocalLivenessForBytecodeIndex(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, BytecodeBasicBlock* block, BytecodeIndex targetIndex, FastBitVector& result)
+inline bool BytecodeLivenessPropagation::computeLocalLivenessForBytecodeIndex(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, BytecodeBasicBlock& block, BytecodeIndex targetIndex, FastBitVector& result)
{
- ASSERT(!block->isExitBlock());
- ASSERT(!block->isEntryBlock());
+ ASSERT(!block.isExitBlock());
+ ASSERT(!block.isEntryBlock());
- FastBitVector out = block->out();
+ FastBitVector out = block.out();
- for (int i = block->offsets().size() - 1; i >= 0; i--) {
- unsigned bytecodeOffset = block->offsets()[i];
- if (targetIndex.offset() > bytecodeOffset)
+ unsigned cursor = block.totalLength();
+ for (unsigned i = block.delta().size(); i--;) {
+ cursor -= block.delta()[i];
+ BytecodeIndex bytecodeIndex = BytecodeIndex(block.leaderOffset() + cursor);
+ if (targetIndex.offset() > bytecodeIndex.offset())
break;
- stepOverInstruction(codeBlock, instructions, graph, BytecodeIndex(bytecodeOffset), out);
+ stepOverInstruction(codeBlock, instructions, graph, bytecodeIndex, out);
}
return result.setAndCheck(out);
@@ -153,11 +155,11 @@
}
template<typename CodeBlockType, typename Instructions>
-inline bool BytecodeLivenessPropagation::computeLocalLivenessForBlock(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, BytecodeBasicBlock* block)
+inline bool BytecodeLivenessPropagation::computeLocalLivenessForBlock(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, BytecodeBasicBlock& block)
{
- if (block->isExitBlock() || block->isEntryBlock())
+ if (block.isExitBlock() || block.isEntryBlock())
return false;
- return computeLocalLivenessForBytecodeIndex(codeBlock, instructions, graph, block, BytecodeIndex(block->leaderOffset()), block->in());
+ return computeLocalLivenessForBytecodeIndex(codeBlock, instructions, graph, block, BytecodeIndex(block.leaderOffset()), block.in());
}
template<typename CodeBlockType, typename Instructions>
@@ -169,7 +171,7 @@
ASSERT(!block->isExitBlock());
FastBitVector out;
out.resize(block->out().numBits());
- computeLocalLivenessForBytecodeIndex(codeBlock, instructions, graph, block, bytecodeIndex, out);
+ computeLocalLivenessForBytecodeIndex(codeBlock, instructions, graph, *block, bytecodeIndex, out);
return out;
}
@@ -177,27 +179,29 @@
inline void BytecodeLivenessPropagation::runLivenessFixpoint(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph)
{
unsigned numberOfVariables = codeBlock->numCalleeLocals();
- for (BytecodeBasicBlock* block : graph) {
- block->in().resize(numberOfVariables);
- block->out().resize(numberOfVariables);
- block->in().clearAll();
- block->out().clearAll();
+ for (BytecodeBasicBlock& block : graph) {
+ block.in().resize(numberOfVariables);
+ block.out().resize(numberOfVariables);
+ block.in().clearAll();
+ block.out().clearAll();
}
bool changed;
- BytecodeBasicBlock* lastBlock = graph.last();
- lastBlock->in().clearAll();
- lastBlock->out().clearAll();
+ BytecodeBasicBlock& lastBlock = graph.last();
+ lastBlock.in().clearAll();
+ lastBlock.out().clearAll();
FastBitVector newOut;
- newOut.resize(lastBlock->out().numBits());
+ newOut.resize(lastBlock.out().numBits());
do {
changed = false;
- for (std::unique_ptr<BytecodeBasicBlock>& block : graph.basicBlocksInReverseOrder()) {
+ for (BytecodeBasicBlock& block : graph.basicBlocksInReverseOrder()) {
newOut.clearAll();
- for (BytecodeBasicBlock* successor : block->successors())
- newOut |= successor->in();
- block->out() = newOut;
- changed |= computeLocalLivenessForBlock(codeBlock, instructions, graph, block.get());
+ for (unsigned blockIndex : block.successors()) {
+ BytecodeBasicBlock& successor = graph[blockIndex];
+ newOut |= successor.in();
+ }
+ block.out() = newOut;
+ changed |= computeLocalLivenessForBlock(codeBlock, instructions, graph, block);
}
} while (changed);
}
Modified: trunk/Source/_javascript_Core/bytecode/InstructionStream.h (255458 => 255459)
--- trunk/Source/_javascript_Core/bytecode/InstructionStream.h 2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/InstructionStream.h 2020-01-30 22:32:43 UTC (rev 255459)
@@ -111,7 +111,9 @@
public:
Ref freeze() const { return Ref { m_instructions, m_index }; }
inline Instruction* operator->() { return unwrap(); }
+ inline const Instruction* operator->() const { return unwrap(); }
inline Instruction* ptr() { return unwrap(); }
+ inline const Instruction* ptr() const { return unwrap(); }
inline operator Ref()
{
return Ref { m_instructions, m_index };
@@ -119,6 +121,7 @@
private:
inline Instruction* unwrap() { return reinterpret_cast<Instruction*>(&m_instructions[m_index]); }
+ inline const Instruction* unwrap() const { return reinterpret_cast<const Instruction*>(&m_instructions[m_index]); }
};
private:
Modified: trunk/Source/_javascript_Core/bytecode/Opcode.h (255458 => 255459)
--- trunk/Source/_javascript_Core/bytecode/Opcode.h 2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/bytecode/Opcode.h 2020-01-30 22:32:43 UTC (rev 255459)
@@ -36,6 +36,7 @@
#include <string.h>
#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
namespace JSC {
@@ -53,7 +54,6 @@
)
-const int maxOpcodeLength = 40;
#if ENABLE(C_LOOP)
const int numOpcodeIDs = NUMBER_OF_BYTECODE_IDS + NUMBER_OF_CLOOP_BYTECODE_HELPER_IDS + NUMBER_OF_BYTECODE_HELPER_IDS;
#else
@@ -88,6 +88,11 @@
FOR_EACH_WASM_ID(OPCODE_ID_LENGTHS);
#undef OPCODE_ID_LENGTHS
+static constexpr unsigned maxJSOpcodeLength = /* Opcode */ 1 + /* Wide32 Opcode */ 1 + /* Operands */ (MAX_LENGTH_OF_BYTECODE_IDS - 1) * 4;
+static constexpr unsigned maxWasmOpcodeLength = /* Opcode */ 1 + /* Wide32 Opcode */ 1 + /* Operands */ (MAX_LENGTH_OF_WASM_IDS - 1) * 4;
+static constexpr unsigned maxOpcodeLength = std::max(maxJSOpcodeLength, maxWasmOpcodeLength);
+static constexpr unsigned bitWidthForMaxOpcodeLength = WTF::getMSBSetConstexpr(maxOpcodeLength) + 1;
+
#define FOR_EACH_OPCODE_WITH_VALUE_PROFILE(macro) \
macro(OpCallVarargs) \
macro(OpTailCallVarargs) \
Modified: trunk/Source/_javascript_Core/generator/Section.rb (255458 => 255459)
--- trunk/Source/_javascript_Core/generator/Section.rb 2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/generator/Section.rb 2020-01-30 22:32:43 UTC (rev 255459)
@@ -69,6 +69,7 @@
out << "\n"
out.write("#define NUMBER_OF_#{config[:macro_name_component]}_IDS #{opcodes.length}\n")
+ out.write("#define MAX_LENGTH_OF_#{config[:macro_name_component]}_IDS #{(opcodes.max {|a, b| a.length <=> b.length }).length}\n")
end
if config[:emit_in_structs_file]
Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (255458 => 255459)
--- trunk/Source/_javascript_Core/jit/JIT.cpp 2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp 2020-01-30 22:32:43 UTC (rev 255459)
@@ -215,7 +215,8 @@
while (BytecodeBasicBlock* block = worklist.pop()) {
startBytecodeIndex = BytecodeIndex(std::min(startBytecodeIndex.offset(), block->leaderOffset()));
- worklist.pushAll(block->successors());
+ for (unsigned successorIndex : block->successors())
+ worklist.push(&graph[successorIndex]);
// Also add catch blocks for bytecodes that throw.
if (m_codeBlock->numberOfExceptionHandlers()) {
Modified: trunk/Source/_javascript_Core/llint/LLIntData.cpp (255458 => 255459)
--- trunk/Source/_javascript_Core/llint/LLIntData.cpp 2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/llint/LLIntData.cpp 2020-01-30 22:32:43 UTC (rev 255459)
@@ -81,7 +81,7 @@
}
ASSERT(llint_throw_from_slow_path_trampoline < UINT8_MAX);
- for (int i = 0; i < maxOpcodeLength + 1; ++i) {
+ for (unsigned i = 0; i < maxOpcodeLength + 1; ++i) {
Data::s_exceptionInstructions[i] = llint_throw_from_slow_path_trampoline;
Data::s_wasmExceptionInstructions[i] = wasm_throw_from_slow_path_trampoline;
}
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.cpp (255458 => 255459)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.cpp 2020-01-30 22:31:31 UTC (rev 255458)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.cpp 2020-01-30 22:32:43 UTC (rev 255459)
@@ -280,7 +280,7 @@
// initialized the opcodeMap above. This is because getCodePtr()
// can depend on the opcodeMap.
uint8_t* exceptionInstructions = reinterpret_cast<uint8_t*>(LLInt::exceptionInstructions());
- for (int i = 0; i < maxOpcodeLength + 1; ++i)
+ for (unsigned i = 0; i < maxOpcodeLength + 1; ++i)
exceptionInstructions[i] = llint_throw_from_slow_path_trampoline;
return JSValue();