@@ -60,10 +60,6 @@ class ByteCodeParser {
6060 , m_variables(codeBlock->m_numVars)
6161 , m_temporaries(codeBlock->m_numCalleeRegisters - codeBlock->m_numVars)
6262 {
63- for (unsigned i = 0 ; i < m_arguments.size (); ++i)
64- m_arguments[i] = NoNode;
65- for (unsigned i = 0 ; i < m_variables.size (); ++i)
66- m_variables[i] = NoNode;
6763 for (unsigned i = 0 ; i < m_temporaries.size (); ++i)
6864 m_temporaries[i] = NoNode;
6965 }
@@ -86,11 +82,8 @@ class ByteCodeParser {
8682 }
8783
8884 // Is this an argument?
89- if (operand < 0 ) {
90- unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
91- ASSERT (argument < m_arguments.size ());
92- return getArgument (argument);
93- }
85+ if (operand < 0 )
86+ return getArgument (operand);
9487
9588 // Is this a variable?
9689 unsigned numVariables = m_variables.size ();
@@ -106,9 +99,8 @@ class ByteCodeParser {
10699 {
107100 // Is this an argument?
108101 if (operand < 0 ) {
109- unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
110- ASSERT (argument < m_arguments.size ());
111- return setArgument (argument, value);
102+ setArgument (operand, value);
103+ return ;
112104 }
113105
114106 // Is this a variable?
@@ -127,19 +119,24 @@ class ByteCodeParser {
127119 // Used in implementing get/set, above, where the operand is a local variable.
128120 NodeIndex getVariable (unsigned operand)
129121 {
130- NodeIndex index = m_variables[operand];
131- if (index != NoNode)
132- return index;
133- // We have not yet seen a definition for this value in this block.
134- // For now, since we are only generating single block functions,
135- // this value must be undefined.
136- // For example:
137- // function f() { var x; return x; }
138- return constantUndefined ();
122+ NodeIndex setNode = m_variables[operand].set ;
123+ if (setNode != NoNode)
124+ return m_graph[setNode].child1 ;
125+
126+ NodeIndex getNode = m_variables[operand].get ;
127+ if (getNode != NoNode)
128+ return getNode;
129+
130+ getNode = addToGraph (GetLocal, OpInfo (operand));
131+ m_variables[operand].get = getNode;
132+ return getNode;
139133 }
140- void setVariable (int operand, NodeIndex value)
134+ void setVariable (unsigned operand, NodeIndex value)
141135 {
142- m_variables[operand] = value;
136+ NodeIndex priorSet = m_variables[operand].set ;
137+ m_variables[operand].set = addToGraph (SetLocal, OpInfo (operand), value);
138+ if (priorSet != NoNode)
139+ m_graph.deref (priorSet);
143140 }
144141
145142 // Used in implementing get/set, above, where the operand is a temporary.
@@ -159,17 +156,32 @@ class ByteCodeParser {
159156 }
160157
161158 // Used in implementing get/set, above, where the operand is an argument.
162- NodeIndex getArgument (unsigned argument )
159+ NodeIndex getArgument (unsigned operand )
163160 {
164- NodeIndex index = m_arguments[argument];
165- if (index != NoNode)
166- return index;
167- NodeIndex resultIndex = addToGraph (Argument, OpInfo (argument));
168- return m_arguments[argument] = resultIndex;
161+ unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
162+ ASSERT (argument < m_arguments.size ());
163+
164+ NodeIndex setNode = m_arguments[argument].set ;
165+ if (setNode != NoNode)
166+ return m_graph[setNode].child1 ;
167+
168+ NodeIndex getNode = m_arguments[argument].get ;
169+ if (getNode != NoNode)
170+ return getNode;
171+
172+ getNode = addToGraph (GetLocal, OpInfo (operand));
173+ m_arguments[argument].get = getNode;
174+ return getNode;
169175 }
170176 void setArgument (int operand, NodeIndex value)
171177 {
172- m_arguments[operand] = value;
178+ unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
179+ ASSERT (argument < m_arguments.size ());
180+
181+ NodeIndex priorSet = m_arguments[argument].set ;
182+ m_arguments[argument].set = addToGraph (SetLocal, OpInfo (operand), value);
183+ if (priorSet != NoNode)
184+ m_graph.deref (priorSet);
173185 }
174186
175187 // Get an operand, and perform a ToInt32/ToNumber conversion on it.
@@ -300,11 +312,11 @@ class ByteCodeParser {
300312 // Helper functions to get/set the this value.
301313 NodeIndex getThis ()
302314 {
303- return getArgument (0 );
315+ return getArgument (m_codeBlock-> thisRegister () );
304316 }
305317 void setThis (NodeIndex value)
306318 {
307- setArgument (0 , value);
319+ setArgument (m_codeBlock-> thisRegister () , value);
308320 }
309321
310322 // Convenience methods for checking nodes for constants.
@@ -469,12 +481,26 @@ class ByteCodeParser {
469481 NodeIndex asNumeric;
470482 NodeIndex asJSValue;
471483 };
472- Vector <ConstantRecord, 32 > m_constants;
484+
485+ // For every local variable we track any existing get or set of the value.
486+ // We track the get so that these may be shared, and we track the set to
487+ // retrieve the current value, and to reference the final definition.
488+ struct VariableRecord {
489+ VariableRecord ()
490+ : get(NoNode)
491+ , set(NoNode)
492+ {
493+ }
494+
495+ NodeIndex get;
496+ NodeIndex set;
497+ };
473498
474499 // Track the index of the node whose result is the current value for every
475500 // register value in the bytecode - argument, local, and temporary.
476- Vector <NodeIndex, 32 > m_arguments;
477- Vector <NodeIndex, 32 > m_variables;
501+ Vector <ConstantRecord, 32 > m_constants;
502+ Vector <VariableRecord, 32 > m_arguments;
503+ Vector <VariableRecord, 32 > m_variables;
478504 Vector <NodeIndex, 32 > m_temporaries;
479505
480506 // These maps are used to unique ToNumber and ToInt32 operations.
@@ -505,8 +531,9 @@ bool ByteCodeParser::parseBlock()
505531 // === Function entry opcodes ===
506532
507533 case op_enter:
508- // This is a no-op for now - may need to initialize locals, if
509- // DCE analysis cannot determine that the values are never read.
534+ // Initialize all locals to undefined.
535+ for (int i = 0 ; i < m_codeBlock->m_numVars ; ++i)
536+ set (i, constantUndefined ());
510537 NEXT_OPCODE (op_enter);
511538
512539 case op_convert_this: {
@@ -818,6 +845,15 @@ bool ByteCodeParser::parseBlock()
818845
819846 case op_ret: {
820847 addToGraph (Return, get (currentInstruction[1 ].u .operand ));
848+
849+ // FIXME: throw away terminal definitions of variables;
850+ // should not be necessary once we have proper DCE!
851+ for (unsigned i = 0 ; i < m_variables.size (); ++i) {
852+ NodeIndex priorSet = m_variables[i].set ;
853+ if (priorSet != NoNode)
854+ m_graph.deref (priorSet);
855+ }
856+
821857 LAST_OPCODE (op_ret);
822858 }
823859
0 commit comments