Chromium Code Reviews| Index: src/compiler/change-lowering.cc |
| diff --git a/src/compiler/change-lowering.cc b/src/compiler/change-lowering.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3f8e45b9e71d70b63cde34c37b986999486ab000 |
| --- /dev/null |
| +++ b/src/compiler/change-lowering.cc |
| @@ -0,0 +1,260 @@ |
| +// Copyright 2014 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/change-lowering.h" |
| + |
| +#include "src/compiler/common-node-cache.h" |
| +#include "src/compiler/graph.h" |
| + |
| +namespace v8 { |
| +namespace internal { |
| +namespace compiler { |
| + |
| +ChangeLoweringBase::ChangeLoweringBase(Graph* graph, Linkage* linkage, |
| + CommonNodeCache* cache) |
| + : graph_(graph), |
| + isolate_(graph->zone()->isolate()), |
| + linkage_(linkage), |
| + cache_(cache), |
| + common_(graph->zone()), |
| + machine_(graph->zone()) {} |
| + |
| + |
| +ChangeLoweringBase::~ChangeLoweringBase() {} |
| + |
| + |
| +Node* ChangeLoweringBase::ExternalConstant(ExternalReference reference) { |
|
titzer
2014/08/13 08:59:47
This is a big duplication of code. Why didn't you
|
| + Node** loc = cache()->FindExternalConstant(reference); |
| + if (*loc == NULL) { |
| + *loc = graph()->NewNode(common()->ExternalConstant(reference)); |
| + } |
| + return *loc; |
| +} |
| + |
| + |
| +Node* ChangeLoweringBase::HeapConstant(PrintableUnique<HeapObject> value) { |
| + // TODO(bmeurer): Use common node cache. |
| + return graph()->NewNode(common()->HeapConstant(value)); |
| +} |
| + |
| + |
| +Node* ChangeLoweringBase::ImmovableHeapConstant(Handle<HeapObject> value) { |
| + return HeapConstant( |
| + PrintableUnique<HeapObject>::CreateImmovable(graph()->zone(), value)); |
| +} |
| + |
| + |
| +Node* ChangeLoweringBase::Int32Constant(int32_t value) { |
| + Node** loc = cache()->FindInt32Constant(value); |
| + if (*loc == NULL) { |
| + *loc = graph()->NewNode(common()->Int32Constant(value)); |
| + } |
| + return *loc; |
| +} |
| + |
| + |
| +Node* ChangeLoweringBase::NumberConstant(double value) { |
| + Node** loc = cache()->FindNumberConstant(value); |
| + if (*loc == NULL) { |
| + *loc = graph()->NewNode(common()->NumberConstant(value)); |
| + } |
| + return *loc; |
| +} |
| + |
| + |
| +Node* ChangeLoweringBase::CEntryStubConstant() { |
| + if (!c_entry_stub_constant_.is_set()) { |
| + c_entry_stub_constant_.set( |
| + ImmovableHeapConstant(CEntryStub(isolate(), 1).GetCode())); |
| + } |
| + return c_entry_stub_constant_.get(); |
| +} |
| + |
| + |
| +Node* ChangeLoweringBase::TrueConstant() { |
| + if (!true_constant_.is_set()) { |
| + true_constant_.set( |
| + ImmovableHeapConstant(isolate()->factory()->true_value())); |
| + } |
| + return true_constant_.get(); |
| +} |
| + |
| + |
| +Node* ChangeLoweringBase::FalseConstant() { |
| + if (!false_constant_.is_set()) { |
| + false_constant_.set( |
| + ImmovableHeapConstant(isolate()->factory()->false_value())); |
| + } |
| + return false_constant_.get(); |
| +} |
| + |
| + |
| +Reduction ChangeLoweringBase::ChangeBitToBool(Node* val, Node* control) { |
| + Node* branch = graph()->NewNode(common()->Branch(), val, control); |
| + |
| + Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
| + Node* true_value = TrueConstant(); |
| + |
| + Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
| + Node* false_value = FalseConstant(); |
| + |
| + Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
| + Node* phi = |
| + graph()->NewNode(common()->Phi(2), true_value, false_value, merge); |
| + |
| + return Replace(phi); |
| +} |
| + |
| + |
| +template <size_t kPointerSize> |
| +ChangeLowering<kPointerSize>::ChangeLowering(Graph* graph, Linkage* linkage) |
| + : ChangeLoweringBase(graph, linkage, |
| + new (graph->zone()) CommonNodeCache(graph->zone())) {} |
| + |
| + |
| +template <size_t kPointerSize> |
| +Reduction ChangeLowering<kPointerSize>::Reduce(Node* node) { |
| + Node* control = graph()->start(); |
| + Node* effect = control; |
| + switch (node->opcode()) { |
| + case IrOpcode::kChangeBitToBool: |
| + return ChangeBitToBool(node->InputAt(0), control); |
| + case IrOpcode::kChangeBoolToBit: |
| + return ChangeBoolToBit(node->InputAt(0)); |
| + case IrOpcode::kChangeInt32ToTagged: |
| + return ChangeInt32ToTagged(node->InputAt(0), effect, control); |
| + case IrOpcode::kChangeTaggedToFloat64: |
| + return ChangeTaggedToFloat64(node->InputAt(0), effect, control); |
| + default: |
| + return NoChange(); |
| + } |
| + UNREACHABLE(); |
| + return NoChange(); |
| +} |
| + |
| + |
| +template <> |
| +Reduction ChangeLowering<4>::ChangeBoolToBit(Node* val) { |
|
titzer
2014/08/13 08:59:47
This templatization of the changes is unnecessary
Benedikt Meurer
2014/08/13 09:03:41
Before it was simple and not unit testable because
titzer
2014/08/13 09:11:12
You could, e.g. make the pointer size a field on t
Benedikt Meurer
2014/08/13 09:14:12
That's another option, sure. But I decided to do i
|
| + return Replace( |
| + graph()->NewNode(machine()->Word32Equal(), val, TrueConstant())); |
| +} |
| + |
| + |
| +template <> |
| +Reduction ChangeLowering<8>::ChangeBoolToBit(Node* val) { |
| + return Replace( |
| + graph()->NewNode(machine()->Word64Equal(), val, TrueConstant())); |
| +} |
| + |
| + |
| +template <> |
| +Reduction ChangeLowering<4>::ChangeInt32ToTagged(Node* val, Node* effect, |
| + Node* control) { |
| + Node* context = NumberConstant(0); |
| + |
| + Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), val, val); |
| + Node* ovf = graph()->NewNode(common()->Projection(1), add); |
| + |
| + Node* branch = graph()->NewNode(common()->Branch(), ovf, control); |
| + |
| + Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
| + Node* number = graph()->NewNode(machine()->ChangeInt32ToFloat64(), val); |
| + |
| + // TODO(bmeurer): Inline allocation if possible. |
| + const Runtime::Function* fn = |
| + Runtime::FunctionForId(Runtime::kAllocateHeapNumber); |
| + DCHECK_EQ(0, fn->nargs); |
| + CallDescriptor* desc = linkage()->GetRuntimeCallDescriptor( |
| + fn->function_id, 0, Operator::kNoProperties); |
| + Node* heap_number = |
| + graph()->NewNode(common()->Call(desc), CEntryStubConstant(), |
| + ExternalConstant(ExternalReference(fn, isolate())), |
| + Int32Constant(0), context, effect, if_true); |
| + |
| + Node* store = graph()->NewNode( |
| + machine()->Store(kMachineFloat64, kNoWriteBarrier), heap_number, |
| + Int32Constant(HeapNumber::kValueOffset - kHeapObjectTag), number, effect, |
| + heap_number); |
| + |
| + Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
| + Node* smi = graph()->NewNode(common()->Projection(0), add); |
| + |
| + Node* merge = graph()->NewNode(common()->Merge(2), store, if_false); |
| + Node* phi = graph()->NewNode(common()->Phi(2), heap_number, smi, merge); |
| + |
| + return Replace(phi); |
| +} |
| + |
| + |
| +template <> |
| +Reduction ChangeLowering<8>::ChangeInt32ToTagged(Node* val, Node* effect, |
| + Node* control) { |
| + return Replace(graph()->NewNode( |
| + machine()->Word64Shl(), val, |
| + Int32Constant(SmiTagging<8>::kSmiShiftSize + kSmiTagSize))); |
| +} |
| + |
| + |
| +template <> |
| +Reduction ChangeLowering<4>::ChangeTaggedToFloat64(Node* val, Node* effect, |
|
titzer
2014/08/13 08:59:47
ChangeLowering<4> and ChangeLowering<8> of this me
Benedikt Meurer
2014/08/13 09:03:41
Yap, will be refactored once everythings in place.
|
| + Node* control) { |
| + Node* branch = graph()->NewNode( |
| + common()->Branch(), |
| + graph()->NewNode(machine()->Word32And(), val, Int32Constant(kSmiTagMask)), |
| + control); |
| + |
| + Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
| + Node* load = graph()->NewNode( |
| + machine()->Load(kMachineFloat64), val, |
| + Int32Constant(HeapNumber::kValueOffset - kHeapObjectTag), if_true); |
| + |
| + Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
| + Node* number = graph()->NewNode( |
| + machine()->ChangeInt32ToFloat64(), |
| + graph()->NewNode( |
| + machine()->Word32Sar(), val, |
| + Int32Constant(SmiTagging<4>::kSmiShiftSize + kSmiTagSize))); |
| + |
| + Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
| + Node* phi = graph()->NewNode(common()->Phi(2), load, number, merge); |
| + |
| + return Replace(phi); |
| +} |
| + |
| + |
| +template <> |
| +Reduction ChangeLowering<8>::ChangeTaggedToFloat64(Node* val, Node* effect, |
| + Node* control) { |
| + Node* branch = graph()->NewNode( |
| + common()->Branch(), |
| + graph()->NewNode(machine()->Word64And(), val, Int32Constant(kSmiTagMask)), |
| + control); |
| + |
| + Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
| + Node* load = graph()->NewNode( |
| + machine()->Load(kMachineFloat64), val, |
| + Int32Constant(HeapNumber::kValueOffset - kHeapObjectTag), if_true); |
| + |
| + Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
| + Node* number = graph()->NewNode( |
| + machine()->ChangeInt32ToFloat64(), |
| + graph()->NewNode( |
| + machine()->ConvertInt64ToInt32(), |
| + graph()->NewNode( |
| + machine()->Word64Sar(), val, |
| + Int32Constant(SmiTagging<8>::kSmiShiftSize + kSmiTagSize)))); |
| + |
| + Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
| + Node* phi = graph()->NewNode(common()->Phi(2), load, number, merge); |
| + |
| + return Replace(phi); |
| +} |
| + |
| + |
| +template class ChangeLowering<4>; |
| +template class ChangeLowering<8>; |
| + |
| +} // namespace compiler |
| +} // namespace internal |
| +} // namespace v8 |