Skip to content

Commit e3a890c

Browse files
author
Gavin Barraclough
committed
Bug 58696 - DFG JIT split handling of vars/temporaries
Reviewed by Sam Weinig. Presently all callee registers are treated as having single block scope, since the DFG JIT can only compile single block functions. In order to expand the JIT to support control flow we will need to change to retaining locals (but not temporaries) across basic block boundaries. * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::ByteCodeParser): (JSC::DFG::ByteCodeParser::get): (JSC::DFG::ByteCodeParser::set): (JSC::DFG::ByteCodeParser::getVariable): (JSC::DFG::ByteCodeParser::setVariable): (JSC::DFG::ByteCodeParser::getTemporary): (JSC::DFG::ByteCodeParser::setTemporary): (JSC::DFG::ByteCodeParser::getArgument): (JSC::DFG::ByteCodeParser::getInt32Constant): (JSC::DFG::ByteCodeParser::getDoubleConstant): (JSC::DFG::ByteCodeParser::getJSConstant): (JSC::DFG::ByteCodeParser::constantUndefined): (JSC::DFG::ByteCodeParser::constantNull): (JSC::DFG::ByteCodeParser::one): (JSC::DFG::ByteCodeParser::parseBlock): (JSC::DFG::ByteCodeParser::parse): (JSC::DFG::parse): * dfg/DFGNode.h: * dfg/DFGScoreBoard.h: (JSC::DFG::ScoreBoard::ScoreBoard): (JSC::DFG::ScoreBoard::~ScoreBoard): (JSC::DFG::ScoreBoard::allocate): (JSC::DFG::ScoreBoard::use): Canonical link: https://commits.webkit.org/73779@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@84037 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent b989f90 commit e3a890c

4 files changed

Lines changed: 153 additions & 70 deletions

File tree

Source/JavaScriptCore/ChangeLog

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,39 @@
1+
2011-04-15 Gavin Barraclough <barraclough@apple.com>
2+
3+
Reviewed by Sam Weinig.
4+
5+
Bug 58696 - DFG JIT split handling of vars/temporaries
6+
7+
Presently all callee registers are treated as having single block scope,
8+
since the DFG JIT can only compile single block functions. In order to
9+
expand the JIT to support control flow we will need to change to retaining
10+
locals (but not temporaries) across basic block boundaries.
11+
12+
* dfg/DFGByteCodeParser.cpp:
13+
(JSC::DFG::ByteCodeParser::ByteCodeParser):
14+
(JSC::DFG::ByteCodeParser::get):
15+
(JSC::DFG::ByteCodeParser::set):
16+
(JSC::DFG::ByteCodeParser::getVariable):
17+
(JSC::DFG::ByteCodeParser::setVariable):
18+
(JSC::DFG::ByteCodeParser::getTemporary):
19+
(JSC::DFG::ByteCodeParser::setTemporary):
20+
(JSC::DFG::ByteCodeParser::getArgument):
21+
(JSC::DFG::ByteCodeParser::getInt32Constant):
22+
(JSC::DFG::ByteCodeParser::getDoubleConstant):
23+
(JSC::DFG::ByteCodeParser::getJSConstant):
24+
(JSC::DFG::ByteCodeParser::constantUndefined):
25+
(JSC::DFG::ByteCodeParser::constantNull):
26+
(JSC::DFG::ByteCodeParser::one):
27+
(JSC::DFG::ByteCodeParser::parseBlock):
28+
(JSC::DFG::ByteCodeParser::parse):
29+
(JSC::DFG::parse):
30+
* dfg/DFGNode.h:
31+
* dfg/DFGScoreBoard.h:
32+
(JSC::DFG::ScoreBoard::ScoreBoard):
33+
(JSC::DFG::ScoreBoard::~ScoreBoard):
34+
(JSC::DFG::ScoreBoard::allocate):
35+
(JSC::DFG::ScoreBoard::use):
36+
137
2011-04-15 Michael Saboff <msaboff@apple.com>
238

339
Reviewed by Oliver Hunt.

Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

