Index: src/compiler/frame-states.cc |
diff --git a/src/compiler/frame-states.cc b/src/compiler/frame-states.cc |
index b9ea010cccdb38e7caf98b337879db996d497e36..fb3740d06256b551fc383ca8df3dd6e4745fe204 100644 |
--- a/src/compiler/frame-states.cc |
+++ b/src/compiler/frame-states.cc |
@@ -2,8 +2,13 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "src/base/functional.h" |
#include "src/compiler/frame-states.h" |
+ |
+#include "src/base/functional.h" |
+#include "src/compiler/code-generator.h" |
+#include "src/compiler/instruction-selector-impl.h" |
+#include "src/compiler/node.h" |
+#include "src/compiler/state-values-utils.h" |
#include "src/handles-inl.h" |
namespace v8 { |
@@ -72,6 +77,225 @@ std::ostream& operator<<(std::ostream& os, FrameStateInfo const& info) { |
return os; |
} |
+ |
+FrameStateDescriptor::FrameStateDescriptor( |
+ Zone* zone, FrameStateType type, BailoutId bailout_id, |
+ OutputFrameStateCombine state_combine, size_t parameters_count, |
+ size_t locals_count, size_t stack_count, |
+ MaybeHandle<SharedFunctionInfo> shared_info, |
+ FrameStateDescriptor* outer_state) |
+ : type_(type), |
+ bailout_id_(bailout_id), |
+ frame_state_combine_(state_combine), |
+ parameters_count_(parameters_count), |
+ locals_count_(locals_count), |
+ stack_count_(stack_count), |
+ values_(zone, kMachAnyTagged), |
+ shared_info_(shared_info), |
+ outer_state_(outer_state) {} |
+ |
+ |
+size_t FrameStateDescriptor::GetSize(OutputFrameStateCombine combine) const { |
+ size_t size = 1 + parameters_count() + locals_count() + stack_count() + |
+ (HasContext() ? 1 : 0); |
+ switch (combine.kind()) { |
+ case OutputFrameStateCombine::kPushOutput: |
+ size += combine.GetPushCount(); |
+ break; |
+ case OutputFrameStateCombine::kPokeAt: |
+ break; |
+ } |
+ return size; |
+} |
+ |
+ |
+size_t FrameStateDescriptor::GetTotalSize() const { |
+ size_t total_size = 0; |
+ for (const FrameStateDescriptor* iter = this; iter != NULL; |
+ iter = iter->outer_state_) { |
+ total_size += iter->GetSize(); |
+ } |
+ return total_size; |
+} |
+ |
+ |
+size_t FrameStateDescriptor::GetFrameCount() const { |
+ size_t count = 0; |
+ for (const FrameStateDescriptor* iter = this; iter != NULL; |
+ iter = iter->outer_state_) { |
+ ++count; |
+ } |
+ return count; |
+} |
+ |
+ |
+size_t FrameStateDescriptor::GetJSFrameCount() const { |
+ size_t count = 0; |
+ for (const FrameStateDescriptor* iter = this; iter != NULL; |
+ iter = iter->outer_state_) { |
+ if (iter->type_ == FrameStateType::kJavaScriptFunction) { |
+ ++count; |
+ } |
+ } |
+ return count; |
+} |
+ |
+ |
+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.
|
+ OperandGenerator* g, |
+ StateObjectCache* cache, Node* input, |
+ MachineType type, |
+ FrameStateInputKind kind, Zone* zone) { |
+ switch (input->opcode()) { |
+ case IrOpcode::kObjectState: { |
+ size_t id = cache->GetObjectId(input); |
+ if (id == StateObjectCache::kNotCached) { |
+ size_t entries = 0; |
+ id = cache->InsertObject(input); |
+ fields_.push_back(StateValueDescriptor(zone, kMachAnyTagged, id)); |
+ StateValueDescriptor& desc = fields_.back(); |
+ for (Edge edge : input->input_edges()) { |
+ entries += desc.AddOperand(inputs, g, cache, edge.to(), |
+ kMachAnyTagged, kind, zone); |
+ } |
+ return entries; |
+ } else { |
+ 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.
|
+ return 0; |
+ } |
+ } break; |
Jarin
2015/12/02 12:24:34
The "break;" should go before the brace.
sigurds
2015/12/02 16:35:12
Done.
|
+ default: |
+ inputs->push_back(g->UseForDeopt(input, kind)); |
+ fields_.push_back(StateValueDescriptor(zone, type)); |
+ return 1; |
+ } |
+} |
+ |
+ |
+size_t FrameStateDescriptor::AddInputs(Node* state, OperandGenerator* g, |
+ StateObjectCache* cache, |
+ InstructionOperandVector* inputs, |
+ FrameStateInputKind kind, Zone* zone) { |
+ DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode()); |
+ |
+ size_t entries = 0; |
+ size_t initial_size = inputs->size(); |
+ |
+ if (outer_state()) { |
+ entries += |
+ outer_state()->AddInputs(state->InputAt(kFrameStateOuterStateInput), g, |
+ cache, inputs, kind, zone); |
+ } |
+ |
+ Node* parameters = state->InputAt(kFrameStateParametersInput); |
+ Node* locals = state->InputAt(kFrameStateLocalsInput); |
+ Node* stack = state->InputAt(kFrameStateStackInput); |
+ Node* context = state->InputAt(kFrameStateContextInput); |
+ Node* function = state->InputAt(kFrameStateFunctionInput); |
+ |
+ DCHECK_EQ(parameters_count(), StateValuesAccess(parameters).size()); |
+ DCHECK_EQ(locals_count(), StateValuesAccess(locals).size()); |
+ DCHECK_EQ(stack_count(), StateValuesAccess(stack).size()); |
+ |
+ StateValueDescriptor* desc = GetStateValueDescriptor(); |
+ entries += |
+ desc->AddOperand(inputs, g, cache, function, kMachAnyTagged, kind, zone); |
+ for (StateValuesAccess::TypedNode input_node : |
+ StateValuesAccess(parameters)) { |
+ entries += desc->AddOperand(inputs, g, cache, input_node.node, |
+ input_node.type, kind, zone); |
+ } |
+ if (HasContext()) { |
+ entries += |
+ desc->AddOperand(inputs, g, cache, context, kMachAnyTagged, kind, zone); |
+ } |
+ for (StateValuesAccess::TypedNode input_node : StateValuesAccess(locals)) { |
+ entries += desc->AddOperand(inputs, g, cache, input_node.node, |
+ input_node.type, kind, zone); |
+ } |
+ for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) { |
+ entries += desc->AddOperand(inputs, g, cache, input_node.node, |
+ input_node.type, kind, zone); |
+ } |
+ DCHECK_EQ(initial_size + entries, inputs->size()); |
+ return entries; |
+} |
+ |
+ |
+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.
|
+ Translation* translation, |
+ Instruction* instr, |
+ size_t frame_state_offset) { |
+ if (IsRecursive()) { |
+ size_t entries = 0; |
+ translation->BeginCapturedObject(static_cast<int>(size())); |
+ for (size_t index = 0; index < fields_.size(); index++) { |
+ entries += fields_[index].Translate(gen, translation, instr, |
+ frame_state_offset + index); |
+ } |
+ return entries; |
+ } else if (IsDuplicate()) { |
+ translation->DuplicateObject(static_cast<int>(id_)); |
+ return 0; |
+ } else { |
+ gen->AddTranslationForOperand(translation, instr, |
+ instr->InputAt(frame_state_offset), type_); |
+ return 1; |
+ } |
+} |
+ |
+ |
+size_t StateValueDescriptor::TranslateOperand(size_t index, CodeGenerator* gen, |
+ Translation* translation, |
+ Instruction* instr, |
+ size_t frame_state_offset) { |
+ return fields_[index].Translate(gen, translation, instr, |
+ frame_state_offset + index); |
+} |
+ |
+ |
+void FrameStateDescriptor::TranslateOperands(CodeGenerator* gen, |
+ Instruction* instr, |
+ size_t frame_state_offset, |
+ OutputFrameStateCombine combine, |
+ Translation* translation) { |
+ for (size_t index = 0; index < GetSize(combine); index++) { |
+ switch (combine.kind()) { |
+ case OutputFrameStateCombine::kPushOutput: { |
+ DCHECK(combine.GetPushCount() <= instr->OutputCount()); |
+ size_t size_without_output = GetSize(OutputFrameStateCombine::Ignore()); |
+ // If the index is past the existing stack items in values_. |
+ if (index >= size_without_output) { |
+ // Materialize the result of the call instruction in this slot. |
+ gen->AddTranslationForOperand( |
+ translation, instr, instr->OutputAt(index - size_without_output), |
+ kMachAnyTagged); |
+ continue; |
+ } |
+ break; |
+ } |
+ case OutputFrameStateCombine::kPokeAt: |
+ // The result of the call should be placed at position |
+ // [index_from_top] in the stack (overwriting whatever was |
+ // previously there). |
+ size_t index_from_top = |
+ GetSize(combine) - 1 - combine.GetOffsetToPokeAt(); |
+ if (index >= index_from_top && |
+ index < index_from_top + instr->OutputCount()) { |
+ gen->AddTranslationForOperand(translation, instr, |
+ instr->OutputAt(index - index_from_top), |
+ kMachAnyTagged); |
+ continue; |
+ } |
+ break; |
+ } |
+ // Add the additional fields we read during materialization. |
+ frame_state_offset += values_.TranslateOperand(index, gen, translation, |
+ instr, frame_state_offset) - |
+ 1; |
+ } |
+} |
+ |
} // namespace compiler |
} // namespace internal |
} // namespace v8 |