Commit 440584f1 authored by mark.lam@apple.com's avatar mark.lam@apple.com

Adding UnlinkedCodeBlock::opDebugBytecodeOffsetForLineAndColumn()..

https://bugs.webkit.org/show_bug.cgi?id=127127.

Reviewed by Geoffrey Garen.

In order to implement bytecode level breakpoints, we need a mechanism
for computing the best fit op_debug bytecode offset for any valid given
line and column value in the source. The "best fit" op_debug bytecode
in this case is defined below in the comment for
UnlinkedCodeBlock::opDebugBytecodeOffsetForLineAndColumn().

* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::opDebugBytecodeOffsetForLineAndColumn):
- Convert the line and column to unlinked line and column values and
  pass them to UnlinkedCodeBlock::opDebugBytecodeOffsetForLineAndColumn()
  to do the real work.

* bytecode/CodeBlock.h:
* bytecode/LineColumnInfo.h: Added.
(JSC::LineColumnInfo::operator <):
(JSC::LineColumnInfo::LineColumnPair::LineColumnPair):
(JSC::LineColumnInfo::operator ==):
(JSC::LineColumnInfo::operator !=):
(JSC::LineColumnInfo::operator <=):
(JSC::LineColumnInfo::operator >):
(JSC::LineColumnInfo::operator >=):
* bytecode/LineInfo.h: Removed.

* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedCodeBlock::decodeExpressionRangeLineAndColumn):
- Factored this out of expressionRangeForBytecodeOffset() so that it can
  be called from multiple places.
(JSC::dumpLineColumnEntry):
(JSC::UnlinkedCodeBlock::dumpExpressionRangeInfo):
(JSC::UnlinkedCodeBlock::dumpOpDebugLineColumnInfoList):
- Some dumpers for debugging use only.
(JSC::UnlinkedCodeBlock::expressionRangeForBytecodeOffset):
(JSC::UnlinkedCodeBlock::opDebugBytecodeOffsetForLineAndColumn):
- Finds the earliest op_debug bytecode whose line and column matches the
  specified line and column values. If an exact match is not found, then
  finds the nearest op_debug bytecode that precedes the specified line
  and column values. If there are more than one op_debug at that preceding
  line and column value, then the earliest of those op_debug bytecodes will
  be be selected. The offset of the selected bytecode will be returned.

  We want the earliest one because when we have multiple op_debug bytecodes
  that map to a given line and column, a debugger user would expect to break
  on the first one and step through the rest thereafter if needed.

(JSC::compareLineColumnInfo):
(JSC::UnlinkedCodeBlock::opDebugLineColumnInfoList):
- Creates the sorted opDebugLineColumnInfoList on demand. This list is
  stored in the UnlinkedCodeBlock's rareData.