Lines changed: 103 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -55,31 +55,33 @@ class ByteCodeParser {
5555
, m_constantUndefined(UINT_MAX)
5656
, m_constantNull(UINT_MAX)
5757
, m_constant1(UINT_MAX)
58+
, m_constants(codeBlock->numberOfConstantRegisters())
59+
, m_arguments(codeBlock->m_numParameters)
60+
, m_variables(codeBlock->m_numVars)
61+
, m_temporaries(codeBlock->m_numCalleeRegisters - codeBlock->m_numVars)
5862
{
59-
unsigned numberOfConstants = codeBlock->numberOfConstantRegisters();
60-
m_constantRecords.grow(numberOfConstants);
61-
62-
unsigned numberOfParameters = codeBlock->m_numParameters;
63-
m_arguments.grow(numberOfParameters);
64-
for (unsigned i = 0; i < numberOfParameters; ++i)
63+
for (unsigned i = 0; i < m_arguments.size(); ++i)
6564
m_arguments[i] = NoNode;
66-
67-
unsigned numberOfRegisters = codeBlock->m_numCalleeRegisters;
68-
m_calleeRegisters.grow(numberOfRegisters);
69-
for (unsigned i = 0; i < numberOfRegisters; ++i)
70-
m_calleeRegisters[i] = NoNode;
65+
for (unsigned i = 0; i < m_variables.size(); ++i)
66+
m_variables[i] = NoNode;
67+
for (unsigned i = 0; i < m_temporaries.size(); ++i)
68+
m_temporaries[i] = NoNode;
7169
}
7270

71+
// Parse a full CodeBlock of bytecode.
7372
bool parse();
7473

7574
private:
75+
// Parse a single basic block of bytecode instructions.
76+
bool parseBlock();
77+
7678
// Get/Set the operands/result of a bytecode instruction.
7779
NodeIndex get(int operand)
7880
{
7981
// Is this a constant?
8082
if (operand >= FirstConstantRegisterIndex) {
8183
unsigned constant = operand - FirstConstantRegisterIndex;
82-
ASSERT(constant < m_constantRecords.size());
84+
ASSERT(constant < m_constants.size());
8385
return getJSConstant(constant);
8486
}
8587

@@ -90,9 +92,15 @@ class ByteCodeParser {
9092
return getArgument(argument);
9193
}
9294

93-
// Must be a local or temporary.
94-
ASSERT((unsigned)operand < m_calleeRegisters.size());
95-
return getRegister((unsigned)operand);
95+
// Is this a variable?
96+
unsigned numVariables = m_variables.size();
97+
if ((unsigned)operand < numVariables)
98+
return getVariable((unsigned)operand);
99+
100+
// Must be a temporary.
101+
unsigned temporary = (unsigned)operand - numVariables;
102+
ASSERT(temporary < m_temporaries.size());
103+
return getTemporary(temporary);
96104
}
97105
void set(int operand, NodeIndex value)
98106
{
@@ -103,15 +111,23 @@ class ByteCodeParser {
103111
return setArgument(argument, value);
104112
}
105113

106-
// Must be a local or temporary.
107-
ASSERT((unsigned)operand < m_calleeRegisters.size());
108-
return setRegister((unsigned)operand, value);
114+
// Is this a variable?
115+
unsigned numVariables = m_variables.size();
116+
if ((unsigned)operand < numVariables) {
117+
setVariable((unsigned)operand, value);
118+
return;
119+
}
120+
121+
// Must be a temporary.
122+
unsigned temporary = (unsigned)operand - numVariables;
123+
ASSERT(temporary < m_temporaries.size());
124+
setTemporary(temporary, value);
109125
}
110126

111-
// Used in implementing get/set, above, where the operand is a local or temporary.
112-
NodeIndex getRegister(unsigned operand)
127+
// Used in implementing get/set, above, where the operand is a local variable.
128+
NodeIndex getVariable(unsigned operand)
113129
{
114-
NodeIndex index = m_calleeRegisters[operand];
130+
NodeIndex index = m_variables[operand];
115131
if (index != NoNode)
116132
return index;
117133
// We have not yet seen a definition for this value in this block.
@@ -121,9 +137,25 @@ class ByteCodeParser {
121137
// function f() { var x; return x; }
122138
return constantUndefined();
123139
}
124-
void setRegister(int operand, NodeIndex value)
140+
void setVariable(int operand, NodeIndex value)
125141
{
126-
m_calleeRegisters[operand] = value;
142+
m_variables[operand] = value;
143+
}
144+
145+
// Used in implementing get/set, above, where the operand is a temporary.
146+
NodeIndex getTemporary(unsigned operand)
147+
{
148+
NodeIndex index = m_temporaries[operand];
149+
if (index != NoNode)
150+
return index;
151+
152+
// Detect a read of an temporary that is not a yet defined within this block (e.g. use of ?:).
153+
m_parseFailed = true;
154+
return constantUndefined();
155+
}
156+
void setTemporary(int operand, NodeIndex value)
157+
{
158+
m_temporaries[operand] = value;
127159
}
128160

129161
// Used in implementing get/set, above, where the operand is an argument.
@@ -132,8 +164,7 @@ class ByteCodeParser {
132164
NodeIndex index = m_arguments[argument];
133165
if (index != NoNode)
134166
return index;
135-
NodeIndex resultIndex = (NodeIndex)m_graph.size();
136-
m_graph.append(Node(Argument, m_currentIndex, OpInfo(argument)));
167+
NodeIndex resultIndex = addToGraph(Argument, OpInfo(argument));
137168
return m_arguments[argument] = resultIndex;
138169
}
139170
void setArgument(int operand, NodeIndex value)
@@ -237,35 +268,32 @@ class ByteCodeParser {
237268
// Used in implementing get, above, where the operand is a constant.
238269
NodeIndex getInt32Constant(int32_t value, unsigned constant)
239270
{
240-
NodeIndex index = m_constantRecords[constant].asInt32;
271+
NodeIndex index = m_constants[constant].asInt32;
241272
if (index != NoNode)
242273
return index;
243-
NodeIndex resultIndex = (NodeIndex)m_graph.size();
244-
m_graph.append(Node(Int32Constant, m_currentIndex, OpInfo(constant)));
274+
NodeIndex resultIndex = addToGraph(Int32Constant, OpInfo(constant));
245275
m_graph[resultIndex].setInt32Constant(value);
246-
m_constantRecords[constant].asInt32 = resultIndex;
276+
m_constants[constant].asInt32 = resultIndex;
247277
return resultIndex;
248278
}
249279
NodeIndex getDoubleConstant(double value, unsigned constant)
250280
{
251-
NodeIndex index = m_constantRecords[constant].asNumeric;
281+
NodeIndex index = m_constants[constant].asNumeric;
252282
if (index != NoNode)
253283
return index;
254-
NodeIndex resultIndex = (NodeIndex)m_graph.size();
255-
m_graph.append(Node(DoubleConstant, m_currentIndex, OpInfo(constant)));
284+
NodeIndex resultIndex = addToGraph(DoubleConstant, OpInfo(constant));
256285
m_graph[resultIndex].setDoubleConstant(value);
257-
m_constantRecords[constant].asNumeric = resultIndex;
286+
m_constants[constant].asNumeric = resultIndex;
258287
return resultIndex;
259288
}
260289
NodeIndex getJSConstant(unsigned constant)
261290
{
262-
NodeIndex index = m_constantRecords[constant].asJSValue;
291+
NodeIndex index = m_constants[constant].asJSValue;
263292
if (index != NoNode)
264293
return index;
265294

266-
NodeIndex resultIndex = (NodeIndex)m_graph.size();
267-
m_graph.append(Node(JSConstant, m_currentIndex, OpInfo(constant)));
268-
m_constantRecords[constant].asJSValue = resultIndex;
295+
NodeIndex resultIndex = addToGraph(JSConstant, OpInfo(constant));
296+
m_constants[constant].asJSValue = resultIndex;
269297
return resultIndex;
270298
}
271299

@@ -323,11 +351,11 @@ class ByteCodeParser {
323351
return getJSConstant(m_constantUndefined);
324352
}
325353

326-
// Add undefined to the CodeBlock's constants, and add a corresponding slot in m_constantRecords.
327-
ASSERT(m_constantRecords.size() == numberOfConstants);
354+
// Add undefined to the CodeBlock's constants, and add a corresponding slot in m_constants.
355+
ASSERT(m_constants.size() == numberOfConstants);
328356
m_codeBlock->addConstant(jsUndefined());
329-
m_constantRecords.append(ConstantRecord());
330-
ASSERT(m_constantRecords.size() == m_codeBlock->numberOfConstantRegisters());
357+
m_constants.append(ConstantRecord());
358+
ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
331359
}
332360

333361
// m_constantUndefined must refer to an entry in the CodeBlock's constant pool that has the value 'undefined'.
@@ -348,11 +376,11 @@ class ByteCodeParser {
348376
return getJSConstant(m_constantNull);
349377
}
350378

351-
// Add null to the CodeBlock's constants, and add a corresponding slot in m_constantRecords.
352-
ASSERT(m_constantRecords.size() == numberOfConstants);
379+
// Add null to the CodeBlock's constants, and add a corresponding slot in m_constants.
380+
ASSERT(m_constants.size() == numberOfConstants);
353381
m_codeBlock->addConstant(jsNull());
354-
m_constantRecords.append(ConstantRecord());
355-
ASSERT(m_constantRecords.size() == m_codeBlock->numberOfConstantRegisters());
382+
m_constants.append(ConstantRecord());
383+
ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
356384
}
357385

358386
// m_constantNull must refer to an entry in the CodeBlock's constant pool that has the value 'null'.
@@ -373,11 +401,11 @@ class ByteCodeParser {
373401
return getDoubleConstant(1, m_constant1);
374402
}
375403

376-
// Add the value 1 to the CodeBlock's constants, and add a corresponding slot in m_constantRecords.
377-
ASSERT(m_constantRecords.size() == numberOfConstants);
404+
// Add the value 1 to the CodeBlock's constants, and add a corresponding slot in m_constants.
405+
ASSERT(m_constants.size() == numberOfConstants);
378406
m_codeBlock->addConstant(jsNumber(1));
379-
m_constantRecords.append(ConstantRecord());
380-
ASSERT(m_constantRecords.size() == m_codeBlock->numberOfConstantRegisters());
407+
m_constants.append(ConstantRecord());
408+
ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
381409
}
382410

