OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/frame-states.h" | |
6 | |
5 #include "src/base/functional.h" | 7 #include "src/base/functional.h" |
6 #include "src/compiler/frame-states.h" | 8 #include "src/compiler/code-generator.h" |
9 #include "src/compiler/instruction-selector-impl.h" | |
10 #include "src/compiler/node.h" | |
11 #include "src/compiler/state-values-utils.h" | |
7 #include "src/handles-inl.h" | 12 #include "src/handles-inl.h" |
8 | 13 |
9 namespace v8 { | 14 namespace v8 { |
10 namespace internal { | 15 namespace internal { |
11 namespace compiler { | 16 namespace compiler { |
12 | 17 |
13 size_t hash_value(OutputFrameStateCombine const& sc) { | 18 size_t hash_value(OutputFrameStateCombine const& sc) { |
14 return base::hash_combine(sc.kind_, sc.parameter_); | 19 return base::hash_combine(sc.kind_, sc.parameter_); |
15 } | 20 } |
16 | 21 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
65 std::ostream& operator<<(std::ostream& os, FrameStateInfo const& info) { | 70 std::ostream& operator<<(std::ostream& os, FrameStateInfo const& info) { |
66 os << info.type() << ", " << info.bailout_id() << ", " | 71 os << info.type() << ", " << info.bailout_id() << ", " |
67 << info.state_combine(); | 72 << info.state_combine(); |
68 Handle<SharedFunctionInfo> shared_info; | 73 Handle<SharedFunctionInfo> shared_info; |
69 if (info.shared_info().ToHandle(&shared_info)) { | 74 if (info.shared_info().ToHandle(&shared_info)) { |
70 os << ", " << Brief(*shared_info); | 75 os << ", " << Brief(*shared_info); |
71 } | 76 } |
72 return os; | 77 return os; |
73 } | 78 } |
74 | 79 |
80 | |
81 FrameStateDescriptor::FrameStateDescriptor( | |
82 Zone* zone, FrameStateType type, BailoutId bailout_id, | |
83 OutputFrameStateCombine state_combine, size_t parameters_count, | |
84 size_t locals_count, size_t stack_count, | |
85 MaybeHandle<SharedFunctionInfo> shared_info, | |
86 FrameStateDescriptor* outer_state) | |
87 : type_(type), | |
88 bailout_id_(bailout_id), | |
89 frame_state_combine_(state_combine), | |
90 parameters_count_(parameters_count), | |
91 locals_count_(locals_count), | |
92 stack_count_(stack_count), | |
93 values_(zone, kMachAnyTagged), | |
94 shared_info_(shared_info), | |
95 outer_state_(outer_state) {} | |
96 | |
97 | |
98 size_t FrameStateDescriptor::GetSize(OutputFrameStateCombine combine) const { | |
99 size_t size = 1 + parameters_count() + locals_count() + stack_count() + | |
100 (HasContext() ? 1 : 0); | |
101 switch (combine.kind()) { | |
102 case OutputFrameStateCombine::kPushOutput: | |
103 size += combine.GetPushCount(); | |
104 break; | |
105 case OutputFrameStateCombine::kPokeAt: | |
106 break; | |
107 } | |
108 return size; | |
109 } | |
110 | |
111 | |
112 size_t FrameStateDescriptor::GetTotalSize() const { | |
113 size_t total_size = 0; | |
114 for (const FrameStateDescriptor* iter = this; iter != NULL; | |
115 iter = iter->outer_state_) { | |
116 total_size += iter->GetSize(); | |
117 } | |
118 return total_size; | |
119 } | |
120 | |
121 | |
122 size_t FrameStateDescriptor::GetFrameCount() const { | |
123 size_t count = 0; | |
124 for (const FrameStateDescriptor* iter = this; iter != NULL; | |
125 iter = iter->outer_state_) { | |
126 ++count; | |
127 } | |
128 return count; | |
129 } | |
130 | |
131 | |
132 size_t FrameStateDescriptor::GetJSFrameCount() const { | |
133 size_t count = 0; | |
134 for (const FrameStateDescriptor* iter = this; iter != NULL; | |
135 iter = iter->outer_state_) { | |
136 if (iter->type_ == FrameStateType::kJavaScriptFunction) { | |
137 ++count; | |
138 } | |
139 } | |
140 return count; | |
141 } | |
142 | |
143 | |
144 size_t StateValueDescriptor::AddOperand(InstructionOperandVector* inputs, | |
Jarin
2015/12/02 12:24:34
Could we have a comment explaining what the return
sigurds
2015/12/02 16:35:13
Done.
| |
145 OperandGenerator* g, | |
146 StateObjectCache* cache, Node* input, | |
147 MachineType type, | |
148 FrameStateInputKind kind, Zone* zone) { | |
149 switch (input->opcode()) { | |
150 case IrOpcode::kObjectState: { | |
151 size_t id = cache->GetObjectId(input); | |
152 if (id == StateObjectCache::kNotCached) { | |
153 size_t entries = 0; | |
154 id = cache->InsertObject(input); | |
155 fields_.push_back(StateValueDescriptor(zone, kMachAnyTagged, id)); | |
156 StateValueDescriptor& desc = fields_.back(); | |
157 for (Edge edge : input->input_edges()) { | |
158 entries += desc.AddOperand(inputs, g, cache, edge.to(), | |
159 kMachAnyTagged, kind, zone); | |
160 } | |
161 return entries; | |
162 } else { | |
163 fields_.push_back(StateValueDescriptor(zone, kMachAnyTagged, id)); | |
Jarin
2015/12/02 12:24:34
I think it would be nice to somehow signal in the
sigurds
2015/12/02 16:35:13
Great idea, thanks.
| |
164 return 0; | |
165 } | |
166 } break; | |
Jarin
2015/12/02 12:24:34
The "break;" should go before the brace.
sigurds
2015/12/02 16:35:12
Done.
| |
167 default: | |
168 inputs->push_back(g->UseForDeopt(input, kind)); | |
169 fields_.push_back(StateValueDescriptor(zone, type)); | |
170 return 1; | |
171 } | |
172 } | |
173 | |
174 | |
175 size_t FrameStateDescriptor::AddInputs(Node* state, OperandGenerator* g, | |
176 StateObjectCache* cache, | |
177 InstructionOperandVector* inputs, | |
178 FrameStateInputKind kind, Zone* zone) { | |
179 DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode()); | |
180 | |
181 size_t entries = 0; | |
182 size_t initial_size = inputs->size(); | |
183 | |
184 if (outer_state()) { | |
185 entries += | |
186 outer_state()->AddInputs(state->InputAt(kFrameStateOuterStateInput), g, | |
187 cache, inputs, kind, zone); | |
188 } | |
189 | |
190 Node* parameters = state->InputAt(kFrameStateParametersInput); | |
191 Node* locals = state->InputAt(kFrameStateLocalsInput); | |
192 Node* stack = state->InputAt(kFrameStateStackInput); | |
193 Node* context = state->InputAt(kFrameStateContextInput); | |
194 Node* function = state->InputAt(kFrameStateFunctionInput); | |
195 | |
196 DCHECK_EQ(parameters_count(), StateValuesAccess(parameters).size()); | |
197 DCHECK_EQ(locals_count(), StateValuesAccess(locals).size()); | |
198 DCHECK_EQ(stack_count(), StateValuesAccess(stack).size()); | |
199 | |
200 StateValueDescriptor* desc = GetStateValueDescriptor(); | |
201 entries += | |
202 desc->AddOperand(inputs, g, cache, function, kMachAnyTagged, kind, zone); | |
203 for (StateValuesAccess::TypedNode input_node : | |
204 StateValuesAccess(parameters)) { | |
205 entries += desc->AddOperand(inputs, g, cache, input_node.node, | |
206 input_node.type, kind, zone); | |
207 } | |
208 if (HasContext()) { | |
209 entries += | |
210 desc->AddOperand(inputs, g, cache, context, kMachAnyTagged, kind, zone); | |
211 } | |
212 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(locals)) { | |
213 entries += desc->AddOperand(inputs, g, cache, input_node.node, | |
214 input_node.type, kind, zone); | |
215 } | |
216 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) { | |
217 entries += desc->AddOperand(inputs, g, cache, input_node.node, | |
218 input_node.type, kind, zone); | |
219 } | |
220 DCHECK_EQ(initial_size + entries, inputs->size()); | |
221 return entries; | |
222 } | |
223 | |
224 | |
225 size_t StateValueDescriptor::Translate(CodeGenerator* gen, | |
Jarin
2015/12/02 12:24:34
Description of return value, please. (Number of co
sigurds
2015/12/02 16:35:13
Done.
| |
226 Translation* translation, | |
227 Instruction* instr, | |
228 size_t frame_state_offset) { | |
229 if (IsRecursive()) { | |
230 size_t entries = 0; | |
231 translation->BeginCapturedObject(static_cast<int>(size())); | |
232 for (size_t index = 0; index < fields_.size(); index++) { | |
233 entries += fields_[index].Translate(gen, translation, instr, | |
234 frame_state_offset + index); | |
235 } | |
236 return entries; | |
237 } else if (IsDuplicate()) { | |
238 translation->DuplicateObject(static_cast<int>(id_)); | |
239 return 0; | |
240 } else { | |
241 gen->AddTranslationForOperand(translation, instr, | |
242 instr->InputAt(frame_state_offset), type_); | |
243 return 1; | |
244 } | |
245 } | |
246 | |
247 | |
248 size_t StateValueDescriptor::TranslateOperand(size_t index, CodeGenerator* gen, | |
249 Translation* translation, | |
250 Instruction* instr, | |
251 size_t frame_state_offset) { | |
252 return fields_[index].Translate(gen, translation, instr, | |
253 frame_state_offset + index); | |
254 } | |
255 | |
256 | |
257 void FrameStateDescriptor::TranslateOperands(CodeGenerator* gen, | |
258 Instruction* instr, | |
259 size_t frame_state_offset, | |
260 OutputFrameStateCombine combine, | |
261 Translation* translation) { | |
262 for (size_t index = 0; index < GetSize(combine); index++) { | |
263 switch (combine.kind()) { | |
264 case OutputFrameStateCombine::kPushOutput: { | |
265 DCHECK(combine.GetPushCount() <= instr->OutputCount()); | |
266 size_t size_without_output = GetSize(OutputFrameStateCombine::Ignore()); | |
267 // If the index is past the existing stack items in values_. | |
268 if (index >= size_without_output) { | |
269 // Materialize the result of the call instruction in this slot. | |
270 gen->AddTranslationForOperand( | |
271 translation, instr, instr->OutputAt(index - size_without_output), | |
272 kMachAnyTagged); | |
273 continue; | |
274 } | |
275 break; | |
276 } | |
277 case OutputFrameStateCombine::kPokeAt: | |
278 // The result of the call should be placed at position | |
279 // [index_from_top] in the stack (overwriting whatever was | |
280 // previously there). | |
281 size_t index_from_top = | |
282 GetSize(combine) - 1 - combine.GetOffsetToPokeAt(); | |
283 if (index >= index_from_top && | |
284 index < index_from_top + instr->OutputCount()) { | |
285 gen->AddTranslationForOperand(translation, instr, | |
286 instr->OutputAt(index - index_from_top), | |
287 kMachAnyTagged); | |
288 continue; | |
289 } | |
290 break; | |
291 } | |
292 // Add the additional fields we read during materialization. | |
293 frame_state_offset += values_.TranslateOperand(index, gen, translation, | |
294 instr, frame_state_offset) - | |
295 1; | |
296 } | |
297 } | |
298 | |
75 } // namespace compiler | 299 } // namespace compiler |
76 } // namespace internal | 300 } // namespace internal |
77 } // namespace v8 | 301 } // namespace v8 |
OLD | NEW |