Chromium Code Reviews| 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 |