383411
// m_constant1 must refer to an entry in the CodeBlock's constant pool that has the integer value 1.
@@ -441,12 +469,13 @@ class ByteCodeParser {
441469
NodeIndex asNumeric;
442470
NodeIndex asJSValue;
443471
};
444-
Vector <ConstantRecord, 32> m_constantRecords;
472+
Vector <ConstantRecord, 32> m_constants;
445473

446474
// Track the index of the node whose result is the current value for every
447475
// register value in the bytecode - argument, local, and temporary.
448476
Vector <NodeIndex, 32> m_arguments;
449-
Vector <NodeIndex, 32> m_calleeRegisters;
477+
Vector <NodeIndex, 32> m_variables;
478+
Vector <NodeIndex, 32> m_temporaries;
450479

451480
// These maps are used to unique ToNumber and ToInt32 operations.
452481
typedef HashMap<NodeIndex, NodeIndex> UnaryOpMap;
@@ -462,7 +491,7 @@ class ByteCodeParser {
462491
m_currentIndex += OPCODE_LENGTH(name); \
463492
return !m_parseFailed
464493

465-
bool ByteCodeParser::parse()
494+
bool ByteCodeParser::parseBlock()
466495
{
467496
AliasTracker aliases(m_graph);
468497

@@ -799,17 +828,15 @@ bool ByteCodeParser::parse()
799828
}
800829
}
801830

