V8 Project
change-lowering.cc
Go to the documentation of this file.
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
7 
9 
10 namespace v8 {
11 namespace internal {
12 namespace compiler {
13 
14 ChangeLowering::~ChangeLowering() {}
15 
16 
17 Reduction ChangeLowering::Reduce(Node* node) {
18  Node* control = graph()->start();
19  switch (node->opcode()) {
20  case IrOpcode::kChangeBitToBool:
21  return ChangeBitToBool(node->InputAt(0), control);
22  case IrOpcode::kChangeBoolToBit:
23  return ChangeBoolToBit(node->InputAt(0));
24  case IrOpcode::kChangeFloat64ToTagged:
25  return ChangeFloat64ToTagged(node->InputAt(0), control);
26  case IrOpcode::kChangeInt32ToTagged:
27  return ChangeInt32ToTagged(node->InputAt(0), control);
28  case IrOpcode::kChangeTaggedToFloat64:
29  return ChangeTaggedToFloat64(node->InputAt(0), control);
30  case IrOpcode::kChangeTaggedToInt32:
31  return ChangeTaggedToUI32(node->InputAt(0), control, kSigned);
32  case IrOpcode::kChangeTaggedToUint32:
33  return ChangeTaggedToUI32(node->InputAt(0), control, kUnsigned);
34  case IrOpcode::kChangeUint32ToTagged:
35  return ChangeUint32ToTagged(node->InputAt(0), control);
36  default:
37  return NoChange();
38  }
39  UNREACHABLE();
40  return NoChange();
41 }
42 
43 
44 Node* ChangeLowering::HeapNumberValueIndexConstant() {
46  const int heap_number_value_offset =
47  ((HeapNumber::kValueOffset / kPointerSize) * (machine()->Is64() ? 8 : 4));
48  return jsgraph()->Int32Constant(heap_number_value_offset - kHeapObjectTag);
49 }
50 
51 
52 Node* ChangeLowering::SmiMaxValueConstant() {
53  const int smi_value_size = machine()->Is32() ? SmiTagging<4>::SmiValueSize()
54  : SmiTagging<8>::SmiValueSize();
55  return jsgraph()->Int32Constant(
56  -(static_cast<int>(0xffffffffu << (smi_value_size - 1)) + 1));
57 }
58 
59 
60 Node* ChangeLowering::SmiShiftBitsConstant() {
61  const int smi_shift_size = machine()->Is32() ? SmiTagging<4>::SmiShiftSize()
62  : SmiTagging<8>::SmiShiftSize();
63  return jsgraph()->Int32Constant(smi_shift_size + kSmiTagSize);
64 }
65 
66 
67 Node* ChangeLowering::AllocateHeapNumberWithValue(Node* value, Node* control) {
68  // The AllocateHeapNumber() runtime function does not use the context, so we
69  // can safely pass in Smi zero here.
70  Node* context = jsgraph()->ZeroConstant();
71  Node* effect = graph()->NewNode(common()->ValueEffect(1), value);
72  const Runtime::Function* function =
73  Runtime::FunctionForId(Runtime::kAllocateHeapNumber);
74  DCHECK_EQ(0, function->nargs);
75  CallDescriptor* desc = linkage()->GetRuntimeCallDescriptor(
76  function->function_id, 0, Operator::kNoProperties);
77  Node* heap_number = graph()->NewNode(
78  common()->Call(desc), jsgraph()->CEntryStubConstant(),
79  jsgraph()->ExternalConstant(ExternalReference(function, isolate())),
80  jsgraph()->Int32Constant(function->nargs), context, effect, control);
81  Node* store = graph()->NewNode(
82  machine()->Store(StoreRepresentation(kMachFloat64, kNoWriteBarrier)),
83  heap_number, HeapNumberValueIndexConstant(), value, heap_number, control);
84  return graph()->NewNode(common()->Finish(1), heap_number, store);
85 }
86 
87 
88 Node* ChangeLowering::ChangeSmiToInt32(Node* value) {
89  value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant());
90  if (machine()->Is64()) {
91  value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value);
92  }
93  return value;
94 }
95 
96 
97 Node* ChangeLowering::LoadHeapNumberValue(Node* value, Node* control) {
98  return graph()->NewNode(machine()->Load(kMachFloat64), value,
99  HeapNumberValueIndexConstant(),
100  graph()->NewNode(common()->ControlEffect(), control));
101 }
102 
103 
104 Reduction ChangeLowering::ChangeBitToBool(Node* val, Node* control) {
105  Node* branch = graph()->NewNode(common()->Branch(), val, control);
106 
107  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
108  Node* true_value = jsgraph()->TrueConstant();
109 
110  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
111  Node* false_value = jsgraph()->FalseConstant();
112 
113  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
114  Node* phi = graph()->NewNode(
115  common()->Phi(static_cast<MachineType>(kTypeBool | kRepTagged), 2),
116  true_value, false_value, merge);
117 
118  return Replace(phi);
119 }
120 
121 
122 Reduction ChangeLowering::ChangeBoolToBit(Node* val) {
123  return Replace(
124  graph()->NewNode(machine()->WordEqual(), val, jsgraph()->TrueConstant()));
125 }
126 
127 
128 Reduction ChangeLowering::ChangeFloat64ToTagged(Node* val, Node* control) {
129  return Replace(AllocateHeapNumberWithValue(val, control));
130 }
131 
132 
133 Reduction ChangeLowering::ChangeInt32ToTagged(Node* val, Node* control) {
134  if (machine()->Is64()) {
135  return Replace(
136  graph()->NewNode(machine()->Word64Shl(),
137  graph()->NewNode(machine()->ChangeInt32ToInt64(), val),
138  SmiShiftBitsConstant()));
139  }
140 
141  Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), val, val);
142  Node* ovf = graph()->NewNode(common()->Projection(1), add);
143 
144  Node* branch = graph()->NewNode(common()->Branch(), ovf, control);
145 
146  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
147  Node* heap_number = AllocateHeapNumberWithValue(
148  graph()->NewNode(machine()->ChangeInt32ToFloat64(), val), if_true);
149 
150  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
151  Node* smi = graph()->NewNode(common()->Projection(0), add);
152 
153  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
154  Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), heap_number,
155  smi, merge);
156 
157  return Replace(phi);
158 }
159 
160 
161 Reduction ChangeLowering::ChangeTaggedToUI32(Node* val, Node* control,
162  Signedness signedness) {
163  STATIC_ASSERT(kSmiTag == 0);
165 
166  Node* tag = graph()->NewNode(machine()->WordAnd(), val,
167  jsgraph()->Int32Constant(kSmiTagMask));
168  Node* branch = graph()->NewNode(common()->Branch(), tag, control);
169 
170  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
171  const Operator* op = (signedness == kSigned)
172  ? machine()->ChangeFloat64ToInt32()
173  : machine()->ChangeFloat64ToUint32();
174  Node* change = graph()->NewNode(op, LoadHeapNumberValue(val, if_true));
175 
176  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
177  Node* number = ChangeSmiToInt32(val);
178 
179  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
180  Node* phi = graph()->NewNode(
181  common()->Phi((signedness == kSigned) ? kMachInt32 : kMachUint32, 2),
182  change, number, merge);
183 
184  return Replace(phi);
185 }
186 
187 
188 Reduction ChangeLowering::ChangeTaggedToFloat64(Node* val, Node* control) {
189  STATIC_ASSERT(kSmiTag == 0);
191 
192  Node* tag = graph()->NewNode(machine()->WordAnd(), val,
193  jsgraph()->Int32Constant(kSmiTagMask));
194  Node* branch = graph()->NewNode(common()->Branch(), tag, control);
195 
196  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
197  Node* load = LoadHeapNumberValue(val, if_true);
198 
199  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
200  Node* number = graph()->NewNode(machine()->ChangeInt32ToFloat64(),
201  ChangeSmiToInt32(val));
202 
203  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
204  Node* phi =
205  graph()->NewNode(common()->Phi(kMachFloat64, 2), load, number, merge);
206 
207  return Replace(phi);
208 }
209 
210 
211 Reduction ChangeLowering::ChangeUint32ToTagged(Node* val, Node* control) {
212  STATIC_ASSERT(kSmiTag == 0);
214 
215  Node* cmp = graph()->NewNode(machine()->Uint32LessThanOrEqual(), val,
216  SmiMaxValueConstant());
217  Node* branch = graph()->NewNode(common()->Branch(), cmp, control);
218 
219  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
220  Node* smi = graph()->NewNode(
221  machine()->WordShl(),
222  machine()->Is64()
223  ? graph()->NewNode(machine()->ChangeUint32ToUint64(), val)
224  : val,
225  SmiShiftBitsConstant());
226 
227  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
228  Node* heap_number = AllocateHeapNumberWithValue(
229  graph()->NewNode(machine()->ChangeUint32ToFloat64(), val), if_false);
230 
231  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
232  Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), smi,
233  heap_number, merge);
234 
235  return Replace(phi);
236 }
237 
238 
239 Isolate* ChangeLowering::isolate() const { return jsgraph()->isolate(); }
240 
241 
242 Graph* ChangeLowering::graph() const { return jsgraph()->graph(); }
243 
244 
245 CommonOperatorBuilder* ChangeLowering::common() const {
246  return jsgraph()->common();
247 }
248 
249 
250 MachineOperatorBuilder* ChangeLowering::machine() const {
251  return jsgraph()->machine();
252 }
253 
254 } // namespace compiler
255 } // namespace internal
256 } // namespace v8
static const int kValueOffset
Definition: objects.h:1506
static const Function * FunctionForId(FunctionId id)
Definition: runtime.cc:9312
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
STATIC_ASSERT(DoubleRegister::kMaxNumAllocatableRegisters >=Register::kMaxNumAllocatableRegisters)
const int kPointerSize
Definition: globals.h:129
const int kSmiTagSize
Definition: v8.h:5743
const int kHeapObjectTag
Definition: v8.h:5737
const intptr_t kSmiTagMask
Definition: v8.h:5744
const int kSmiTag
Definition: v8.h:5742
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
static int SmiValueSize()
Definition: v8.h:5760
static int SmiShiftSize()
Definition: v8.h:5759