Index: src/compiler/graph-assembler.cc |
diff --git a/src/compiler/graph-assembler.cc b/src/compiler/graph-assembler.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..988cf147911b4cb6a75bc177a2a98aec165ca39a |
--- /dev/null |
+++ b/src/compiler/graph-assembler.cc |
@@ -0,0 +1,297 @@ |
+// Copyright 2015 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "src/compiler/graph-assembler.h" |
+ |
+#include "src/code-factory.h" |
+#include "src/compiler/linkage.h" |
+ |
+namespace v8 { |
+namespace internal { |
+namespace compiler { |
+ |
+GraphAssembler::GraphAssembler(JSGraph* jsgraph, Node* effect, Node* control, |
+ Zone* zone) |
+ : temp_zone_(zone), |
+ jsgraph_(jsgraph), |
+ current_effect_(effect), |
+ current_control_(control) {} |
+ |
+Node* GraphAssembler::TrueConstant() { return jsgraph()->TrueConstant(); } |
+ |
+Node* GraphAssembler::FalseConstant() { return jsgraph()->FalseConstant(); } |
+ |
+Node* GraphAssembler::HeapNumberMapConstant() { |
+ return jsgraph()->HeapNumberMapConstant(); |
+} |
+ |
+Node* GraphAssembler::IntPtrConstant(intptr_t value) { |
+ return jsgraph()->IntPtrConstant(value); |
+} |
+ |
+Node* GraphAssembler::Int32Constant(int32_t value) { |
+ return jsgraph()->Int32Constant(value); |
+} |
+ |
+Node* GraphAssembler::SmiConstant(int32_t value) { |
+ return jsgraph()->SmiConstant(value); |
+} |
+ |
+Node* GraphAssembler::Uint32Constant(int32_t value) { |
+ return jsgraph()->Uint32Constant(value); |
+} |
+ |
+Node* GraphAssembler::Float64Constant(double value) { |
+ return jsgraph()->Float64Constant(value); |
+} |
+ |
+Node* GraphAssembler::HeapConstant(Handle<HeapObject> object) { |
+ return jsgraph()->HeapConstant(object); |
+} |
+ |
+Node* GraphAssembler::NoContextConstant() { |
+ return jsgraph()->NoContextConstant(); |
+} |
+ |
+Node* GraphAssembler::ExternalConstant(ExternalReference ref) { |
+ return jsgraph()->ExternalConstant(ref); |
+} |
+ |
+Node* GraphAssembler::CEntryStubConstant(int result_size) { |
+ return jsgraph()->CEntryStubConstant(result_size); |
+} |
+ |
+Node* GraphAssembler::EmptyStringConstant() { |
+ return jsgraph()->EmptyStringConstant(); |
+} |
+ |
+Node* GraphAssembler::UndefinedConstant() { |
+ return jsgraph()->UndefinedConstant(); |
+} |
+ |
+Node* GraphAssembler::TheHoleConstant() { return jsgraph()->TheHoleConstant(); } |
+ |
+Node* GraphAssembler::FixedArrayMapConstant() { |
+ return jsgraph()->FixedArrayMapConstant(); |
+} |
+ |
+#define PURE_UNOP_DEF(Name) \ |
+ Node* GraphAssembler::Name(Node* input) { \ |
+ return graph()->NewNode(machine()->Name(), input); \ |
+ } |
+PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DEF) |
+#undef PURE_UNOP_DEF |
+ |
+#define PURE_BINOP_DEF(Name) \ |
+ Node* GraphAssembler::Name(Node* left, Node* right) { \ |
+ return graph()->NewNode(machine()->Name(), left, right); \ |
+ } |
+PURE_ASSEMBLER_MACH_BINOP_LIST(PURE_BINOP_DEF) |
+#undef PURE_BINOP_DEF |
+ |
+#define CHECKED_BINOP_DEF(Name) \ |
+ Node* GraphAssembler::Name(Node* left, Node* right) { \ |
+ return graph()->NewNode(machine()->Name(), left, right, current_control_); \ |
+ } |
+CHECKED_ASSEMBLER_MACH_BINOP_LIST(CHECKED_BINOP_DEF) |
+#undef CHECKED_BINOP_DEF |
+ |
+Node* GraphAssembler::Float64RoundDown(Node* value) { |
+ if (machine()->Float64RoundDown().IsSupported()) { |
+ return graph()->NewNode(machine()->Float64RoundDown().op(), value); |
+ } |
+ return nullptr; |
+} |
+ |
+Node* GraphAssembler::Projection(int index, Node* value) { |
+ return graph()->NewNode(common()->Projection(index), value, current_control_); |
+} |
+ |
+Node* GraphAssembler::Allocate(PretenureFlag pretenure, Node* size) { |
+ return current_effect_ = |
+ graph()->NewNode(simplified()->Allocate(NOT_TENURED), size, |
+ current_effect_, current_control_); |
+} |
+ |
+Node* GraphAssembler::LoadField(FieldAccess const& access, Node* object) { |
+ return current_effect_ = |
+ graph()->NewNode(simplified()->LoadField(access), object, |
+ current_effect_, current_control_); |
+} |
+ |
+Node* GraphAssembler::LoadElement(ElementAccess const& access, Node* object, |
+ Node* index) { |
+ return current_effect_ = |
+ graph()->NewNode(simplified()->LoadElement(access), object, index, |
+ current_effect_, current_control_); |
+} |
+ |
+Node* GraphAssembler::StoreField(FieldAccess const& access, Node* object, |
+ Node* value) { |
+ return current_effect_ = |
+ graph()->NewNode(simplified()->StoreField(access), object, value, |
+ current_effect_, current_control_); |
+} |
+ |
+Node* GraphAssembler::StoreElement(ElementAccess const& access, Node* object, |
+ Node* index, Node* value) { |
+ return current_effect_ = |
+ graph()->NewNode(simplified()->StoreElement(access), object, index, |
+ value, current_effect_, current_control_); |
+} |
+ |
+Node* GraphAssembler::Store(StoreRepresentation rep, Node* object, Node* offset, |
+ Node* value) { |
+ return current_effect_ = |
+ graph()->NewNode(machine()->Store(rep), object, offset, value, |
+ current_effect_, current_control_); |
+} |
+ |
+Node* GraphAssembler::Retain(Node* buffer) { |
+ return current_effect_ = |
+ graph()->NewNode(common()->Retain(), buffer, current_effect_); |
+} |
+ |
+Node* GraphAssembler::UnsafePointerAdd(Node* base, Node* external) { |
+ return current_effect_ = |
+ graph()->NewNode(machine()->UnsafePointerAdd(), base, external, |
+ current_effect_, current_control_); |
+} |
+ |
+Node* GraphAssembler::ToNumber(Node* value) { |
+ return current_effect_ = graph()->NewNode( |
+ ToNumberOperator(), jsgraph()->ToNumberBuiltinConstant(), value, |
+ jsgraph()->NoContextConstant(), current_effect_); |
+} |
+ |
+Node* GraphAssembler::DeoptimizeIf(DeoptimizeReason reason, Node* condition, |
+ Node* frame_state) { |
+ return current_control_ = current_effect_ = |
+ graph()->NewNode(common()->DeoptimizeIf(reason), condition, |
+ frame_state, current_effect_, current_control_); |
+} |
+ |
+Node* GraphAssembler::DeoptimizeUnless(DeoptimizeReason reason, Node* condition, |
+ Node* frame_state) { |
+ return current_control_ = current_effect_ = |
+ graph()->NewNode(common()->DeoptimizeUnless(reason), condition, |
+ frame_state, current_effect_, current_control_); |
+} |
+ |
+void GraphAssembler::Branch(Node* condition, |
+ GraphAssemblerStaticLabel<1>* if_true, |
+ GraphAssemblerStaticLabel<1>* if_false) { |
+ DCHECK_NOT_NULL(current_control_); |
+ |
+ BranchHint hint = BranchHint::kNone; |
+ if (if_true->IsDeferred() != if_false->IsDeferred()) { |
+ hint = if_false->IsDeferred() ? BranchHint::kTrue : BranchHint::kFalse; |
+ } |
+ |
+ Node* branch = |
+ graph()->NewNode(common()->Branch(hint), condition, current_control_); |
+ |
+ current_control_ = graph()->NewNode(common()->IfTrue(), branch); |
+ MergeState(if_true); |
+ |
+ current_control_ = graph()->NewNode(common()->IfFalse(), branch); |
+ MergeState(if_false); |
+ |
+ current_control_ = nullptr; |
+ current_effect_ = nullptr; |
+} |
+ |
+// Extractors (should be only used when destructing the assembler. |
+Node* GraphAssembler::ExtractCurrentControl() { |
+ Node* result = current_control_; |
+ current_control_ = nullptr; |
+ return result; |
+} |
+ |
+Node* GraphAssembler::ExtractCurrentEffect() { |
+ Node* result = current_effect_; |
+ current_effect_ = nullptr; |
+ return result; |
+} |
+ |
+void GraphAssembler::Reset(Node* effect, Node* control) { |
+ current_effect_ = effect; |
+ current_control_ = control; |
+} |
+ |
+Operator const* GraphAssembler::ToNumberOperator() { |
+ if (!to_number_operator_.is_set()) { |
+ Callable callable = CodeFactory::ToNumber(jsgraph()->isolate()); |
+ CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
+ CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
+ jsgraph()->isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
+ Operator::kEliminatable); |
+ to_number_operator_.set(common()->Call(desc)); |
+ } |
+ return to_number_operator_.get(); |
+} |
+ |
+Node* GraphAssemblerLabel::PhiAt(size_t index) { |
+ DCHECK(IsBound()); |
+ return GetBindingsPtrFor(index)[0]; |
+} |
+ |
+GraphAssemblerLabel::GraphAssemblerLabel(GraphAssemblerLabelType is_deferred, |
+ size_t merge_count, size_t var_count, |
+ MachineRepresentation* representations, |
+ Zone* zone) |
+ : is_deferred_(is_deferred == GraphAssemblerLabelType::kDeferred), |
+ max_merge_count_(merge_count), |
+ var_count_(var_count) { |
+ effects_ = zone->NewArray<Node*>(MaxMergeCount() + 1); |
+ for (size_t i = 0; i < MaxMergeCount() + 1; i++) { |
+ effects_[i] = nullptr; |
+ } |
+ |
+ controls_ = zone->NewArray<Node*>(MaxMergeCount()); |
+ for (size_t i = 0; i < MaxMergeCount(); i++) { |
+ controls_[i] = nullptr; |
+ } |
+ |
+ size_t num_bindings = (MaxMergeCount() + 1) * PhiCount() + 1; |
+ bindings_ = zone->NewArray<Node*>(num_bindings); |
+ for (size_t i = 0; i < num_bindings; i++) { |
+ bindings_[i] = nullptr; |
+ } |
+ |
+ representations_ = zone->NewArray<MachineRepresentation>(PhiCount() + 1); |
+ for (size_t i = 0; i < PhiCount(); i++) { |
+ representations_[i] = representations[i]; |
+ } |
+} |
+ |
+GraphAssemblerLabel::~GraphAssemblerLabel() { |
+ DCHECK(IsBound() || MergedCount() == 0); |
+} |
+ |
+Node** GraphAssemblerLabel::GetBindingsPtrFor(size_t phi_index) { |
+ DCHECK_LT(phi_index, PhiCount()); |
+ return &bindings_[phi_index * (MaxMergeCount() + 1)]; |
+} |
+ |
+void GraphAssemblerLabel::SetBinding(size_t phi_index, size_t merge_index, |
+ Node* binding) { |
+ DCHECK_LT(phi_index, PhiCount()); |
+ DCHECK_LT(merge_index, MaxMergeCount()); |
+ bindings_[phi_index * (MaxMergeCount() + 1) + merge_index] = binding; |
+} |
+ |
+MachineRepresentation GraphAssemblerLabel::GetRepresentationFor( |
+ size_t phi_index) { |
+ DCHECK_LT(phi_index, PhiCount()); |
+ return representations_[phi_index]; |
+} |
+ |
+Node** GraphAssemblerLabel::GetControlsPtr() { return controls_; } |
+ |
+Node** GraphAssemblerLabel::GetEffectsPtr() { return effects_; } |
+ |
+} // namespace compiler |
+} // namespace internal |
+} // namespace v8 |