802-
bool parse(Graph& graph, JSGlobalData* globalData, CodeBlock* codeBlock)
831+
bool ByteCodeParser::parse()
803832
{
804-
// Call ByteCodeParser::parse to build the dataflow for the basic block at 'startIndex'.
805-
ByteCodeParser state(globalData, codeBlock, graph);
806-
if (!state.parse())
833+
if (!parseBlock())
807834
return false;
808835

809836
// Assign VirtualRegisters.
810-
ScoreBoard scoreBoard(graph);
811-
Node* nodes = graph.begin();
812-
size_t size = graph.size();
837+
ScoreBoard scoreBoard(m_graph, m_variables.size());
838+
Node* nodes = m_graph.begin();
839+
size_t size = m_graph.size();
813840
for (size_t i = 0; i < size; ++i) {
814841
Node& node = nodes[i];
815842
if (node.refCount) {
@@ -831,15 +858,29 @@ bool parse(Graph& graph, JSGlobalData* globalData, CodeBlock* codeBlock)
831858
// 'm_numCalleeRegisters' is the number of locals and temporaries allocated
832859
// for the function (and checked for on entry). Since we perform a new and
833860
// different allocation of temporaries, more registers may now be required.
834-
if ((unsigned)codeBlock->m_numCalleeRegisters < scoreBoard.allocatedCount())
835-
codeBlock->m_numCalleeRegisters = scoreBoard.allocatedCount();
861+
unsigned calleeRegisters = scoreBoard.allocatedCount() + m_variables.size();
862+
if ((unsigned)m_codeBlock->m_numCalleeRegisters < calleeRegisters)
863+
m_codeBlock->m_numCalleeRegisters = calleeRegisters;
836864

837865
#if DFG_DEBUG_VERBOSE
838-
graph.dump(codeBlock);
866+
m_graph.dump(m_codeBlock);
839867
#endif
868+
840869
return true;
841870
}
842871

872+
bool parse(Graph& graph, JSGlobalData* globalData, CodeBlock* codeBlock)
873+
{
874+
#if DFG_DEBUG_LOCAL_DISBALE
875+
UNUSED_PARAM(graph);
876+
UNUSED_PARAM(globalData);
877+
UNUSED_PARAM(codeBlock);
878+
return false;
879+
#else
880+
return ByteCodeParser(globalData, codeBlock, graph).parse();
881+
#endif
882+
}
883+
843884
} } // namespace JSC::DFG
844885

845886
#endif

Source/JavaScriptCore/dfg/DFGNode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
#define DFG_CONSISTENCY_CHECK 0
3939
// Emit a breakpoint into the head of every generated function, to aid debugging in GDB.
4040
#define DFG_JIT_BREAK_ON_ENTRY 0
41+
// Disable the DFG JIT without having to touch Platform.h!
42+
#define DFG_DEBUG_LOCAL_DISBALE 0
4143

4244

4345
namespace JSC { namespace DFG {

0 commit comments

Comments
 (0)