* bytecode/UnlinkedCodeBlock.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@162256 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 4041f1f2
2014-01-18 Mark Lam <mark.lam@apple.com>
Adding UnlinkedCodeBlock::opDebugBytecodeOffsetForLineAndColumn()..
https://bugs.webkit.org/show_bug.cgi?id=127127.
Reviewed by Geoffrey Garen.
In order to implement bytecode level breakpoints, we need a mechanism
for computing the best fit op_debug bytecode offset for any valid given
line and column value in the source. The "best fit" op_debug bytecode
in this case is defined below in the comment for
UnlinkedCodeBlock::opDebugBytecodeOffsetForLineAndColumn().
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::opDebugBytecodeOffsetForLineAndColumn):
- Convert the line and column to unlinked line and column values and
pass them to UnlinkedCodeBlock::opDebugBytecodeOffsetForLineAndColumn()
to do the real work.
* bytecode/CodeBlock.h:
* bytecode/LineColumnInfo.h: Added.
(JSC::LineColumnInfo::operator <):
(JSC::LineColumnInfo::LineColumnPair::LineColumnPair):
(JSC::LineColumnInfo::operator ==):
(JSC::LineColumnInfo::operator !=):
(JSC::LineColumnInfo::operator <=):
(JSC::LineColumnInfo::operator >):
(JSC::LineColumnInfo::operator >=):
* bytecode/LineInfo.h: Removed.
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedCodeBlock::decodeExpressionRangeLineAndColumn):
- Factored this out of expressionRangeForBytecodeOffset() so that it can
be called from multiple places.
(JSC::dumpLineColumnEntry):
(JSC::UnlinkedCodeBlock::dumpExpressionRangeInfo):
(JSC::UnlinkedCodeBlock::dumpOpDebugLineColumnInfoList):
- Some dumpers for debugging use only.
(JSC::UnlinkedCodeBlock::expressionRangeForBytecodeOffset):
(JSC::UnlinkedCodeBlock::opDebugBytecodeOffsetForLineAndColumn):
- Finds the earliest op_debug bytecode whose line and column matches the
specified line and column values. If an exact match is not found, then
finds the nearest op_debug bytecode that precedes the specified line
and column values. If there are more than one op_debug at that preceding
line and column value, then the earliest of those op_debug bytecodes will
be be selected. The offset of the selected bytecode will be returned.
We want the earliest one because when we have multiple op_debug bytecodes
that map to a given line and column, a debugger user would expect to break
on the first one and step through the rest thereafter if needed.
(JSC::compareLineColumnInfo):
(JSC::UnlinkedCodeBlock::opDebugLineColumnInfoList):
- Creates the sorted opDebugLineColumnInfoList on demand. This list is
stored in the UnlinkedCodeBlock's rareData.
* bytecode/UnlinkedCodeBlock.h:
2014-01-18 Zan Dobersek <zdobersek@igalia.com>
Inspector scripts are not compatible with Python v3
......
......@@ -152,7 +152,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/bytecode/LLIntCallLinkInfo.h \
Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp \
Source/JavaScriptCore/bytecode/LazyOperandValueProfile.h \
Source/JavaScriptCore/bytecode/LineInfo.h \
Source/JavaScriptCore/bytecode/LineColumnInfo.h \
Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp \
Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h \
Source/JavaScriptCore/bytecode/ObjectAllocationProfile.h \
......
......@@ -816,7 +816,7 @@
<ClInclude Include="..\bytecode\Instruction.h" />
<ClInclude Include="..\bytecode\JumpTable.h" />
<ClInclude Include="..\bytecode\LazyOperandValueProfile.h" />
<ClInclude Include="..\bytecode\LineInfo.h" />
<ClInclude Include="..\bytecode\LineColumnInfo.h" />
<ClInclude Include="..\bytecode\LLIntCallLinkInfo.h" />
<ClInclude Include="..\bytecode\MethodOfGettingAValueProfile.h" />
<ClInclude Include="..\bytecode\Opcode.h" />
......
......@@ -1502,7 +1502,7 @@
<ClInclude Include="..\bytecode\LazyOperandValueProfile.h">
<Filter>bytecode</Filter>
</ClInclude>
<ClInclude Include="..\bytecode\LineInfo.h">
<ClInclude Include="..\bytecode\LineColumnInfo.h">
<Filter>bytecode</Filter>
</ClInclude>
<ClInclude Include="..\bytecode\LLIntCallLinkInfo.h">
......
......@@ -65,7 +65,6 @@
0F0B83A714BCF50700885B4F /* CodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A514BCF50400885B4F /* CodeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0B83A914BCF56200885B4F /* HandlerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A814BCF55E00885B4F /* HandlerInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0B83AB14BCF5BB00885B4F /* ExpressionRangeInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83AA14BCF5B900885B4F /* ExpressionRangeInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0B83AD14BCF60400885B4F /* LineInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83AC14BCF60200885B4F /* LineInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0B83B014BCF71600885B4F /* CallLinkInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B83AE14BCF71400885B4F /* CallLinkInfo.cpp */; };
0F0B83B114BCF71800885B4F /* CallLinkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83AF14BCF71400885B4F /* CallLinkInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F0B83B914BCF95F00885B4F /* CallReturnOffsetToBytecodeOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -1313,6 +1312,7 @@
E49DC16D12EF295300184A1F /* SourceProviderCacheItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E49DC14912EF261A00184A1F /* SourceProviderCacheItem.h */; settings = {ATTRIBUTES = (Private, ); }; };
FE20CE9D15F04A9500DF3430 /* LLIntCLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE20CE9B15F04A9500DF3430 /* LLIntCLoop.cpp */; };
FE20CE9E15F04A9500DF3430 /* LLIntCLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = FE20CE9C15F04A9500DF3430 /* LLIntCLoop.h */; settings = {ATTRIBUTES = (Private, ); }; };
FE37DD56183C1E880018B2F0 /* LineColumnInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = FE37DD55183C1E880018B2F0 /* LineColumnInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
FE4A331F15BD2E07006F54F3 /* VMInspector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE4A331D15BD2E07006F54F3 /* VMInspector.cpp */; };
FE4A332015BD2E07006F54F3 /* VMInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = FE4A331E15BD2E07006F54F3 /* VMInspector.h */; settings = {ATTRIBUTES = (Private, ); }; };
FE5932A7183C5A2600A1ECCC /* VMEntryScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */; };
......@@ -1435,7 +1435,6 @@
0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = "<group>"; };
0F0B83A814BCF55E00885B4F /* HandlerInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HandlerInfo.h; sourceTree = "<group>"; };
0F0B83AA14BCF5B900885B4F /* ExpressionRangeInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExpressionRangeInfo.h; sourceTree = "<group>"; };
0F0B83AC14BCF60200885B4F /* LineInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LineInfo.h; sourceTree = "<group>"; };
0F0B83AE14BCF71400885B4F /* CallLinkInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallLinkInfo.cpp; sourceTree = "<group>"; };
0F0B83AF14BCF71400885B4F /* CallLinkInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallLinkInfo.h; sourceTree = "<group>"; };
0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallReturnOffsetToBytecodeOffset.h; sourceTree = "<group>"; };
......@@ -2723,6 +2722,7 @@
F692A8870255597D01FF60F7 /* JSCJSValue.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCJSValue.cpp; sourceTree = "<group>"; tabWidth = 8; };
FE20CE9B15F04A9500DF3430 /* LLIntCLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntCLoop.cpp; path = llint/LLIntCLoop.cpp; sourceTree = "<group>"; };
FE20CE9C15F04A9500DF3430 /* LLIntCLoop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntCLoop.h; path = llint/LLIntCLoop.h; sourceTree = "<group>"; };
FE37DD55183C1E880018B2F0 /* LineColumnInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LineColumnInfo.h; sourceTree = "<group>"; };
FE4A331D15BD2E07006F54F3 /* VMInspector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VMInspector.cpp; sourceTree = "<group>"; };
FE4A331E15BD2E07006F54F3 /* VMInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMInspector.h; sourceTree = "<group>"; };
FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VMEntryScope.cpp; sourceTree = "<group>"; };
......@@ -4230,6 +4230,7 @@
969A078F0ED1D3AE00F1F681 /* bytecode */ = {
isa = PBXGroup;
children = (
FE37DD55183C1E880018B2F0 /* LineColumnInfo.h */,
0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */,
0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */,
0F63945115D07051006A597C /* ArrayProfile.cpp */,
......@@ -4280,7 +4281,6 @@
BCFD8C910EEB2EE700283848 /* JumpTable.h */,
0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */,
0FB5467614F59AD1002C2989 /* LazyOperandValueProfile.h */,
0F0B83AC14BCF60200885B4F /* LineInfo.h */,
0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */,
0FB5467C14F5CFD3002C2989 /* MethodOfGettingAValueProfile.cpp */,
0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */,
......@@ -4471,6 +4471,7 @@
C2FCAE1117A9C24E0034C735 /* BytecodeBasicBlock.h in Headers */,
A532439418569709002ED692 /* generate-combined-inspector-json.py in Headers */,
C2FCAE1317A9C24E0034C735 /* BytecodeLivenessAnalysis.h in Headers */,
FE37DD56183C1E880018B2F0 /* LineColumnInfo.h in Headers */,
0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */,
A5840E29187CA5E600843B10 /* inline-and-minify-stylesheets-and-scripts.py in Headers */,
A5840E2B187CA75B00843B10 /* jsmin.py in Headers */,
......@@ -4936,7 +4937,6 @@
BC18C4310E16F5CD00B34460 /* Lexer.h in Headers */,
BC18C52E0E16FCE100B34460 /* Lexer.lut.h in Headers */,
A513E5CB185F9624007E95AD /* InjectedScriptManager.h in Headers */,
0F0B83AD14BCF60400885B4F /* LineInfo.h in Headers */,
86D3B3C310159D7F002865E7 /* LinkBuffer.h in Headers */,
0F431738146BAC69007E3890 /* ListableHandler.h in Headers */,
A7E2EA6B0FB460CF00601F06 /* LiteralParser.h in Headers */,
......
/*
* Copyright (C) 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2008, 2009, 2010, 2012, 2013, 2014 Apple Inc. All rights reserved.
* Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
*
* Redistribution and use in source and binary forms, with or without
......@@ -2565,6 +2565,23 @@ void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& d
line += m_ownerExecutable->lineNo();
}
unsigned CodeBlock::opDebugBytecodeOffsetForLineAndColumn(unsigned& line, unsigned& column)
{
unsigned lineAdjustment = m_ownerExecutable->lineNo();
ASSERT(line >= lineAdjustment);
unsigned unlinkedLine = line - lineAdjustment;
unsigned columnAdjustment = unlinkedLine ? 1 : firstLineColumnOffset();
ASSERT(column >= columnAdjustment);
unsigned unlinkedColumn = column - columnAdjustment;
unsigned bytecodeOffset = m_unlinkedCode->opDebugBytecodeOffsetForLineAndColumn(unlinkedLine, unlinkedColumn);
if (bytecodeOffset != static_cast<unsigned>(WTF::notFound)) {
line = unlinkedLine + lineAdjustment;
column = unlinkedColumn + (unlinkedLine ? 1 : firstLineColumnOffset());
}
return bytecodeOffset;
}
void CodeBlock::shrinkToFit(ShrinkMode shrinkMode)
{
#if ENABLE(JIT)
......
/*
* Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
* Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
*
* Redistribution and use in source and binary forms, with or without
......@@ -65,7 +65,6 @@
#include "JumpTable.h"
#include "LLIntCallLinkInfo.h"
#include "LazyOperandValueProfile.h"
#include "LineInfo.h"
#include "ProfilerCompilation.h"
#include "RegExpObject.h"
#include "StructureStubInfo.h"
......@@ -175,6 +174,7 @@ public:
unsigned columnNumberForBytecodeOffset(unsigned bytecodeOffset);
void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,
int& startOffset, int& endOffset, unsigned& line, unsigned& column);
unsigned opDebugBytecodeOffsetForLineAndColumn(unsigned& line, unsigned& column);
#if ENABLE(JIT)
StructureStubInfo* addStubInfo();
......
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -23,19 +23,75 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LineInfo_h
#define LineInfo_h
#include <wtf/StdLibExtras.h>
#ifndef LineColumnInfo_h
#define LineColumnInfo_h
namespace JSC {
struct LineInfo {
uint32_t instructionOffset;
int32_t lineNumber;
struct LineColumnInfo {
unsigned instructionOffset;
unsigned line;
unsigned column;
bool operator <(const LineColumnInfo& other) const
{
if (line == other.line) {
if (column == other.column)
return instructionOffset < other.instructionOffset;
return column < other.column;
}
return line < other.line;
}
struct LineColumnPair {
LineColumnPair(unsigned line, unsigned column)
: line(line), column(column)
{
}
unsigned line;
unsigned column;
};
bool operator ==(const LineColumnPair& pair) const
{
return (line == pair.line) && (column == pair.column);
}
bool operator !=(const LineColumnPair& pair) const
{
return (line != pair.line) || (column != pair.column);
}
bool operator <(const LineColumnPair& pair) const
{
if (line == pair.line)
return column < pair.column;
return line < pair.line;
}
bool operator <=(const LineColumnPair& pair) const
{
if (line == pair.line)
return column <= pair.column;
return line < pair.line;
}
bool operator >(const LineColumnPair& pair) const
{
if (line == pair.line)
return column > pair.column;
return line > pair.line;
}
bool operator >=(const LineColumnPair& pair) const
{
if (line == pair.line)
return column >= pair.column;
return line > pair.line;
}
};
} // namespace JSC
#endif // LineInfo_h
#endif // LineColumnInfo_h
......@@ -37,6 +37,7 @@
#include "SourceProvider.h"
#include "Structure.h"
#include "SymbolTable.h"
#include <wtf/DataLog.h>
namespace JSC {
......@@ -256,6 +257,74 @@ int UnlinkedCodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
return line;
}
inline void UnlinkedCodeBlock::getLineAndColumn(ExpressionRangeInfo& info,
unsigned& line, unsigned& column)
{
switch (info.mode) {
case ExpressionRangeInfo::FatLineMode:
info.decodeFatLineMode(line, column);
break;
case ExpressionRangeInfo::FatColumnMode:
info.decodeFatColumnMode(line, column);
break;
case ExpressionRangeInfo::FatLineAndColumnMode: {
unsigned fatIndex = info.position;
ExpressionRangeInfo::FatPosition& fatPos = m_rareData->m_expressionInfoFatPositions[fatIndex];
line = fatPos.line;
column = fatPos.column;
break;
}
} // switch
}
#ifndef NDEBUG
static void dumpLineColumnEntry(size_t index, const RefCountedArray<UnlinkedInstruction>& instructions, unsigned instructionOffset, unsigned line, unsigned column)
{
OpcodeID opcode = instructions[instructionOffset].u.opcode;
const char* event = "";
if (opcode == op_debug) {
switch (instructions[instructionOffset + 1].u.operand) {
case WillExecuteProgram: event = " WillExecuteProgram"; break;
case DidExecuteProgram: event = " DidExecuteProgram"; break;
case DidEnterCallFrame: event = " DidEnterCallFrame"; break;
case DidReachBreakpoint: event = " DidReachBreakpoint"; break;
case WillLeaveCallFrame: event = " WillLeaveCallFrame"; break;
case WillExecuteStatement: event = " WillExecuteStatement"; break;
}
}
dataLogF(" [%zu] pc %u @ line %u col %u : %s%s\n", index, instructionOffset, line, column, opcodeNames[opcode], event);
}
void UnlinkedCodeBlock::dumpExpressionRangeInfo()
{
Vector<ExpressionRangeInfo>& expressionInfo = m_expressionInfo;
size_t size = m_expressionInfo.size();
dataLogF("UnlinkedCodeBlock %p expressionRangeInfo[%zu] {\n", this, size);
for (size_t i = 0; i < size; i++) {
ExpressionRangeInfo& info = expressionInfo[i];
unsigned line;
unsigned column;
getLineAndColumn(info, line, column);
dumpLineColumnEntry(i, instructions(), info.instructionOffset, line, column);
}
dataLog("}\n");
}
void UnlinkedCodeBlock::dumpOpDebugLineColumnInfoList()
{
LineColumnInfoList& infoList = this->opDebugLineColumnInfoList();
size_t size = infoList.size();
dataLogF("UnlinkedCodeBlock %p opDebugLineColumnInfoList[%zu] {\n", this, size);
for (size_t i = 0; i < size; i++) {
LineColumnInfo& info = infoList[i];
dumpLineColumnEntry(i, instructions(), info.instructionOffset, info.line, info.column);
}
dataLog("}\n");
}
#endif
void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset,
int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
{
......@@ -289,22 +358,78 @@ void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset
startOffset = info.startOffset;
endOffset = info.endOffset;
divot = info.divotPoint;
getLineAndColumn(info, line, column);
}
switch (info.mode) {
case ExpressionRangeInfo::FatLineMode:
info.decodeFatLineMode(line, column);
break;
case ExpressionRangeInfo::FatColumnMode:
info.decodeFatColumnMode(line, column);
break;
case ExpressionRangeInfo::FatLineAndColumnMode: {
unsigned fatIndex = info.position;
ExpressionRangeInfo::FatPosition& fatPos = m_rareData->m_expressionInfoFatPositions[fatIndex];
line = fatPos.line;
column = fatPos.column;
break;
unsigned UnlinkedCodeBlock::opDebugBytecodeOffsetForLineAndColumn(unsigned& line, unsigned& column)
{
if (!m_expressionInfo.size())
return static_cast<unsigned>(WTF::notFound);
LineColumnInfo::LineColumnPair target(line, column);
LineColumnInfoList& list = opDebugLineColumnInfoList();
// Find the earliest op_debug bytecode whose line and column matches the
// target line and column values. If an exact match is not found, then
// find the nearest op_debug bytecode that precedes the target line and
// column values. If there are more than one op_debug at that preceding
// line and column value, then select the earliest of those.
//
// We want the earliest one because when we have multiple op_debug bytecodes
// that map to a given line and column, a debugger user would expect to break
// on the first one and step through the rest thereafter if needed.
LineColumnInfoList::iterator it = std::lower_bound(list.begin(), list.end(), target);
if (it == list.end() || *it > target)
--it;
ASSERT(it >= list.begin() && it < list.end() && *it <= target);
ASSERT(it == list.begin() || *(it - 1) < *it);
line = it->line;
column = it->column;
unsigned offset = it->instructionOffset;
ASSERT(instructions()[offset].u.opcode == op_debug);
return offset;
}
static bool compareLineColumnInfo(const LineColumnInfo& first, const LineColumnInfo& second)
{
return first < second;
}
UnlinkedCodeBlock::LineColumnInfoList& UnlinkedCodeBlock::opDebugLineColumnInfoList()
{
createRareDataIfNecessary();
if (m_rareData->m_opDebugLineColumnInfoList) {
ASSERT(m_rareData->m_opDebugLineColumnInfoList->size() <= m_expressionInfo.size());
return *m_rareData->m_opDebugLineColumnInfoList;
}
} // switch
Vector<ExpressionRangeInfo>& expressionInfo = m_expressionInfo;
size_t size = m_expressionInfo.size();
m_rareData->m_opDebugLineColumnInfoList = std::make_unique<LineColumnInfoList>();
LineColumnInfoList& infoList = *m_rareData->m_opDebugLineColumnInfoList;
for (size_t src = 0; src < size; src++) {
ExpressionRangeInfo& exprInfo = expressionInfo[src];
unsigned instructionOffset = exprInfo.instructionOffset;
OpcodeID opcode = instructions()[instructionOffset].u.opcode;
if (opcode == op_debug) {
LineColumnInfo info;
info.instructionOffset = instructionOffset;
getLineAndColumn(exprInfo, info.line, info.column);
infoList.append(info);
}
}
infoList.shrinkToFit();
std::sort(infoList.begin(), infoList.end(), compareLineColumnInfo);
return *m_rareData->m_opDebugLineColumnInfoList.get();
}
void UnlinkedCodeBlock::addExpressionInfo(unsigned instructionOffset,
......
......@@ -33,7 +33,7 @@
#include "Identifier.h"
#include "JSCell.h"
#include "JSString.h"
#include "LineInfo.h"
#include "LineColumnInfo.h"
#include "ParserModes.h"
#include "RegExp.h"
#include "SpecialPointer.h"
......@@ -42,6 +42,7 @@
#include <wtf/Compression.h>
#include <wtf/RefCountedArray.h>
#include <wtf/StdLibExtras.h>
#include <wtf/Vector.h>
namespace JSC {
......@@ -444,6 +445,7 @@ public:
void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,
int& startOffset, int& endOffset, unsigned& line, unsigned& column);
unsigned opDebugBytecodeOffsetForLineAndColumn(unsigned& line, unsigned& column);
void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount, unsigned endColumn)
{
......@@ -462,6 +464,9 @@ public:
ALWAYS_INLINE unsigned startColumn() const { return 0; }
unsigned endColumn() const { return m_endColumn; }
void dumpExpressionRangeInfo(); // For debugging purpose only.
void dumpOpDebugLineColumnInfoList(); // For debugging purpose only.
protected:
UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&);
~UnlinkedCodeBlock();
......@@ -482,6 +487,11 @@ private:
m_rareData = adoptPtr(new RareData);
}
void getLineAndColumn(ExpressionRangeInfo&, unsigned& line, unsigned& column);
typedef Vector<LineColumnInfo> LineColumnInfoList;
LineColumnInfoList& opDebugLineColumnInfoList();
RefCountedArray<UnlinkedInstruction> m_unlinkedInstructions;
int m_numParameters;
......@@ -546,6 +556,7 @@ public:
Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables;
Vector<ExpressionRangeInfo::FatPosition> m_expressionInfoFatPositions;
std::unique_ptr<LineColumnInfoList> m_opDebugLineColumnInfoList;
};
private:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment