blob: a76d3e2013fd791c04f6b0834df5611ff4cc6344 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
5#include "src/compiler/simplified-lowering.h"
6
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007#include <limits>
8
Ben Murdochc5610432016-08-08 18:44:38 +01009#include "src/address-map.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/base/bits.h"
11#include "src/code-factory.h"
Ben Murdochc5610432016-08-08 18:44:38 +010012#include "src/compiler/access-builder.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "src/compiler/common-operator.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040014#include "src/compiler/diamond.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015#include "src/compiler/linkage.h"
16#include "src/compiler/node-matchers.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017#include "src/compiler/node-properties.h"
18#include "src/compiler/operator-properties.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019#include "src/compiler/representation-change.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020#include "src/compiler/simplified-operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021#include "src/compiler/source-position.h"
Ben Murdochc5610432016-08-08 18:44:38 +010022#include "src/conversions-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023#include "src/objects.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024#include "src/type-cache.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025
26namespace v8 {
27namespace internal {
28namespace compiler {
29
30// Macro for outputting trace information from representation inference.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000031#define TRACE(...) \
32 do { \
33 if (FLAG_trace_representation) PrintF(__VA_ARGS__); \
34 } while (false)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035
36// Representation selection and lowering of {Simplified} operators to machine
37// operators are interwined. We use a fixpoint calculation to compute both the
38// output representation and the best possible lowering for {Simplified} nodes.
39// Representation change insertion ensures that all values are in the correct
40// machine representation after this phase, as dictated by the machine
41// operators themselves.
42enum Phase {
43 // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information
44 // backwards from uses to definitions, around cycles in phis, according
45 // to local rules for each operator.
46 // During this phase, the usage information for a node determines the best
47 // possible lowering for each operator so far, and that in turn determines
48 // the output representation.
49 // Therefore, to be correct, this phase must iterate to a fixpoint before
50 // the next phase can begin.
51 PROPAGATE,
52
53 // 2.) LOWER: perform lowering for all {Simplified} nodes by replacing some
54 // operators for some nodes, expanding some nodes to multiple nodes, or
55 // removing some (redundant) nodes.
56 // During this phase, use the {RepresentationChanger} to insert
57 // representation changes between uses that demand a particular
58 // representation and nodes that produce a different representation.
59 LOWER
60};
61
62
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063namespace {
64
65// The {UseInfo} class is used to describe a use of an input of a node.
66//
67// This information is used in two different ways, based on the phase:
68//
69// 1. During propagation, the use info is used to inform the input node
70// about what part of the input is used (we call this truncation) and what
71// is the preferred representation.
72//
73// 2. During lowering, the use info is used to properly convert the input
74// to the preferred representation. The preferred representation might be
75// insufficient to do the conversion (e.g. word32->float64 conv), so we also
76// need the signedness information to produce the correct value.
77class UseInfo {
78 public:
79 UseInfo(MachineRepresentation preferred, Truncation truncation)
80 : preferred_(preferred), truncation_(truncation) {}
81 static UseInfo TruncatingWord32() {
82 return UseInfo(MachineRepresentation::kWord32, Truncation::Word32());
83 }
84 static UseInfo TruncatingWord64() {
85 return UseInfo(MachineRepresentation::kWord64, Truncation::Word64());
86 }
87 static UseInfo Bool() {
88 return UseInfo(MachineRepresentation::kBit, Truncation::Bool());
89 }
Ben Murdochc5610432016-08-08 18:44:38 +010090 static UseInfo TruncatingFloat32() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000091 return UseInfo(MachineRepresentation::kFloat32, Truncation::Float32());
92 }
Ben Murdochc5610432016-08-08 18:44:38 +010093 static UseInfo TruncatingFloat64() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000094 return UseInfo(MachineRepresentation::kFloat64, Truncation::Float64());
95 }
96 static UseInfo PointerInt() {
97 return kPointerSize == 4 ? TruncatingWord32() : TruncatingWord64();
98 }
99 static UseInfo AnyTagged() {
100 return UseInfo(MachineRepresentation::kTagged, Truncation::Any());
101 }
102
103 // Undetermined representation.
104 static UseInfo Any() {
105 return UseInfo(MachineRepresentation::kNone, Truncation::Any());
106 }
107 static UseInfo None() {
108 return UseInfo(MachineRepresentation::kNone, Truncation::None());
109 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000110 static UseInfo AnyTruncatingToBool() {
111 return UseInfo(MachineRepresentation::kNone, Truncation::Bool());
112 }
113
114 MachineRepresentation preferred() const { return preferred_; }
115 Truncation truncation() const { return truncation_; }
116
117 private:
118 MachineRepresentation preferred_;
119 Truncation truncation_;
120};
121
122
123UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) {
124 switch (rep) {
125 case MachineRepresentation::kTagged:
126 return UseInfo::AnyTagged();
127 case MachineRepresentation::kFloat64:
Ben Murdochc5610432016-08-08 18:44:38 +0100128 return UseInfo::TruncatingFloat64();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 case MachineRepresentation::kFloat32:
Ben Murdochc5610432016-08-08 18:44:38 +0100130 return UseInfo::TruncatingFloat32();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000131 case MachineRepresentation::kWord64:
Ben Murdochc5610432016-08-08 18:44:38 +0100132 return UseInfo::TruncatingWord64();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133 case MachineRepresentation::kWord8:
134 case MachineRepresentation::kWord16:
135 case MachineRepresentation::kWord32:
Ben Murdochc5610432016-08-08 18:44:38 +0100136 return UseInfo::TruncatingWord32();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000137 case MachineRepresentation::kBit:
138 return UseInfo::Bool();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100139 case MachineRepresentation::kSimd128: // Fall through.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140 case MachineRepresentation::kNone:
141 break;
142 }
143 UNREACHABLE();
144 return UseInfo::None();
145}
146
147
148UseInfo UseInfoForBasePointer(const FieldAccess& access) {
149 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
150}
151
152
153UseInfo UseInfoForBasePointer(const ElementAccess& access) {
154 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
155}
156
157
158#ifdef DEBUG
159// Helpers for monotonicity checking.
160bool MachineRepresentationIsSubtype(MachineRepresentation r1,
161 MachineRepresentation r2) {
162 switch (r1) {
163 case MachineRepresentation::kNone:
164 return true;
165 case MachineRepresentation::kBit:
166 return r2 == MachineRepresentation::kBit ||
167 r2 == MachineRepresentation::kTagged;
168 case MachineRepresentation::kWord8:
169 return r2 == MachineRepresentation::kWord8 ||
170 r2 == MachineRepresentation::kWord16 ||
171 r2 == MachineRepresentation::kWord32 ||
172 r2 == MachineRepresentation::kWord64 ||
173 r2 == MachineRepresentation::kFloat32 ||
174 r2 == MachineRepresentation::kFloat64 ||
175 r2 == MachineRepresentation::kTagged;
176 case MachineRepresentation::kWord16:
177 return r2 == MachineRepresentation::kWord16 ||
178 r2 == MachineRepresentation::kWord32 ||
179 r2 == MachineRepresentation::kWord64 ||
180 r2 == MachineRepresentation::kFloat32 ||
181 r2 == MachineRepresentation::kFloat64 ||
182 r2 == MachineRepresentation::kTagged;
183 case MachineRepresentation::kWord32:
184 return r2 == MachineRepresentation::kWord32 ||
185 r2 == MachineRepresentation::kWord64 ||
186 r2 == MachineRepresentation::kFloat64 ||
187 r2 == MachineRepresentation::kTagged;
188 case MachineRepresentation::kWord64:
189 return r2 == MachineRepresentation::kWord64;
190 case MachineRepresentation::kFloat32:
191 return r2 == MachineRepresentation::kFloat32 ||
192 r2 == MachineRepresentation::kFloat64 ||
193 r2 == MachineRepresentation::kTagged;
194 case MachineRepresentation::kFloat64:
195 return r2 == MachineRepresentation::kFloat64 ||
196 r2 == MachineRepresentation::kTagged;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100197 case MachineRepresentation::kSimd128:
198 return r2 == MachineRepresentation::kSimd128 ||
199 r2 == MachineRepresentation::kTagged;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 case MachineRepresentation::kTagged:
201 return r2 == MachineRepresentation::kTagged;
202 }
203 UNREACHABLE();
204 return false;
205}
206
207
208class InputUseInfos {
209 public:
210 explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {}
211
212 void SetAndCheckInput(Node* node, int index, UseInfo use_info) {
213 if (input_use_infos_.empty()) {
214 input_use_infos_.resize(node->InputCount(), UseInfo::None());
215 }
216 // Check that the new use informatin is a super-type of the old
217 // one.
218 CHECK(IsUseLessGeneral(input_use_infos_[index], use_info));
219 input_use_infos_[index] = use_info;
220 }
221
222 private:
223 ZoneVector<UseInfo> input_use_infos_;
224
225 static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) {
226 return MachineRepresentationIsSubtype(use1.preferred(), use2.preferred()) &&
227 use1.truncation().IsLessGeneralThan(use2.truncation());
228 }
229};
230
231#endif // DEBUG
232
233} // namespace
234
235
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236class RepresentationSelector {
237 public:
238 // Information for each node tracked during the fixpoint.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239 class NodeInfo {
240 public:
241 // Adds new use to the node. Returns true if something has changed
242 // and the node has to be requeued.
243 bool AddUse(UseInfo info) {
244 Truncation old_truncation = truncation_;
245 truncation_ = Truncation::Generalize(truncation_, info.truncation());
246 return truncation_ != old_truncation;
247 }
248
249 void set_queued(bool value) { queued_ = value; }
250 bool queued() const { return queued_; }
251 void set_visited() { visited_ = true; }
252 bool visited() const { return visited_; }
253 Truncation truncation() const { return truncation_; }
Ben Murdochda12d292016-06-02 14:46:10 +0100254 void set_output(MachineRepresentation output) { representation_ = output; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000255
Ben Murdochda12d292016-06-02 14:46:10 +0100256 MachineRepresentation representation() const { return representation_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000257
258 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100259 bool queued_ = false; // Bookkeeping for the traversal.
260 bool visited_ = false; // Bookkeeping for the traversal.
261 MachineRepresentation representation_ =
262 MachineRepresentation::kNone; // Output representation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000263 Truncation truncation_ = Truncation::None(); // Information about uses.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000264 };
265
266 RepresentationSelector(JSGraph* jsgraph, Zone* zone,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000267 RepresentationChanger* changer,
268 SourcePositionTable* source_positions)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269 : jsgraph_(jsgraph),
270 count_(jsgraph->graph()->NodeCount()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000271 info_(count_, zone),
272#ifdef DEBUG
273 node_input_use_infos_(count_, InputUseInfos(zone), zone),
274#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275 nodes_(zone),
276 replacements_(zone),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000277 phase_(PROPAGATE),
278 changer_(changer),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 queue_(zone),
280 source_positions_(source_positions),
281 type_cache_(TypeCache::Get()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000282 }
283
284 void Run(SimplifiedLowering* lowering) {
285 // Run propagation phase to a fixpoint.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000286 TRACE("--{Propagation phase}--\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000287 phase_ = PROPAGATE;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000288 EnqueueInitial(jsgraph_->graph()->end());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000289 // Process nodes from the queue until it is empty.
290 while (!queue_.empty()) {
291 Node* node = queue_.front();
292 NodeInfo* info = GetInfo(node);
293 queue_.pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000294 info->set_queued(false);
295 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
296 VisitNode(node, info->truncation(), nullptr);
297 TRACE(" ==> output ");
298 PrintOutputInfo(info);
299 TRACE("\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000300 }
301
302 // Run lowering and change insertion phase.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000303 TRACE("--{Simplified lowering phase}--\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000304 phase_ = LOWER;
305 // Process nodes from the collected {nodes_} vector.
306 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) {
307 Node* node = *i;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000308 NodeInfo* info = GetInfo(node);
309 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000310 // Reuse {VisitNode()} so the representation rules are in one place.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000311 SourcePositionTable::Scope scope(
312 source_positions_, source_positions_->GetSourcePosition(node));
313 VisitNode(node, info->truncation(), lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000314 }
315
316 // Perform the final replacements.
317 for (NodeVector::iterator i = replacements_.begin();
318 i != replacements_.end(); ++i) {
319 Node* node = *i;
320 Node* replacement = *(++i);
321 node->ReplaceUses(replacement);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000322 // We also need to replace the node in the rest of the vector.
323 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) {
324 ++j;
325 if (*j == node) *j = replacement;
326 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000327 }
328 }
329
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000330 void EnqueueInitial(Node* node) {
331 NodeInfo* info = GetInfo(node);
332 info->set_visited();
333 info->set_queued(true);
334 nodes_.push_back(node);
335 queue_.push(node);
336 }
337
338 // Enqueue {use_node}'s {index} input if the {use} contains new information
339 // for that input node. Add the input to {nodes_} if this is the first time
340 // it's been visited.
341 void EnqueueInput(Node* use_node, int index,
342 UseInfo use_info = UseInfo::None()) {
343 Node* node = use_node->InputAt(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000344 if (phase_ != PROPAGATE) return;
345 NodeInfo* info = GetInfo(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000346#ifdef DEBUG
347 // Check monotonicity of input requirements.
348 node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index,
349 use_info);
350#endif // DEBUG
351 if (!info->visited()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000352 // First visit of this node.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000353 info->set_visited();
354 info->set_queued(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000355 nodes_.push_back(node);
356 queue_.push(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000357 TRACE(" initial: ");
358 info->AddUse(use_info);
359 PrintTruncation(info->truncation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000360 return;
361 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000362 TRACE(" queue?: ");
363 PrintTruncation(info->truncation());
364 if (info->AddUse(use_info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000365 // New usage information for the node is available.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366 if (!info->queued()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000367 queue_.push(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000368 info->set_queued(true);
369 TRACE(" added: ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000370 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000371 TRACE(" inqueue: ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000372 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000373 PrintTruncation(info->truncation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000374 }
375 }
376
377 bool lower() { return phase_ == LOWER; }
378
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000379 void EnqueueUses(Node* node) {
380 for (Edge edge : node->use_edges()) {
381 if (NodeProperties::IsValueEdge(edge)) {
382 Node* const user = edge.from();
383 if (user->id() < count_) {
384 // New type information for the node is available.
385 NodeInfo* info = GetInfo(user);
386 // Enqueue the node only if we are sure it is reachable from
387 // the end and it has not been queued yet.
388 if (info->visited() && !info->queued()) {
389 queue_.push(user);
390 info->set_queued(true);
391 }
392 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400393 }
394 }
395 }
396
Ben Murdochda12d292016-06-02 14:46:10 +0100397 void SetOutput(Node* node, MachineRepresentation representation) {
398 NodeInfo* info = GetInfo(node);
399 DCHECK(
400 MachineRepresentationIsSubtype(info->representation(), representation));
401 info->set_output(representation);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000402 }
403
Ben Murdochda12d292016-06-02 14:46:10 +0100404 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000405
406 bool BothInputsAreSigned32(Node* node) {
407 DCHECK_EQ(2, node->InputCount());
Ben Murdochda12d292016-06-02 14:46:10 +0100408 return GetUpperBound(node->InputAt(0))->Is(Type::Signed32()) &&
409 GetUpperBound(node->InputAt(1))->Is(Type::Signed32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000410 }
411
412 bool BothInputsAreUnsigned32(Node* node) {
413 DCHECK_EQ(2, node->InputCount());
Ben Murdochda12d292016-06-02 14:46:10 +0100414 return GetUpperBound(node->InputAt(0))->Is(Type::Unsigned32()) &&
415 GetUpperBound(node->InputAt(1))->Is(Type::Unsigned32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416 }
417
418 bool BothInputsAre(Node* node, Type* type) {
419 DCHECK_EQ(2, node->InputCount());
Ben Murdochda12d292016-06-02 14:46:10 +0100420 return GetUpperBound(node->InputAt(0))->Is(type) &&
421 GetUpperBound(node->InputAt(1))->Is(type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000422 }
423
424 void ConvertInput(Node* node, int index, UseInfo use) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425 Node* input = node->InputAt(index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000426 // In the change phase, insert a change before the use if necessary.
427 if (use.preferred() == MachineRepresentation::kNone)
428 return; // No input requirement on the use.
429 NodeInfo* input_info = GetInfo(input);
430 MachineRepresentation input_rep = input_info->representation();
431 if (input_rep != use.preferred()) {
432 // Output representation doesn't match usage.
433 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(),
434 index, input->id(), input->op()->mnemonic());
435 TRACE(" from ");
436 PrintOutputInfo(input_info);
437 TRACE(" to ");
438 PrintUseInfo(use);
439 TRACE("\n");
440 Node* n = changer_->GetRepresentationFor(
Ben Murdochda12d292016-06-02 14:46:10 +0100441 input, input_info->representation(), GetUpperBound(input),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000442 use.preferred(), use.truncation());
443 node->ReplaceInput(index, n);
444 }
445 }
446
447 void ProcessInput(Node* node, int index, UseInfo use) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000448 if (phase_ == PROPAGATE) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000449 EnqueueInput(node, index, use);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000450 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000451 ConvertInput(node, index, use);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000452 }
453 }
454
455 void ProcessRemainingInputs(Node* node, int index) {
456 DCHECK_GE(index, NodeProperties::PastValueIndex(node));
457 DCHECK_GE(index, NodeProperties::PastContextIndex(node));
458 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node));
459 i < NodeProperties::PastEffectIndex(node); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460 EnqueueInput(node, i); // Effect inputs: just visit
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000461 }
462 for (int i = std::max(index, NodeProperties::FirstControlIndex(node));
463 i < NodeProperties::PastControlIndex(node); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000464 EnqueueInput(node, i); // Control inputs: just visit
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000465 }
466 }
467
468 // The default, most general visitation case. For {node}, process all value,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000469 // context, frame state, effect, and control inputs, assuming that value
470 // inputs should have {kRepTagged} representation and can observe all output
471 // values {kTypeAny}.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000472 void VisitInputs(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000473 int tagged_count = node->op()->ValueInputCount() +
474 OperatorProperties::GetContextInputCount(node->op());
475 // Visit value and context inputs as tagged.
476 for (int i = 0; i < tagged_count; i++) {
477 ProcessInput(node, i, UseInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000478 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000479 // Only enqueue other inputs (framestates, effects, control).
480 for (int i = tagged_count; i < node->InputCount(); i++) {
481 EnqueueInput(node, i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000482 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000483 }
484
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000485 // Helper for binops of the R x L -> O variety.
486 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
Ben Murdochda12d292016-06-02 14:46:10 +0100487 MachineRepresentation output) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488 DCHECK_EQ(2, node->op()->ValueInputCount());
489 ProcessInput(node, 0, left_use);
490 ProcessInput(node, 1, right_use);
491 for (int i = 2; i < node->InputCount(); i++) {
492 EnqueueInput(node, i);
493 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494 SetOutput(node, output);
495 }
496
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497 // Helper for binops of the I x I -> O variety.
Ben Murdochda12d292016-06-02 14:46:10 +0100498 void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000499 VisitBinop(node, input_use, input_use, output);
500 }
501
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000502 // Helper for unops of the I -> O variety.
Ben Murdochda12d292016-06-02 14:46:10 +0100503 void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000504 DCHECK_EQ(1, node->InputCount());
505 ProcessInput(node, 0, input_use);
506 SetOutput(node, output);
507 }
508
509 // Helper for leaf nodes.
Ben Murdochda12d292016-06-02 14:46:10 +0100510 void VisitLeaf(Node* node, MachineRepresentation output) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511 DCHECK_EQ(0, node->InputCount());
512 SetOutput(node, output);
513 }
514
515 // Helpers for specific types of binops.
516 void VisitFloat64Binop(Node* node) {
Ben Murdochc5610432016-08-08 18:44:38 +0100517 VisitBinop(node, UseInfo::TruncatingFloat64(),
518 MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000519 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000520 void VisitInt32Binop(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100521 VisitBinop(node, UseInfo::TruncatingWord32(),
522 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000523 }
524 void VisitWord32TruncatingBinop(Node* node) {
525 VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +0100526 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000527 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000528 void VisitUint32Binop(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100529 VisitBinop(node, UseInfo::TruncatingWord32(),
530 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000531 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000532 void VisitInt64Binop(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100533 VisitBinop(node, UseInfo::TruncatingWord64(),
534 MachineRepresentation::kWord64);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000535 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000536 void VisitUint64Binop(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100537 VisitBinop(node, UseInfo::TruncatingWord64(),
538 MachineRepresentation::kWord64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000539 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000540 void VisitFloat64Cmp(Node* node) {
Ben Murdochc5610432016-08-08 18:44:38 +0100541 VisitBinop(node, UseInfo::TruncatingFloat64(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000542 }
543 void VisitInt32Cmp(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100544 VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000545 }
546 void VisitUint32Cmp(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100547 VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000548 }
549 void VisitInt64Cmp(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100550 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000551 }
552 void VisitUint64Cmp(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100553 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000554 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000555
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400556 // Infer representation for phi-like nodes.
Ben Murdochda12d292016-06-02 14:46:10 +0100557 MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000558 // Compute the representation.
Ben Murdochda12d292016-06-02 14:46:10 +0100559 Type* type = GetUpperBound(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000560 if (type->Is(Type::None())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100561 return MachineRepresentation::kNone;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000562 } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100563 return MachineRepresentation::kWord32;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000564 } else if (use.TruncatesToWord32()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100565 return MachineRepresentation::kWord32;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000566 } else if (type->Is(Type::Boolean())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100567 return MachineRepresentation::kBit;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000568 } else if (type->Is(Type::Number())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100569 return MachineRepresentation::kFloat64;
Ben Murdochc5610432016-08-08 18:44:38 +0100570 } else if (use.TruncatesToFloat64()) {
571 return MachineRepresentation::kFloat64;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000572 } else if (type->Is(Type::Internal())) {
573 // We mark (u)int64 as Type::Internal.
574 // TODO(jarin) This is a workaround for our lack of (u)int64
575 // types. This can be removed once we can represent (u)int64
576 // unambiguously. (At the moment internal objects, such as the hole,
577 // are also Type::Internal()).
578 bool is_word64 = GetInfo(node->InputAt(0))->representation() ==
579 MachineRepresentation::kWord64;
580#ifdef DEBUG
581 // Check that all the inputs agree on being Word64.
582 for (int i = 1; i < node->op()->ValueInputCount(); i++) {
583 DCHECK_EQ(is_word64, GetInfo(node->InputAt(i))->representation() ==
584 MachineRepresentation::kWord64);
585 }
586#endif
Ben Murdochda12d292016-06-02 14:46:10 +0100587 return is_word64 ? MachineRepresentation::kWord64
588 : MachineRepresentation::kTagged;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000589 }
Ben Murdochda12d292016-06-02 14:46:10 +0100590 return MachineRepresentation::kTagged;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400591 }
592
593 // Helper for handling selects.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000594 void VisitSelect(Node* node, Truncation truncation,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400595 SimplifiedLowering* lowering) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596 ProcessInput(node, 0, UseInfo::Bool());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400597
Ben Murdochda12d292016-06-02 14:46:10 +0100598 MachineRepresentation output = GetOutputInfoForPhi(node, truncation);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000599 SetOutput(node, output);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000600
601 if (lower()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400602 // Update the select operator.
603 SelectParameters p = SelectParametersOf(node->op());
Ben Murdochda12d292016-06-02 14:46:10 +0100604 if (output != p.representation()) {
605 NodeProperties::ChangeOp(node,
606 lowering->common()->Select(output, p.hint()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400607 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400608 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000609 // Convert inputs to the output representation of this phi, pass the
610 // truncation truncation along.
Ben Murdochda12d292016-06-02 14:46:10 +0100611 UseInfo input_use(output, truncation);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612 ProcessInput(node, 1, input_use);
613 ProcessInput(node, 2, input_use);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400614 }
615
616 // Helper for handling phis.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000617 void VisitPhi(Node* node, Truncation truncation,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400618 SimplifiedLowering* lowering) {
Ben Murdochda12d292016-06-02 14:46:10 +0100619 MachineRepresentation output = GetOutputInfoForPhi(node, truncation);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000620 SetOutput(node, output);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400621
622 int values = node->op()->ValueInputCount();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400623 if (lower()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624 // Update the phi operator.
Ben Murdochda12d292016-06-02 14:46:10 +0100625 if (output != PhiRepresentationOf(node->op())) {
626 NodeProperties::ChangeOp(node, lowering->common()->Phi(output, values));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000627 }
628 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000629
630 // Convert inputs to the output representation of this phi, pass the
631 // truncation truncation along.
Ben Murdochda12d292016-06-02 14:46:10 +0100632 UseInfo input_use(output, truncation);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633 for (int i = 0; i < node->InputCount(); i++) {
634 ProcessInput(node, i, i < values ? input_use : UseInfo::None());
635 }
636 }
637
638 void VisitCall(Node* node, SimplifiedLowering* lowering) {
Ben Murdochc5610432016-08-08 18:44:38 +0100639 const CallDescriptor* desc = CallDescriptorOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000640 const MachineSignature* sig = desc->GetMachineSignature();
641 int params = static_cast<int>(sig->parameter_count());
642 // Propagate representation information from call descriptor.
643 for (int i = 0; i < node->InputCount(); i++) {
644 if (i == 0) {
645 // The target of the call.
646 ProcessInput(node, i, UseInfo::None());
647 } else if ((i - 1) < params) {
648 ProcessInput(node, i, TruncatingUseInfoFromRepresentation(
649 sig->GetParam(i - 1).representation()));
650 } else {
651 ProcessInput(node, i, UseInfo::None());
652 }
653 }
654
655 if (sig->return_count() > 0) {
Ben Murdochda12d292016-06-02 14:46:10 +0100656 SetOutput(node,
657 desc->GetMachineSignature()->GetReturn().representation());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000658 } else {
Ben Murdochda12d292016-06-02 14:46:10 +0100659 SetOutput(node, MachineRepresentation::kTagged);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000660 }
661 }
662
663 MachineSemantic DeoptValueSemanticOf(Type* type) {
664 CHECK(!type->Is(Type::None()));
665 // We only need signedness to do deopt correctly.
666 if (type->Is(Type::Signed32())) {
667 return MachineSemantic::kInt32;
668 } else if (type->Is(Type::Unsigned32())) {
669 return MachineSemantic::kUint32;
670 } else {
671 return MachineSemantic::kAny;
672 }
673 }
674
675 void VisitStateValues(Node* node) {
676 if (phase_ == PROPAGATE) {
677 for (int i = 0; i < node->InputCount(); i++) {
678 EnqueueInput(node, i, UseInfo::Any());
679 }
680 } else {
681 Zone* zone = jsgraph_->zone();
682 ZoneVector<MachineType>* types =
683 new (zone->New(sizeof(ZoneVector<MachineType>)))
684 ZoneVector<MachineType>(node->InputCount(), zone);
685 for (int i = 0; i < node->InputCount(); i++) {
Ben Murdochda12d292016-06-02 14:46:10 +0100686 Node* input = node->InputAt(i);
687 NodeInfo* input_info = GetInfo(input);
688 MachineType machine_type(input_info->representation(),
689 DeoptValueSemanticOf(GetUpperBound(input)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000690 DCHECK(machine_type.representation() !=
691 MachineRepresentation::kWord32 ||
692 machine_type.semantic() == MachineSemantic::kInt32 ||
693 machine_type.semantic() == MachineSemantic::kUint32);
694 (*types)[i] = machine_type;
695 }
696 NodeProperties::ChangeOp(node,
697 jsgraph_->common()->TypedStateValues(types));
698 }
Ben Murdochda12d292016-06-02 14:46:10 +0100699 SetOutput(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000700 }
701
702 const Operator* Int32Op(Node* node) {
703 return changer_->Int32OperatorFor(node->opcode());
704 }
705
706 const Operator* Uint32Op(Node* node) {
707 return changer_->Uint32OperatorFor(node->opcode());
708 }
709
710 const Operator* Float64Op(Node* node) {
711 return changer_->Float64OperatorFor(node->opcode());
712 }
713
Ben Murdochc5610432016-08-08 18:44:38 +0100714 WriteBarrierKind WriteBarrierKindFor(
715 BaseTaggedness base_taggedness,
716 MachineRepresentation field_representation, Type* field_type,
717 Node* value) {
718 if (base_taggedness == kTaggedBase &&
719 field_representation == MachineRepresentation::kTagged) {
720 Type* value_type = NodeProperties::GetType(value);
721 if (field_type->Is(Type::TaggedSigned()) ||
722 value_type->Is(Type::TaggedSigned())) {
723 // Write barriers are only for stores of heap objects.
724 return kNoWriteBarrier;
725 }
726 if (field_type->Is(Type::BooleanOrNullOrUndefined()) ||
727 value_type->Is(Type::BooleanOrNullOrUndefined())) {
728 // Write barriers are not necessary when storing true, false, null or
729 // undefined, because these special oddballs are always in the root set.
730 return kNoWriteBarrier;
731 }
732 if (value_type->IsConstant() &&
733 value_type->AsConstant()->Value()->IsHeapObject()) {
734 Handle<HeapObject> value_object =
735 Handle<HeapObject>::cast(value_type->AsConstant()->Value());
736 RootIndexMap root_index_map(jsgraph_->isolate());
737 int root_index = root_index_map.Lookup(*value_object);
738 if (root_index != RootIndexMap::kInvalidRootIndex &&
739 jsgraph_->isolate()->heap()->RootIsImmortalImmovable(root_index)) {
740 // Write barriers are unnecessary for immortal immovable roots.
741 return kNoWriteBarrier;
742 }
743 if (value_object->IsMap()) {
744 // Write barriers for storing maps are cheaper.
745 return kMapWriteBarrier;
746 }
747 }
748 if (field_type->Is(Type::TaggedPointer()) ||
749 value_type->Is(Type::TaggedPointer())) {
750 // Write barriers for heap objects are cheaper.
751 return kPointerWriteBarrier;
752 }
753 NumberMatcher m(value);
754 if (m.HasValue()) {
755 if (IsSmiDouble(m.Value())) {
756 // Storing a smi doesn't need a write barrier.
757 return kNoWriteBarrier;
758 }
759 // The NumberConstant will be represented as HeapNumber.
760 return kPointerWriteBarrier;
761 }
762 return kFullWriteBarrier;
763 }
764 return kNoWriteBarrier;
765 }
766
767 WriteBarrierKind WriteBarrierKindFor(
768 BaseTaggedness base_taggedness,
769 MachineRepresentation field_representation, int field_offset,
770 Type* field_type, Node* value) {
771 if (base_taggedness == kTaggedBase &&
772 field_offset == HeapObject::kMapOffset) {
773 return kMapWriteBarrier;
774 }
775 return WriteBarrierKindFor(base_taggedness, field_representation,
776 field_type, value);
777 }
778
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000779 // Dispatching routine for visiting the node {node} with the usage {use}.
780 // Depending on the operator, propagate new usage info to the inputs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000781 void VisitNode(Node* node, Truncation truncation,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000782 SimplifiedLowering* lowering) {
783 switch (node->opcode()) {
784 //------------------------------------------------------------------
785 // Common operators.
786 //------------------------------------------------------------------
787 case IrOpcode::kStart:
788 case IrOpcode::kDead:
Ben Murdochda12d292016-06-02 14:46:10 +0100789 return VisitLeaf(node, MachineRepresentation::kNone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000790 case IrOpcode::kParameter: {
791 // TODO(titzer): use representation from linkage.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000792 ProcessInput(node, 0, UseInfo::None());
Ben Murdochda12d292016-06-02 14:46:10 +0100793 SetOutput(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000794 return;
795 }
796 case IrOpcode::kInt32Constant:
Ben Murdochda12d292016-06-02 14:46:10 +0100797 return VisitLeaf(node, MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000798 case IrOpcode::kInt64Constant:
Ben Murdochda12d292016-06-02 14:46:10 +0100799 return VisitLeaf(node, MachineRepresentation::kWord64);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000800 case IrOpcode::kFloat32Constant:
Ben Murdochda12d292016-06-02 14:46:10 +0100801 return VisitLeaf(node, MachineRepresentation::kFloat32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000802 case IrOpcode::kFloat64Constant:
Ben Murdochda12d292016-06-02 14:46:10 +0100803 return VisitLeaf(node, MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000804 case IrOpcode::kExternalConstant:
Ben Murdochda12d292016-06-02 14:46:10 +0100805 return VisitLeaf(node, MachineType::PointerRepresentation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000806 case IrOpcode::kNumberConstant:
Ben Murdochda12d292016-06-02 14:46:10 +0100807 return VisitLeaf(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000808 case IrOpcode::kHeapConstant:
Ben Murdochda12d292016-06-02 14:46:10 +0100809 return VisitLeaf(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000810
Ben Murdochda12d292016-06-02 14:46:10 +0100811 case IrOpcode::kDeoptimizeIf:
812 case IrOpcode::kDeoptimizeUnless:
813 ProcessInput(node, 0, UseInfo::Bool());
814 ProcessInput(node, 1, UseInfo::AnyTagged());
815 ProcessRemainingInputs(node, 2);
816 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817 case IrOpcode::kBranch:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000818 ProcessInput(node, 0, UseInfo::Bool());
819 EnqueueInput(node, NodeProperties::FirstControlIndex(node));
820 break;
821 case IrOpcode::kSwitch:
822 ProcessInput(node, 0, UseInfo::TruncatingWord32());
823 EnqueueInput(node, NodeProperties::FirstControlIndex(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000824 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400825 case IrOpcode::kSelect:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000826 return VisitSelect(node, truncation, lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000827 case IrOpcode::kPhi:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000828 return VisitPhi(node, truncation, lowering);
829 case IrOpcode::kCall:
830 return VisitCall(node, lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000831
Ben Murdochc5610432016-08-08 18:44:38 +0100832 //------------------------------------------------------------------
833 // JavaScript operators.
834 //------------------------------------------------------------------
835 case IrOpcode::kJSToNumber: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000836 VisitInputs(node);
Ben Murdochc5610432016-08-08 18:44:38 +0100837 // TODO(bmeurer): Optimize somewhat based on input type?
838 if (truncation.TruncatesToWord32()) {
839 SetOutput(node, MachineRepresentation::kWord32);
840 if (lower()) lowering->DoJSToNumberTruncatesToWord32(node, this);
841 } else if (truncation.TruncatesToFloat64()) {
842 SetOutput(node, MachineRepresentation::kFloat64);
843 if (lower()) lowering->DoJSToNumberTruncatesToFloat64(node, this);
844 } else {
845 SetOutput(node, MachineRepresentation::kTagged);
846 }
847 break;
848 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000849
850 //------------------------------------------------------------------
851 // Simplified operators.
852 //------------------------------------------------------------------
853 case IrOpcode::kBooleanNot: {
854 if (lower()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000855 NodeInfo* input_info = GetInfo(node->InputAt(0));
856 if (input_info->representation() == MachineRepresentation::kBit) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400857 // BooleanNot(x: kRepBit) => Word32Equal(x, #0)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000858 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000859 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000860 } else {
861 // BooleanNot(x: kRepTagged) => WordEqual(x, #false)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000862 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000863 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000864 }
865 } else {
866 // No input representation requirement; adapt during lowering.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000867 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
Ben Murdochda12d292016-06-02 14:46:10 +0100868 SetOutput(node, MachineRepresentation::kBit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000869 }
870 break;
871 }
872 case IrOpcode::kBooleanToNumber: {
873 if (lower()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000874 NodeInfo* input_info = GetInfo(node->InputAt(0));
875 if (input_info->representation() == MachineRepresentation::kBit) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000876 // BooleanToNumber(x: kRepBit) => x
877 DeferReplacement(node, node->InputAt(0));
878 } else {
879 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000880 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000881 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000882 }
883 } else {
884 // No input representation requirement; adapt during lowering.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000885 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
Ben Murdochda12d292016-06-02 14:46:10 +0100886 SetOutput(node, MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000887 }
888 break;
889 }
890 case IrOpcode::kNumberEqual:
891 case IrOpcode::kNumberLessThan:
892 case IrOpcode::kNumberLessThanOrEqual: {
893 // Number comparisons reduce to integer comparisons for integer inputs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000894 if (BothInputsAreSigned32(node)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000895 // => signed Int32Cmp
896 VisitInt32Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000897 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
898 } else if (BothInputsAreUnsigned32(node)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000899 // => unsigned Int32Cmp
900 VisitUint32Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000901 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000902 } else {
903 // => Float64Cmp
904 VisitFloat64Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000905 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000906 }
907 break;
908 }
909 case IrOpcode::kNumberAdd:
910 case IrOpcode::kNumberSubtract: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000911 if (BothInputsAre(node, Type::Signed32()) &&
912 NodeProperties::GetType(node)->Is(Type::Signed32())) {
913 // int32 + int32 = int32
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000914 // => signed Int32Add/Sub
915 VisitInt32Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000916 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
917 } else if (BothInputsAre(node, type_cache_.kAdditiveSafeInteger) &&
918 truncation.TruncatesToWord32()) {
919 // safe-int + safe-int = x (truncated to int32)
920 // => signed Int32Add/Sub (truncated)
921 VisitWord32TruncatingBinop(node);
922 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000923 } else {
924 // => Float64Add/Sub
925 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000926 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000927 }
928 break;
929 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400930 case IrOpcode::kNumberMultiply: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931 if (BothInputsAreSigned32(node)) {
932 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
933 // Multiply reduces to Int32Mul if the inputs and the output
934 // are integers.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400935 VisitInt32Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000936 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
937 break;
938 }
939 if (truncation.TruncatesToWord32() &&
940 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger)) {
941 // Multiply reduces to Int32Mul if the inputs are integers,
942 // the uses are truncating and the result is in the safe
943 // integer range.
944 VisitWord32TruncatingBinop(node);
945 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400946 break;
947 }
948 }
949 // => Float64Mul
950 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400952 break;
953 }
954 case IrOpcode::kNumberDivide: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000955 if (BothInputsAreSigned32(node)) {
956 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400957 // => signed Int32Div
958 VisitInt32Binop(node);
959 if (lower()) DeferReplacement(node, lowering->Int32Div(node));
960 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000961 }
962 if (truncation.TruncatesToWord32()) {
963 // => signed Int32Div
964 VisitWord32TruncatingBinop(node);
965 if (lower()) DeferReplacement(node, lowering->Int32Div(node));
966 break;
967 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400968 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000969 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400970 // => unsigned Uint32Div
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000971 VisitWord32TruncatingBinop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400972 if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
973 break;
974 }
975 // => Float64Div
976 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000977 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400978 break;
979 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000980 case IrOpcode::kNumberModulus: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000981 if (BothInputsAreSigned32(node)) {
982 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
983 // => signed Int32Mod
984 VisitInt32Binop(node);
985 if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
986 break;
987 }
988 if (truncation.TruncatesToWord32()) {
989 // => signed Int32Mod
990 VisitWord32TruncatingBinop(node);
991 if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
992 break;
993 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400994 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000995 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400996 // => unsigned Uint32Mod
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000997 VisitWord32TruncatingBinop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400998 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
999 break;
1000 }
1001 // => Float64Mod
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001002 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001003 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001004 break;
1005 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001006 case IrOpcode::kNumberBitwiseOr:
1007 case IrOpcode::kNumberBitwiseXor:
1008 case IrOpcode::kNumberBitwiseAnd: {
1009 VisitInt32Binop(node);
1010 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
1011 break;
1012 }
1013 case IrOpcode::kNumberShiftLeft: {
Ben Murdochda12d292016-06-02 14:46:10 +01001014 Type* rhs_type = GetUpperBound(node->InputAt(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001015 VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001016 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001017 if (lower()) {
1018 lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001019 }
1020 break;
1021 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001022 case IrOpcode::kNumberShiftRight: {
Ben Murdochda12d292016-06-02 14:46:10 +01001023 Type* rhs_type = GetUpperBound(node->InputAt(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001024 VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001025 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001026 if (lower()) {
1027 lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
1028 }
1029 break;
1030 }
1031 case IrOpcode::kNumberShiftRightLogical: {
Ben Murdochda12d292016-06-02 14:46:10 +01001032 Type* rhs_type = GetUpperBound(node->InputAt(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001033 VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001034 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001035 if (lower()) {
1036 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
1037 }
1038 break;
1039 }
Ben Murdochda12d292016-06-02 14:46:10 +01001040 case IrOpcode::kNumberClz32: {
1041 VisitUnop(node, UseInfo::TruncatingWord32(),
1042 MachineRepresentation::kWord32);
1043 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
1044 break;
1045 }
Ben Murdochc5610432016-08-08 18:44:38 +01001046 case IrOpcode::kNumberImul: {
1047 VisitBinop(node, UseInfo::TruncatingWord32(),
1048 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
1049 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
1050 break;
1051 }
Ben Murdochda12d292016-06-02 14:46:10 +01001052 case IrOpcode::kNumberCeil: {
Ben Murdochc5610432016-08-08 18:44:38 +01001053 VisitUnop(node, UseInfo::TruncatingFloat64(),
1054 MachineRepresentation::kFloat64);
Ben Murdochda12d292016-06-02 14:46:10 +01001055 if (lower()) DeferReplacement(node, lowering->Float64Ceil(node));
1056 break;
1057 }
1058 case IrOpcode::kNumberFloor: {
Ben Murdochc5610432016-08-08 18:44:38 +01001059 VisitUnop(node, UseInfo::TruncatingFloat64(),
1060 MachineRepresentation::kFloat64);
Ben Murdochda12d292016-06-02 14:46:10 +01001061 if (lower()) DeferReplacement(node, lowering->Float64Floor(node));
1062 break;
1063 }
1064 case IrOpcode::kNumberRound: {
Ben Murdochc5610432016-08-08 18:44:38 +01001065 VisitUnop(node, UseInfo::TruncatingFloat64(),
1066 MachineRepresentation::kFloat64);
Ben Murdochda12d292016-06-02 14:46:10 +01001067 if (lower()) DeferReplacement(node, lowering->Float64Round(node));
1068 break;
1069 }
1070 case IrOpcode::kNumberTrunc: {
Ben Murdochc5610432016-08-08 18:44:38 +01001071 VisitUnop(node, UseInfo::TruncatingFloat64(),
1072 MachineRepresentation::kFloat64);
Ben Murdochda12d292016-06-02 14:46:10 +01001073 if (lower()) DeferReplacement(node, lowering->Float64Trunc(node));
1074 break;
1075 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001076 case IrOpcode::kNumberToInt32: {
1077 // Just change representation if necessary.
Ben Murdochda12d292016-06-02 14:46:10 +01001078 VisitUnop(node, UseInfo::TruncatingWord32(),
1079 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001080 if (lower()) DeferReplacement(node, node->InputAt(0));
1081 break;
1082 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001083 case IrOpcode::kNumberToUint32: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001084 // Just change representation if necessary.
Ben Murdochda12d292016-06-02 14:46:10 +01001085 VisitUnop(node, UseInfo::TruncatingWord32(),
1086 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001087 if (lower()) DeferReplacement(node, node->InputAt(0));
1088 break;
1089 }
1090 case IrOpcode::kNumberIsHoleNaN: {
Ben Murdochc5610432016-08-08 18:44:38 +01001091 VisitUnop(node, UseInfo::TruncatingFloat64(),
1092 MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001093 if (lower()) {
1094 // NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x),
1095 // #HoleNaNLower32)
1096 node->ReplaceInput(0,
1097 jsgraph_->graph()->NewNode(
1098 lowering->machine()->Float64ExtractLowWord32(),
1099 node->InputAt(0)));
1100 node->AppendInput(jsgraph_->zone(),
1101 jsgraph_->Int32Constant(kHoleNanLower32));
1102 NodeProperties::ChangeOp(node, jsgraph_->machine()->Word32Equal());
1103 }
1104 break;
1105 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001106 case IrOpcode::kReferenceEqual: {
Ben Murdochda12d292016-06-02 14:46:10 +01001107 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001108 if (lower()) {
1109 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
1110 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001111 break;
1112 }
1113 case IrOpcode::kStringEqual: {
Ben Murdochda12d292016-06-02 14:46:10 +01001114 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1115 if (lower()) {
1116 // StringEqual(x, y) => Call(StringEqualStub, x, y, no-context)
Ben Murdochc5610432016-08-08 18:44:38 +01001117 Operator::Properties properties =
1118 Operator::kCommutative | Operator::kNoThrow;
Ben Murdochda12d292016-06-02 14:46:10 +01001119 Callable callable = CodeFactory::StringEqual(jsgraph_->isolate());
1120 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1121 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1122 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1123 flags, properties);
1124 node->InsertInput(jsgraph_->zone(), 0,
1125 jsgraph_->HeapConstant(callable.code()));
Ben Murdochc5610432016-08-08 18:44:38 +01001126 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
1127 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
1128 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
Ben Murdochda12d292016-06-02 14:46:10 +01001129 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1130 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001131 break;
1132 }
1133 case IrOpcode::kStringLessThan: {
Ben Murdochda12d292016-06-02 14:46:10 +01001134 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1135 if (lower()) {
1136 // StringLessThan(x, y) => Call(StringLessThanStub, x, y, no-context)
Ben Murdochc5610432016-08-08 18:44:38 +01001137 Operator::Properties properties = Operator::kNoThrow;
Ben Murdochda12d292016-06-02 14:46:10 +01001138 Callable callable = CodeFactory::StringLessThan(jsgraph_->isolate());
1139 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1140 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1141 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1142 flags, properties);
1143 node->InsertInput(jsgraph_->zone(), 0,
1144 jsgraph_->HeapConstant(callable.code()));
Ben Murdochc5610432016-08-08 18:44:38 +01001145 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
1146 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
1147 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
Ben Murdochda12d292016-06-02 14:46:10 +01001148 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1149 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001150 break;
1151 }
1152 case IrOpcode::kStringLessThanOrEqual: {
Ben Murdochda12d292016-06-02 14:46:10 +01001153 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1154 if (lower()) {
1155 // StringLessThanOrEqual(x, y)
1156 // => Call(StringLessThanOrEqualStub, x, y, no-context)
Ben Murdochc5610432016-08-08 18:44:38 +01001157 Operator::Properties properties = Operator::kNoThrow;
Ben Murdochda12d292016-06-02 14:46:10 +01001158 Callable callable =
1159 CodeFactory::StringLessThanOrEqual(jsgraph_->isolate());
1160 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1161 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1162 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1163 flags, properties);
1164 node->InsertInput(jsgraph_->zone(), 0,
1165 jsgraph_->HeapConstant(callable.code()));
Ben Murdochc5610432016-08-08 18:44:38 +01001166 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
1167 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
1168 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
Ben Murdochda12d292016-06-02 14:46:10 +01001169 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1170 }
1171 break;
1172 }
1173 case IrOpcode::kStringToNumber: {
1174 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1175 if (lower()) {
1176 // StringToNumber(x) => Call(StringToNumberStub, x, no-context)
Ben Murdochc5610432016-08-08 18:44:38 +01001177 Operator::Properties properties = Operator::kNoThrow;
Ben Murdochda12d292016-06-02 14:46:10 +01001178 Callable callable = CodeFactory::StringToNumber(jsgraph_->isolate());
1179 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1180 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1181 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1182 flags, properties);
1183 node->InsertInput(jsgraph_->zone(), 0,
1184 jsgraph_->HeapConstant(callable.code()));
1185 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
Ben Murdochc5610432016-08-08 18:44:38 +01001186 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
1187 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
Ben Murdochda12d292016-06-02 14:46:10 +01001188 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1189 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001190 break;
1191 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001192 case IrOpcode::kAllocate: {
Ben Murdochc5610432016-08-08 18:44:38 +01001193 ProcessInput(node, 0, UseInfo::TruncatingWord32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001194 ProcessRemainingInputs(node, 1);
Ben Murdochda12d292016-06-02 14:46:10 +01001195 SetOutput(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001196 break;
1197 }
1198 case IrOpcode::kLoadField: {
1199 FieldAccess access = FieldAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001200 ProcessInput(node, 0, UseInfoForBasePointer(access));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001201 ProcessRemainingInputs(node, 1);
Ben Murdochda12d292016-06-02 14:46:10 +01001202 SetOutput(node, access.machine_type.representation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001203 break;
1204 }
1205 case IrOpcode::kStoreField: {
1206 FieldAccess access = FieldAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001207 ProcessInput(node, 0, UseInfoForBasePointer(access));
1208 ProcessInput(node, 1, TruncatingUseInfoFromRepresentation(
1209 access.machine_type.representation()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001210 ProcessRemainingInputs(node, 2);
Ben Murdochda12d292016-06-02 14:46:10 +01001211 SetOutput(node, MachineRepresentation::kNone);
Ben Murdochc5610432016-08-08 18:44:38 +01001212 if (lower()) {
1213 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
1214 access.base_is_tagged, access.machine_type.representation(),
1215 access.offset, access.type, node->InputAt(1));
1216 if (write_barrier_kind < access.write_barrier_kind) {
1217 access.write_barrier_kind = write_barrier_kind;
1218 NodeProperties::ChangeOp(
1219 node, jsgraph_->simplified()->StoreField(access));
1220 }
1221 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001222 break;
1223 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001224 case IrOpcode::kLoadBuffer: {
1225 BufferAccess access = BufferAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001226 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
1227 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
1228 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001229 ProcessRemainingInputs(node, 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001230
Ben Murdochda12d292016-06-02 14:46:10 +01001231 MachineRepresentation output;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001232 if (truncation.TruncatesUndefinedToZeroOrNaN()) {
1233 if (truncation.TruncatesNaNToZero()) {
1234 // If undefined is truncated to a non-NaN number, we can use
1235 // the load's representation.
Ben Murdochda12d292016-06-02 14:46:10 +01001236 output = access.machine_type().representation();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001237 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001238 // If undefined is truncated to a number, but the use can
1239 // observe NaN, we need to output at least the float32
1240 // representation.
1241 if (access.machine_type().representation() ==
1242 MachineRepresentation::kFloat32) {
Ben Murdochda12d292016-06-02 14:46:10 +01001243 output = access.machine_type().representation();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001244 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01001245 output = MachineRepresentation::kFloat64;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001246 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001247 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001248 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001249 // If undefined is not truncated away, we need to have the tagged
1250 // representation.
Ben Murdochda12d292016-06-02 14:46:10 +01001251 output = MachineRepresentation::kTagged;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001252 }
Ben Murdochda12d292016-06-02 14:46:10 +01001253 SetOutput(node, output);
1254 if (lower()) lowering->DoLoadBuffer(node, output, changer_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001255 break;
1256 }
1257 case IrOpcode::kStoreBuffer: {
1258 BufferAccess access = BufferAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001259 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
1260 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
1261 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
1262 ProcessInput(node, 3,
1263 TruncatingUseInfoFromRepresentation(
1264 access.machine_type().representation())); // value
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001265 ProcessRemainingInputs(node, 4);
Ben Murdochda12d292016-06-02 14:46:10 +01001266 SetOutput(node, MachineRepresentation::kNone);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001267 if (lower()) lowering->DoStoreBuffer(node);
1268 break;
1269 }
1270 case IrOpcode::kLoadElement: {
1271 ElementAccess access = ElementAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001272 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
1273 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001274 ProcessRemainingInputs(node, 2);
Ben Murdochda12d292016-06-02 14:46:10 +01001275 SetOutput(node, access.machine_type.representation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001276 break;
1277 }
1278 case IrOpcode::kStoreElement: {
1279 ElementAccess access = ElementAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001280 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
1281 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
1282 ProcessInput(node, 2,
1283 TruncatingUseInfoFromRepresentation(
1284 access.machine_type.representation())); // value
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001285 ProcessRemainingInputs(node, 3);
Ben Murdochda12d292016-06-02 14:46:10 +01001286 SetOutput(node, MachineRepresentation::kNone);
Ben Murdochc5610432016-08-08 18:44:38 +01001287 if (lower()) {
1288 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
1289 access.base_is_tagged, access.machine_type.representation(),
1290 access.type, node->InputAt(2));
1291 if (write_barrier_kind < access.write_barrier_kind) {
1292 access.write_barrier_kind = write_barrier_kind;
1293 NodeProperties::ChangeOp(
1294 node, jsgraph_->simplified()->StoreElement(access));
1295 }
1296 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001297 break;
1298 }
Ben Murdochc5610432016-08-08 18:44:38 +01001299 case IrOpcode::kObjectIsCallable:
Ben Murdochda12d292016-06-02 14:46:10 +01001300 case IrOpcode::kObjectIsNumber:
1301 case IrOpcode::kObjectIsReceiver:
1302 case IrOpcode::kObjectIsSmi:
Ben Murdochc5610432016-08-08 18:44:38 +01001303 case IrOpcode::kObjectIsString:
Ben Murdochda12d292016-06-02 14:46:10 +01001304 case IrOpcode::kObjectIsUndetectable: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001305 ProcessInput(node, 0, UseInfo::AnyTagged());
Ben Murdochda12d292016-06-02 14:46:10 +01001306 SetOutput(node, MachineRepresentation::kBit);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001307 break;
1308 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001309
1310 //------------------------------------------------------------------
1311 // Machine-level operators.
1312 //------------------------------------------------------------------
1313 case IrOpcode::kLoad: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001314 // TODO(jarin) Eventually, we should get rid of all machine stores
1315 // from the high-level phases, then this becomes UNREACHABLE.
1316 LoadRepresentation rep = LoadRepresentationOf(node->op());
1317 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
1318 ProcessInput(node, 1, UseInfo::PointerInt()); // index
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001319 ProcessRemainingInputs(node, 2);
Ben Murdochda12d292016-06-02 14:46:10 +01001320 SetOutput(node, rep.representation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001321 break;
1322 }
1323 case IrOpcode::kStore: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001324 // TODO(jarin) Eventually, we should get rid of all machine stores
1325 // from the high-level phases, then this becomes UNREACHABLE.
1326 StoreRepresentation rep = StoreRepresentationOf(node->op());
1327 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
1328 ProcessInput(node, 1, UseInfo::PointerInt()); // index
1329 ProcessInput(node, 2,
1330 TruncatingUseInfoFromRepresentation(rep.representation()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001331 ProcessRemainingInputs(node, 3);
Ben Murdochda12d292016-06-02 14:46:10 +01001332 SetOutput(node, MachineRepresentation::kNone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001333 break;
1334 }
1335 case IrOpcode::kWord32Shr:
1336 // We output unsigned int32 for shift right because JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001337 return VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001338 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001339 case IrOpcode::kWord32And:
1340 case IrOpcode::kWord32Or:
1341 case IrOpcode::kWord32Xor:
1342 case IrOpcode::kWord32Shl:
1343 case IrOpcode::kWord32Sar:
1344 // We use signed int32 as the output type for these word32 operations,
1345 // though the machine bits are the same for either signed or unsigned,
1346 // because JavaScript considers the result from these operations signed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001347 return VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001348 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001349 case IrOpcode::kWord32Equal:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001350 return VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001351 MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001352
1353 case IrOpcode::kWord32Clz:
1354 return VisitUnop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001355 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001356
1357 case IrOpcode::kInt32Add:
1358 case IrOpcode::kInt32Sub:
1359 case IrOpcode::kInt32Mul:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001360 case IrOpcode::kInt32MulHigh:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001361 case IrOpcode::kInt32Div:
1362 case IrOpcode::kInt32Mod:
1363 return VisitInt32Binop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001364 case IrOpcode::kUint32Div:
1365 case IrOpcode::kUint32Mod:
1366 case IrOpcode::kUint32MulHigh:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001367 return VisitUint32Binop(node);
1368 case IrOpcode::kInt32LessThan:
1369 case IrOpcode::kInt32LessThanOrEqual:
1370 return VisitInt32Cmp(node);
1371
1372 case IrOpcode::kUint32LessThan:
1373 case IrOpcode::kUint32LessThanOrEqual:
1374 return VisitUint32Cmp(node);
1375
1376 case IrOpcode::kInt64Add:
1377 case IrOpcode::kInt64Sub:
1378 case IrOpcode::kInt64Mul:
1379 case IrOpcode::kInt64Div:
1380 case IrOpcode::kInt64Mod:
1381 return VisitInt64Binop(node);
1382 case IrOpcode::kInt64LessThan:
1383 case IrOpcode::kInt64LessThanOrEqual:
1384 return VisitInt64Cmp(node);
1385
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001386 case IrOpcode::kUint64LessThan:
1387 return VisitUint64Cmp(node);
1388
1389 case IrOpcode::kUint64Div:
1390 case IrOpcode::kUint64Mod:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001391 return VisitUint64Binop(node);
1392
1393 case IrOpcode::kWord64And:
1394 case IrOpcode::kWord64Or:
1395 case IrOpcode::kWord64Xor:
1396 case IrOpcode::kWord64Shl:
1397 case IrOpcode::kWord64Shr:
1398 case IrOpcode::kWord64Sar:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001399 return VisitBinop(node, UseInfo::TruncatingWord64(),
Ben Murdochda12d292016-06-02 14:46:10 +01001400 MachineRepresentation::kWord64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001401 case IrOpcode::kWord64Equal:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001402 return VisitBinop(node, UseInfo::TruncatingWord64(),
Ben Murdochda12d292016-06-02 14:46:10 +01001403 MachineRepresentation::kBit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001404
1405 case IrOpcode::kChangeInt32ToInt64:
Ben Murdochda12d292016-06-02 14:46:10 +01001406 return VisitUnop(node, UseInfo::TruncatingWord32(),
1407 MachineRepresentation::kWord64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001408 case IrOpcode::kChangeUint32ToUint64:
Ben Murdochda12d292016-06-02 14:46:10 +01001409 return VisitUnop(node, UseInfo::TruncatingWord32(),
1410 MachineRepresentation::kWord64);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001411 case IrOpcode::kTruncateFloat64ToFloat32:
Ben Murdochc5610432016-08-08 18:44:38 +01001412 return VisitUnop(node, UseInfo::TruncatingFloat64(),
Ben Murdochda12d292016-06-02 14:46:10 +01001413 MachineRepresentation::kFloat32);
Ben Murdochc5610432016-08-08 18:44:38 +01001414 case IrOpcode::kTruncateFloat64ToWord32:
1415 return VisitUnop(node, UseInfo::TruncatingFloat64(),
Ben Murdochda12d292016-06-02 14:46:10 +01001416 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001417
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001418 case IrOpcode::kChangeFloat32ToFloat64:
Ben Murdochc5610432016-08-08 18:44:38 +01001419 UNREACHABLE();
1420 return VisitUnop(node, UseInfo::TruncatingFloat32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001421 MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001422 case IrOpcode::kChangeInt32ToFloat64:
Ben Murdochda12d292016-06-02 14:46:10 +01001423 return VisitUnop(node, UseInfo::TruncatingWord32(),
1424 MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001425 case IrOpcode::kChangeUint32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001426 return VisitUnop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001427 MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001428 case IrOpcode::kFloat64Add:
1429 case IrOpcode::kFloat64Sub:
1430 case IrOpcode::kFloat64Mul:
1431 case IrOpcode::kFloat64Div:
1432 case IrOpcode::kFloat64Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001433 case IrOpcode::kFloat64Min:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001434 return VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001435 case IrOpcode::kFloat64Abs:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001436 case IrOpcode::kFloat64Sqrt:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001437 case IrOpcode::kFloat64RoundDown:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001438 case IrOpcode::kFloat64RoundTruncate:
1439 case IrOpcode::kFloat64RoundTiesAway:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001440 case IrOpcode::kFloat64RoundUp:
Ben Murdochc5610432016-08-08 18:44:38 +01001441 return VisitUnop(node, UseInfo::TruncatingFloat64(),
Ben Murdochda12d292016-06-02 14:46:10 +01001442 MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001443 case IrOpcode::kFloat64Equal:
1444 case IrOpcode::kFloat64LessThan:
1445 case IrOpcode::kFloat64LessThanOrEqual:
1446 return VisitFloat64Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001447 case IrOpcode::kFloat64ExtractLowWord32:
1448 case IrOpcode::kFloat64ExtractHighWord32:
Ben Murdochc5610432016-08-08 18:44:38 +01001449 return VisitUnop(node, UseInfo::TruncatingFloat64(),
Ben Murdochda12d292016-06-02 14:46:10 +01001450 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001451 case IrOpcode::kFloat64InsertLowWord32:
1452 case IrOpcode::kFloat64InsertHighWord32:
Ben Murdochc5610432016-08-08 18:44:38 +01001453 return VisitBinop(node, UseInfo::TruncatingFloat64(),
1454 UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001455 MachineRepresentation::kFloat64);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001456 case IrOpcode::kLoadStackPointer:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001457 case IrOpcode::kLoadFramePointer:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001458 case IrOpcode::kLoadParentFramePointer:
Ben Murdochda12d292016-06-02 14:46:10 +01001459 return VisitLeaf(node, MachineType::PointerRepresentation());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001460 case IrOpcode::kStateValues:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001461 VisitStateValues(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001462 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001463
1464 // The following opcodes are not produced before representation
1465 // inference runs, so we do not have any real test coverage.
1466 // Simply fail here.
1467 case IrOpcode::kChangeFloat64ToInt32:
1468 case IrOpcode::kChangeFloat64ToUint32:
1469 case IrOpcode::kTruncateInt64ToInt32:
1470 FATAL("Representation inference: unsupported opcodes.");
1471
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001472 default:
1473 VisitInputs(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001474 // Assume the output is tagged.
Ben Murdochda12d292016-06-02 14:46:10 +01001475 SetOutput(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001476 break;
1477 }
1478 }
1479
1480 void DeferReplacement(Node* node, Node* replacement) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001481 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(),
1482 node->op()->mnemonic(), replacement->id(),
1483 replacement->op()->mnemonic());
1484
1485 if (replacement->id() < count_ &&
Ben Murdochda12d292016-06-02 14:46:10 +01001486 GetUpperBound(node)->Is(GetUpperBound(replacement))) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001487 // Replace with a previously existing node eagerly only if the type is the
1488 // same.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001489 node->ReplaceUses(replacement);
1490 } else {
1491 // Otherwise, we are replacing a node with a representation change.
1492 // Such a substitution must be done after all lowering is done, because
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001493 // changing the type could confuse the representation change
1494 // insertion for uses of the node.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001495 replacements_.push_back(node);
1496 replacements_.push_back(replacement);
1497 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001498 node->NullAllInputs(); // Node is now dead.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001499 }
1500
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001501 void PrintOutputInfo(NodeInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001502 if (FLAG_trace_representation) {
1503 OFStream os(stdout);
Ben Murdochda12d292016-06-02 14:46:10 +01001504 os << info->representation();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001505 }
1506 }
1507
1508 void PrintRepresentation(MachineRepresentation rep) {
1509 if (FLAG_trace_representation) {
1510 OFStream os(stdout);
1511 os << rep;
1512 }
1513 }
1514
1515 void PrintTruncation(Truncation truncation) {
1516 if (FLAG_trace_representation) {
1517 OFStream os(stdout);
1518 os << truncation.description();
1519 }
1520 }
1521
1522 void PrintUseInfo(UseInfo info) {
1523 if (FLAG_trace_representation) {
1524 OFStream os(stdout);
1525 os << info.preferred() << ":" << info.truncation().description();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001526 }
1527 }
1528
1529 private:
1530 JSGraph* jsgraph_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001531 size_t const count_; // number of nodes in the graph
1532 ZoneVector<NodeInfo> info_; // node id -> usage information
1533#ifdef DEBUG
1534 ZoneVector<InputUseInfos> node_input_use_infos_; // Debug information about
1535 // requirements on inputs.
1536#endif // DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001537 NodeVector nodes_; // collected nodes
1538 NodeVector replacements_; // replacements to be done after lowering
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001539 Phase phase_; // current phase of algorithm
1540 RepresentationChanger* changer_; // for inserting representation changes
1541 ZoneQueue<Node*> queue_; // queue for traversing the graph
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001542 // TODO(danno): RepresentationSelector shouldn't know anything about the
1543 // source positions table, but must for now since there currently is no other
1544 // way to pass down source position information to nodes created during
1545 // lowering. Once this phase becomes a vanilla reducer, it should get source
1546 // position information via the SourcePositionWrapper like all other reducers.
1547 SourcePositionTable* source_positions_;
1548 TypeCache const& type_cache_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001549
1550 NodeInfo* GetInfo(Node* node) {
1551 DCHECK(node->id() >= 0);
1552 DCHECK(node->id() < count_);
1553 return &info_[node->id()];
1554 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001555};
1556
1557
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001558SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone,
1559 SourcePositionTable* source_positions)
1560 : jsgraph_(jsgraph),
1561 zone_(zone),
1562 type_cache_(TypeCache::Get()),
1563 source_positions_(source_positions) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001564
1565
1566void SimplifiedLowering::LowerAllNodes() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001567 RepresentationChanger changer(jsgraph(), jsgraph()->isolate());
1568 RepresentationSelector selector(jsgraph(), zone_, &changer,
1569 source_positions_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001570 selector.Run(this);
1571}
1572
Ben Murdochc5610432016-08-08 18:44:38 +01001573void SimplifiedLowering::DoJSToNumberTruncatesToFloat64(
1574 Node* node, RepresentationSelector* selector) {
1575 DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
1576 Node* value = node->InputAt(0);
1577 Node* context = node->InputAt(1);
1578 Node* frame_state = node->InputAt(2);
1579 Node* effect = node->InputAt(3);
1580 Node* control = node->InputAt(4);
1581 Node* throwing;
1582
1583 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
1584 Node* branch0 =
1585 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
1586
1587 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1588 Node* etrue0 = effect;
1589 Node* vtrue0;
1590 {
1591 vtrue0 = graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
1592 vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0);
1593 }
1594
1595 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1596 Node* efalse0 = effect;
1597 Node* vfalse0;
1598 {
1599 throwing = vfalse0 = efalse0 =
1600 graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
1601 frame_state, efalse0, if_false0);
1602 if_false0 = graph()->NewNode(common()->IfSuccess(), throwing);
1603
1604 Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
1605 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
1606
1607 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1608 Node* etrue1 = efalse0;
1609 Node* vtrue1;
1610 {
1611 vtrue1 =
1612 graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
1613 vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1);
1614 }
1615
1616 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1617 Node* efalse1 = efalse0;
1618 Node* vfalse1;
1619 {
1620 vfalse1 = efalse1 = graph()->NewNode(
1621 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
1622 efalse1, if_false1);
1623 }
1624
1625 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
1626 efalse0 =
1627 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
1628 vfalse0 =
1629 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1630 vtrue1, vfalse1, if_false0);
1631 }
1632
1633 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
1634 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
1635 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1636 vtrue0, vfalse0, control);
1637
1638 // Replace effect and control uses appropriately.
1639 for (Edge edge : node->use_edges()) {
1640 if (NodeProperties::IsControlEdge(edge)) {
1641 if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
1642 edge.from()->ReplaceUses(control);
1643 edge.from()->Kill();
1644 } else if (edge.from()->opcode() == IrOpcode::kIfException) {
1645 edge.UpdateTo(throwing);
1646 } else {
1647 UNREACHABLE();
1648 }
1649 } else if (NodeProperties::IsEffectEdge(edge)) {
1650 edge.UpdateTo(effect);
1651 }
1652 }
1653
1654 selector->DeferReplacement(node, value);
1655}
1656
1657void SimplifiedLowering::DoJSToNumberTruncatesToWord32(
1658 Node* node, RepresentationSelector* selector) {
1659 DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
1660 Node* value = node->InputAt(0);
1661 Node* context = node->InputAt(1);
1662 Node* frame_state = node->InputAt(2);
1663 Node* effect = node->InputAt(3);
1664 Node* control = node->InputAt(4);
1665 Node* throwing;
1666
1667 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
1668 Node* branch0 =
1669 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
1670
1671 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1672 Node* etrue0 = effect;
1673 Node* vtrue0 =
1674 graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
1675
1676 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1677 Node* efalse0 = effect;
1678 Node* vfalse0;
1679 {
1680 throwing = vfalse0 = efalse0 =
1681 graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
1682 frame_state, efalse0, if_false0);
1683 if_false0 = graph()->NewNode(common()->IfSuccess(), throwing);
1684
1685 Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
1686 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
1687
1688 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1689 Node* etrue1 = efalse0;
1690 Node* vtrue1 =
1691 graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
1692
1693 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1694 Node* efalse1 = efalse0;
1695 Node* vfalse1;
1696 {
1697 vfalse1 = efalse1 = graph()->NewNode(
1698 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
1699 efalse1, if_false1);
1700 vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1);
1701 }
1702
1703 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
1704 efalse0 =
1705 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
1706 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
1707 vtrue1, vfalse1, if_false0);
1708 }
1709
1710 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
1711 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
1712 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
1713 vtrue0, vfalse0, control);
1714
1715 // Replace effect and control uses appropriately.
1716 for (Edge edge : node->use_edges()) {
1717 if (NodeProperties::IsControlEdge(edge)) {
1718 if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
1719 edge.from()->ReplaceUses(control);
1720 edge.from()->Kill();
1721 } else if (edge.from()->opcode() == IrOpcode::kIfException) {
1722 edge.UpdateTo(throwing);
1723 } else {
1724 UNREACHABLE();
1725 }
1726 } else if (NodeProperties::IsEffectEdge(edge)) {
1727 edge.UpdateTo(effect);
1728 }
1729 }
1730
1731 selector->DeferReplacement(node, value);
1732}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001733
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001734void SimplifiedLowering::DoLoadBuffer(Node* node,
1735 MachineRepresentation output_rep,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001736 RepresentationChanger* changer) {
1737 DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001738 DCHECK_NE(MachineRepresentation::kNone, output_rep);
1739 MachineType const access_type = BufferAccessOf(node->op()).machine_type();
1740 if (output_rep != access_type.representation()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001741 Node* const buffer = node->InputAt(0);
1742 Node* const offset = node->InputAt(1);
1743 Node* const length = node->InputAt(2);
1744 Node* const effect = node->InputAt(3);
1745 Node* const control = node->InputAt(4);
1746 Node* const index =
1747 machine()->Is64()
1748 ? graph()->NewNode(machine()->ChangeUint32ToUint64(), offset)
1749 : offset;
1750
1751 Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length);
1752 Node* branch =
1753 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1754
1755 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001756 Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index,
1757 effect, if_true);
Ben Murdochc5610432016-08-08 18:44:38 +01001758 Type* element_type =
1759 Type::Intersect(NodeProperties::GetType(node), Type::Number(), zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001760 Node* vtrue = changer->GetRepresentationFor(
Ben Murdochc5610432016-08-08 18:44:38 +01001761 etrue, access_type.representation(), element_type, output_rep,
1762 Truncation::None());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001763
1764 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1765 Node* efalse = effect;
1766 Node* vfalse;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001767 if (output_rep == MachineRepresentation::kTagged) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001768 vfalse = jsgraph()->UndefinedConstant();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001769 } else if (output_rep == MachineRepresentation::kFloat64) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001770 vfalse =
1771 jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001772 } else if (output_rep == MachineRepresentation::kFloat32) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001773 vfalse =
1774 jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN());
1775 } else {
1776 vfalse = jsgraph()->Int32Constant(0);
1777 }
1778
1779 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
1780 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
1781
1782 // Replace effect uses of {node} with the {ephi}.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001783 NodeProperties::ReplaceUses(node, node, ephi);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001784
1785 // Turn the {node} into a Phi.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001786 node->ReplaceInput(0, vtrue);
1787 node->ReplaceInput(1, vfalse);
1788 node->ReplaceInput(2, merge);
1789 node->TrimInputCount(3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001790 NodeProperties::ChangeOp(node, common()->Phi(output_rep, 2));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001791 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001792 NodeProperties::ChangeOp(node, machine()->CheckedLoad(access_type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001793 }
1794}
1795
1796
1797void SimplifiedLowering::DoStoreBuffer(Node* node) {
1798 DCHECK_EQ(IrOpcode::kStoreBuffer, node->opcode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001799 MachineRepresentation const rep =
1800 BufferAccessOf(node->op()).machine_type().representation();
1801 NodeProperties::ChangeOp(node, machine()->CheckedStore(rep));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001802}
1803
Ben Murdochda12d292016-06-02 14:46:10 +01001804Node* SimplifiedLowering::Float64Ceil(Node* const node) {
1805 Node* const one = jsgraph()->Float64Constant(1.0);
1806 Node* const zero = jsgraph()->Float64Constant(0.0);
1807 Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
1808 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
1809 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
1810 Node* const input = node->InputAt(0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001811
Ben Murdochda12d292016-06-02 14:46:10 +01001812 // Use fast hardware instruction if available.
1813 if (machine()->Float64RoundUp().IsSupported()) {
1814 return graph()->NewNode(machine()->Float64RoundUp().op(), input);
1815 }
1816
1817 // General case for ceil.
1818 //
1819 // if 0.0 < input then
1820 // if 2^52 <= input then
1821 // input
1822 // else
1823 // let temp1 = (2^52 + input) - 2^52 in
1824 // if temp1 < input then
1825 // temp1 + 1
1826 // else
1827 // temp1
1828 // else
1829 // if input == 0 then
1830 // input
1831 // else
1832 // if input <= -2^52 then
1833 // input
1834 // else
1835 // let temp1 = -0 - input in
1836 // let temp2 = (2^52 + temp1) - 2^52 in
1837 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
1838 // -0 - temp3
1839 //
1840 // Note: We do not use the Diamond helper class here, because it really hurts
1841 // readability with nested diamonds.
1842
1843 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
1844 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
1845 graph()->start());
1846
1847 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1848 Node* vtrue0;
1849 {
1850 Node* check1 =
1851 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
1852 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
1853
1854 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1855 Node* vtrue1 = input;
1856
1857 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1858 Node* vfalse1;
1859 {
1860 Node* temp1 = graph()->NewNode(
1861 machine()->Float64Sub(),
1862 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
1863 vfalse1 = graph()->NewNode(
1864 common()->Select(MachineRepresentation::kFloat64),
1865 graph()->NewNode(machine()->Float64LessThan(), temp1, input),
1866 graph()->NewNode(machine()->Float64Add(), temp1, one), temp1);
1867 }
1868
1869 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
1870 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1871 vtrue1, vfalse1, if_true0);
1872 }
1873
1874 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1875 Node* vfalse0;
1876 {
1877 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
1878 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1879 check1, if_false0);
1880
1881 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1882 Node* vtrue1 = input;
1883
1884 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1885 Node* vfalse1;
1886 {
1887 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
1888 input, minus_two_52);
1889 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1890 check2, if_false1);
1891
1892 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1893 Node* vtrue2 = input;
1894
1895 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
1896 Node* vfalse2;
1897 {
1898 Node* temp1 =
1899 graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
1900 Node* temp2 = graph()->NewNode(
1901 machine()->Float64Sub(),
1902 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
1903 Node* temp3 = graph()->NewNode(
1904 common()->Select(MachineRepresentation::kFloat64),
1905 graph()->NewNode(machine()->Float64LessThan(), temp1, temp2),
1906 graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2);
1907 vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3);
1908 }
1909
1910 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
1911 vfalse1 =
1912 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1913 vtrue2, vfalse2, if_false1);
1914 }
1915
1916 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
1917 vfalse0 =
1918 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1919 vtrue1, vfalse1, if_false0);
1920 }
1921
1922 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
1923 return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1924 vtrue0, vfalse0, merge0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001925}
1926
Ben Murdochda12d292016-06-02 14:46:10 +01001927Node* SimplifiedLowering::Float64Floor(Node* const node) {
1928 Node* const one = jsgraph()->Float64Constant(1.0);
1929 Node* const zero = jsgraph()->Float64Constant(0.0);
1930 Node* const minus_one = jsgraph()->Float64Constant(-1.0);
1931 Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
1932 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
1933 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
1934 Node* const input = node->InputAt(0);
1935
1936 // Use fast hardware instruction if available.
1937 if (machine()->Float64RoundDown().IsSupported()) {
1938 return graph()->NewNode(machine()->Float64RoundDown().op(), input);
1939 }
1940
1941 // General case for floor.
1942 //
1943 // if 0.0 < input then
1944 // if 2^52 <= input then
1945 // input
1946 // else
1947 // let temp1 = (2^52 + input) - 2^52 in
1948 // if input < temp1 then
1949 // temp1 - 1
1950 // else
1951 // temp1
1952 // else
1953 // if input == 0 then
1954 // input
1955 // else
1956 // if input <= -2^52 then
1957 // input
1958 // else
1959 // let temp1 = -0 - input in
1960 // let temp2 = (2^52 + temp1) - 2^52 in
1961 // if temp2 < temp1 then
1962 // -1 - temp2
1963 // else
1964 // -0 - temp2
1965 //
1966 // Note: We do not use the Diamond helper class here, because it really hurts
1967 // readability with nested diamonds.
1968
1969 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
1970 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
1971 graph()->start());
1972
1973 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1974 Node* vtrue0;
1975 {
1976 Node* check1 =
1977 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
1978 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
1979
1980 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1981 Node* vtrue1 = input;
1982
1983 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1984 Node* vfalse1;
1985 {
1986 Node* temp1 = graph()->NewNode(
1987 machine()->Float64Sub(),
1988 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
1989 vfalse1 = graph()->NewNode(
1990 common()->Select(MachineRepresentation::kFloat64),
1991 graph()->NewNode(machine()->Float64LessThan(), input, temp1),
1992 graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1);
1993 }
1994
1995 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
1996 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1997 vtrue1, vfalse1, if_true0);
1998 }
1999
2000 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2001 Node* vfalse0;
2002 {
2003 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
2004 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2005 check1, if_false0);
2006
2007 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2008 Node* vtrue1 = input;
2009
2010 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2011 Node* vfalse1;
2012 {
2013 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
2014 input, minus_two_52);
2015 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2016 check2, if_false1);
2017
2018 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
2019 Node* vtrue2 = input;
2020
2021 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
2022 Node* vfalse2;
2023 {
2024 Node* temp1 =
2025 graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
2026 Node* temp2 = graph()->NewNode(
2027 machine()->Float64Sub(),
2028 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
2029 vfalse2 = graph()->NewNode(
2030 common()->Select(MachineRepresentation::kFloat64),
2031 graph()->NewNode(machine()->Float64LessThan(), temp2, temp1),
2032 graph()->NewNode(machine()->Float64Sub(), minus_one, temp2),
2033 graph()->NewNode(machine()->Float64Sub(), minus_zero, temp2));
2034 }
2035
2036 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
2037 vfalse1 =
2038 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2039 vtrue2, vfalse2, if_false1);
2040 }
2041
2042 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2043 vfalse0 =
2044 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2045 vtrue1, vfalse1, if_false0);
2046 }
2047
2048 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
2049 return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2050 vtrue0, vfalse0, merge0);
2051}
2052
2053Node* SimplifiedLowering::Float64Round(Node* const node) {
2054 Node* const one = jsgraph()->Float64Constant(1.0);
2055 Node* const one_half = jsgraph()->Float64Constant(0.5);
2056 Node* const input = node->InputAt(0);
2057
2058 // Round up towards Infinity, and adjust if the difference exceeds 0.5.
2059 Node* result = Float64Ceil(node);
2060 return graph()->NewNode(
2061 common()->Select(MachineRepresentation::kFloat64),
2062 graph()->NewNode(
2063 machine()->Float64LessThanOrEqual(),
2064 graph()->NewNode(machine()->Float64Sub(), result, one_half), input),
2065 result, graph()->NewNode(machine()->Float64Sub(), result, one));
2066}
2067
2068Node* SimplifiedLowering::Float64Trunc(Node* const node) {
2069 Node* const one = jsgraph()->Float64Constant(1.0);
2070 Node* const zero = jsgraph()->Float64Constant(0.0);
2071 Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
2072 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
2073 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
2074 Node* const input = node->InputAt(0);
2075
2076 // Use fast hardware instruction if available.
2077 if (machine()->Float64RoundTruncate().IsSupported()) {
2078 return graph()->NewNode(machine()->Float64RoundTruncate().op(), input);
2079 }
2080
2081 // General case for trunc.
2082 //
2083 // if 0.0 < input then
2084 // if 2^52 <= input then
2085 // input
2086 // else
2087 // let temp1 = (2^52 + input) - 2^52 in
2088 // if input < temp1 then
2089 // temp1 - 1
2090 // else
2091 // temp1
2092 // else
2093 // if input == 0 then
2094 // input
2095 // else
2096 // if input <= -2^52 then
2097 // input
2098 // else
2099 // let temp1 = -0 - input in
2100 // let temp2 = (2^52 + temp1) - 2^52 in
2101 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
2102 // -0 - temp3
2103 //
2104 // Note: We do not use the Diamond helper class here, because it really hurts
2105 // readability with nested diamonds.
2106
2107 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
2108 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
2109 graph()->start());
2110
2111 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2112 Node* vtrue0;
2113 {
2114 Node* check1 =
2115 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
2116 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
2117
2118 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2119 Node* vtrue1 = input;
2120
2121 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2122 Node* vfalse1;
2123 {
2124 Node* temp1 = graph()->NewNode(
2125 machine()->Float64Sub(),
2126 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
2127 vfalse1 = graph()->NewNode(
2128 common()->Select(MachineRepresentation::kFloat64),
2129 graph()->NewNode(machine()->Float64LessThan(), input, temp1),
2130 graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1);
2131 }
2132
2133 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2134 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2135 vtrue1, vfalse1, if_true0);
2136 }
2137
2138 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2139 Node* vfalse0;
2140 {
2141 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
2142 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2143 check1, if_false0);
2144
2145 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2146 Node* vtrue1 = input;
2147
2148 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2149 Node* vfalse1;
2150 {
2151 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
2152 input, minus_two_52);
2153 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2154 check2, if_false1);
2155
2156 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
2157 Node* vtrue2 = input;
2158
2159 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
2160 Node* vfalse2;
2161 {
2162 Node* temp1 =
2163 graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
2164 Node* temp2 = graph()->NewNode(
2165 machine()->Float64Sub(),
2166 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
2167 Node* temp3 = graph()->NewNode(
2168 common()->Select(MachineRepresentation::kFloat64),
2169 graph()->NewNode(machine()->Float64LessThan(), temp1, temp2),
2170 graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2);
2171 vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3);
2172 }
2173
2174 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
2175 vfalse1 =
2176 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2177 vtrue2, vfalse2, if_false1);
2178 }
2179
2180 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2181 vfalse0 =
2182 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2183 vtrue1, vfalse1, if_false0);
2184 }
2185
2186 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
2187 return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2188 vtrue0, vfalse0, merge0);
2189}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002190
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002191Node* SimplifiedLowering::Int32Div(Node* const node) {
2192 Int32BinopMatcher m(node);
2193 Node* const zero = jsgraph()->Int32Constant(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002194 Node* const minus_one = jsgraph()->Int32Constant(-1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002195 Node* const lhs = m.left().node();
2196 Node* const rhs = m.right().node();
2197
2198 if (m.right().Is(-1)) {
2199 return graph()->NewNode(machine()->Int32Sub(), zero, lhs);
2200 } else if (m.right().Is(0)) {
2201 return rhs;
2202 } else if (machine()->Int32DivIsSafe() || m.right().HasValue()) {
2203 return graph()->NewNode(machine()->Int32Div(), lhs, rhs, graph()->start());
2204 }
2205
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002206 // General case for signed integer division.
2207 //
2208 // if 0 < rhs then
2209 // lhs / rhs
2210 // else
2211 // if rhs < -1 then
2212 // lhs / rhs
2213 // else if rhs == 0 then
2214 // 0
2215 // else
2216 // 0 - lhs
2217 //
2218 // Note: We do not use the Diamond helper class here, because it really hurts
2219 // readability with nested diamonds.
2220 const Operator* const merge_op = common()->Merge(2);
2221 const Operator* const phi_op =
2222 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002223
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002224 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
2225 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
2226 graph()->start());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002227
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002228 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2229 Node* true0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true0);
2230
2231 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2232 Node* false0;
2233 {
2234 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
2235 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
2236
2237 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2238 Node* true1 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true1);
2239
2240 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2241 Node* false1;
2242 {
2243 Node* check2 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
2244 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1);
2245
2246 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
2247 Node* true2 = zero;
2248
2249 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
2250 Node* false2 = graph()->NewNode(machine()->Int32Sub(), zero, lhs);
2251
2252 if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
2253 false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
2254 }
2255
2256 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
2257 false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
2258 }
2259
2260 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
2261 return graph()->NewNode(phi_op, true0, false0, merge0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002262}
2263
2264
2265Node* SimplifiedLowering::Int32Mod(Node* const node) {
2266 Int32BinopMatcher m(node);
2267 Node* const zero = jsgraph()->Int32Constant(0);
2268 Node* const minus_one = jsgraph()->Int32Constant(-1);
2269 Node* const lhs = m.left().node();
2270 Node* const rhs = m.right().node();
2271
2272 if (m.right().Is(-1) || m.right().Is(0)) {
2273 return zero;
2274 } else if (m.right().HasValue()) {
2275 return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start());
2276 }
2277
2278 // General case for signed integer modulus, with optimization for (unknown)
2279 // power of 2 right hand side.
2280 //
2281 // if 0 < rhs then
2282 // msk = rhs - 1
2283 // if rhs & msk != 0 then
2284 // lhs % rhs
2285 // else
2286 // if lhs < 0 then
2287 // -(-lhs & msk)
2288 // else
2289 // lhs & msk
2290 // else
2291 // if rhs < -1 then
2292 // lhs % rhs
2293 // else
2294 // zero
2295 //
2296 // Note: We do not use the Diamond helper class here, because it really hurts
2297 // readability with nested diamonds.
2298 const Operator* const merge_op = common()->Merge(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002299 const Operator* const phi_op =
2300 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002301
2302 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
2303 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
2304 graph()->start());
2305
2306 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2307 Node* true0;
2308 {
2309 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
2310
2311 Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
2312 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
2313
2314 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2315 Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
2316
2317 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2318 Node* false1;
2319 {
2320 Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero);
2321 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2322 check2, if_false1);
2323
2324 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
2325 Node* true2 = graph()->NewNode(
2326 machine()->Int32Sub(), zero,
2327 graph()->NewNode(machine()->Word32And(),
2328 graph()->NewNode(machine()->Int32Sub(), zero, lhs),
2329 msk));
2330
2331 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
2332 Node* false2 = graph()->NewNode(machine()->Word32And(), lhs, msk);
2333
2334 if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
2335 false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
2336 }
2337
2338 if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
2339 true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
2340 }
2341
2342 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2343 Node* false0;
2344 {
2345 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
2346 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
2347 check1, if_false0);
2348
2349 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2350 Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
2351
2352 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2353 Node* false1 = zero;
2354
2355 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
2356 false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
2357 }
2358
2359 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
2360 return graph()->NewNode(phi_op, true0, false0, merge0);
2361}
2362
2363
2364Node* SimplifiedLowering::Uint32Div(Node* const node) {
2365 Uint32BinopMatcher m(node);
2366 Node* const zero = jsgraph()->Uint32Constant(0);
2367 Node* const lhs = m.left().node();
2368 Node* const rhs = m.right().node();
2369
2370 if (m.right().Is(0)) {
2371 return zero;
2372 } else if (machine()->Uint32DivIsSafe() || m.right().HasValue()) {
2373 return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start());
2374 }
2375
2376 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
2377 Diamond d(graph(), common(), check, BranchHint::kFalse);
2378 Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002379 return d.Phi(MachineRepresentation::kWord32, zero, div);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002380}
2381
2382
2383Node* SimplifiedLowering::Uint32Mod(Node* const node) {
2384 Uint32BinopMatcher m(node);
2385 Node* const minus_one = jsgraph()->Int32Constant(-1);
2386 Node* const zero = jsgraph()->Uint32Constant(0);
2387 Node* const lhs = m.left().node();
2388 Node* const rhs = m.right().node();
2389
2390 if (m.right().Is(0)) {
2391 return zero;
2392 } else if (m.right().HasValue()) {
2393 return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start());
2394 }
2395
2396 // General case for unsigned integer modulus, with optimization for (unknown)
2397 // power of 2 right hand side.
2398 //
2399 // if rhs then
2400 // msk = rhs - 1
2401 // if rhs & msk != 0 then
2402 // lhs % rhs
2403 // else
2404 // lhs & msk
2405 // else
2406 // zero
2407 //
2408 // Note: We do not use the Diamond helper class here, because it really hurts
2409 // readability with nested diamonds.
2410 const Operator* const merge_op = common()->Merge(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002411 const Operator* const phi_op =
2412 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002413
2414 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), rhs,
2415 graph()->start());
2416
2417 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2418 Node* true0;
2419 {
2420 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
2421
2422 Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
2423 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
2424
2425 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2426 Node* true1 = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_true1);
2427
2428 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2429 Node* false1 = graph()->NewNode(machine()->Word32And(), lhs, msk);
2430
2431 if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
2432 true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
2433 }
2434
2435 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2436 Node* false0 = zero;
2437
2438 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
2439 return graph()->NewNode(phi_op, true0, false0, merge0);
2440}
2441
2442
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002443void SimplifiedLowering::DoShift(Node* node, Operator const* op,
2444 Type* rhs_type) {
2445 Node* const rhs = NodeProperties::GetValueInput(node, 1);
2446 if (!rhs_type->Is(type_cache_.kZeroToThirtyOne)) {
2447 node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs,
2448 jsgraph()->Int32Constant(0x1f)));
2449 }
2450 NodeProperties::ChangeOp(node, op);
2451}
2452
Ben Murdochc5610432016-08-08 18:44:38 +01002453Node* SimplifiedLowering::ToNumberCode() {
2454 if (!to_number_code_.is_set()) {
2455 Callable callable = CodeFactory::ToNumber(isolate());
2456 to_number_code_.set(jsgraph()->HeapConstant(callable.code()));
2457 }
2458 return to_number_code_.get();
2459}
2460
2461Operator const* SimplifiedLowering::ToNumberOperator() {
2462 if (!to_number_operator_.is_set()) {
2463 Callable callable = CodeFactory::ToNumber(isolate());
2464 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
2465 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
2466 isolate(), graph()->zone(), callable.descriptor(), 0, flags,
2467 Operator::kNoProperties);
2468 to_number_operator_.set(common()->Call(desc));
2469 }
2470 return to_number_operator_.get();
2471}
2472
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002473} // namespace compiler
2474} // namespace internal
2475} // namespace v8