OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "src/address-map.h" | 9 #include "src/address-map.h" |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
11 #include "src/code-factory.h" | 11 #include "src/code-factory.h" |
12 #include "src/compiler/access-builder.h" | 12 #include "src/compiler/access-builder.h" |
13 #include "src/compiler/common-operator.h" | 13 #include "src/compiler/common-operator.h" |
14 #include "src/compiler/diamond.h" | 14 #include "src/compiler/diamond.h" |
15 #include "src/compiler/linkage.h" | 15 #include "src/compiler/linkage.h" |
16 #include "src/compiler/node-matchers.h" | 16 #include "src/compiler/node-matchers.h" |
17 #include "src/compiler/node-properties.h" | 17 #include "src/compiler/node-properties.h" |
| 18 #include "src/compiler/operation-typer.h" |
18 #include "src/compiler/operator-properties.h" | 19 #include "src/compiler/operator-properties.h" |
19 #include "src/compiler/representation-change.h" | 20 #include "src/compiler/representation-change.h" |
20 #include "src/compiler/simplified-operator.h" | 21 #include "src/compiler/simplified-operator.h" |
21 #include "src/compiler/source-position.h" | 22 #include "src/compiler/source-position.h" |
22 #include "src/conversions-inl.h" | 23 #include "src/conversions-inl.h" |
23 #include "src/objects.h" | 24 #include "src/objects.h" |
24 #include "src/type-cache.h" | 25 #include "src/type-cache.h" |
25 | 26 |
26 namespace v8 { | 27 namespace v8 { |
27 namespace internal { | 28 namespace internal { |
(...skipping 27 matching lines...) Expand all Loading... |
55 // removing some (redundant) nodes. | 56 // removing some (redundant) nodes. |
56 // During this phase, use the {RepresentationChanger} to insert | 57 // During this phase, use the {RepresentationChanger} to insert |
57 // representation changes between uses that demand a particular | 58 // representation changes between uses that demand a particular |
58 // representation and nodes that produce a different representation. | 59 // representation and nodes that produce a different representation. |
59 LOWER | 60 LOWER |
60 }; | 61 }; |
61 | 62 |
62 | 63 |
63 namespace { | 64 namespace { |
64 | 65 |
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. | |
77 class 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 } | |
90 static UseInfo TruncatingFloat32() { | |
91 return UseInfo(MachineRepresentation::kFloat32, Truncation::Float32()); | |
92 } | |
93 static UseInfo TruncatingFloat64() { | |
94 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 } | |
110 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 | 66 |
123 UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) { | 67 UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) { |
124 switch (rep) { | 68 switch (rep) { |
125 case MachineRepresentation::kTagged: | 69 case MachineRepresentation::kTagged: |
126 return UseInfo::AnyTagged(); | 70 return UseInfo::AnyTagged(); |
127 case MachineRepresentation::kFloat64: | 71 case MachineRepresentation::kFloat64: |
128 return UseInfo::TruncatingFloat64(); | 72 return UseInfo::TruncatingFloat64(); |
129 case MachineRepresentation::kFloat32: | 73 case MachineRepresentation::kFloat32: |
130 return UseInfo::TruncatingFloat32(); | 74 return UseInfo::TruncatingFloat32(); |
131 case MachineRepresentation::kWord64: | 75 case MachineRepresentation::kWord64: |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 // Check that the new use informatin is a super-type of the old | 160 // Check that the new use informatin is a super-type of the old |
217 // one. | 161 // one. |
218 CHECK(IsUseLessGeneral(input_use_infos_[index], use_info)); | 162 CHECK(IsUseLessGeneral(input_use_infos_[index], use_info)); |
219 input_use_infos_[index] = use_info; | 163 input_use_infos_[index] = use_info; |
220 } | 164 } |
221 | 165 |
222 private: | 166 private: |
223 ZoneVector<UseInfo> input_use_infos_; | 167 ZoneVector<UseInfo> input_use_infos_; |
224 | 168 |
225 static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) { | 169 static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) { |
226 return MachineRepresentationIsSubtype(use1.preferred(), use2.preferred()) && | 170 return MachineRepresentationIsSubtype(use1.representation(), |
| 171 use2.representation()) && |
227 use1.truncation().IsLessGeneralThan(use2.truncation()); | 172 use1.truncation().IsLessGeneralThan(use2.truncation()); |
228 } | 173 } |
229 }; | 174 }; |
230 | 175 |
231 #endif // DEBUG | 176 #endif // DEBUG |
232 | 177 |
233 } // namespace | 178 } // namespace |
234 | 179 |
235 | 180 |
236 class RepresentationSelector { | 181 class RepresentationSelector { |
237 public: | 182 public: |
238 // Information for each node tracked during the fixpoint. | 183 // Information for each node tracked during the fixpoint. |
239 class NodeInfo { | 184 class NodeInfo { |
240 public: | 185 public: |
241 // Adds new use to the node. Returns true if something has changed | 186 // Adds new use to the node. Returns true if something has changed |
242 // and the node has to be requeued. | 187 // and the node has to be requeued. |
243 bool AddUse(UseInfo info) { | 188 bool AddUse(UseInfo info) { |
244 Truncation old_truncation = truncation_; | 189 Truncation old_truncation = truncation_; |
245 truncation_ = Truncation::Generalize(truncation_, info.truncation()); | 190 truncation_ = Truncation::Generalize(truncation_, info.truncation()); |
246 return truncation_ != old_truncation; | 191 return truncation_ != old_truncation; |
247 } | 192 } |
248 | 193 |
249 void set_queued(bool value) { queued_ = value; } | 194 void set_queued() { state_ = kQueued; } |
250 bool queued() const { return queued_; } | 195 void set_visited() { state_ = kVisited; } |
251 void set_visited() { visited_ = true; } | 196 void set_pushed() { state_ = kPushed; } |
252 bool visited() const { return visited_; } | 197 void reset_state() { state_ = kUnvisited; } |
| 198 bool visited() const { return state_ == kVisited; } |
| 199 bool queued() const { return state_ == kQueued; } |
| 200 bool unvisited() const { return state_ == kUnvisited; } |
253 Truncation truncation() const { return truncation_; } | 201 Truncation truncation() const { return truncation_; } |
254 void set_output(MachineRepresentation output) { representation_ = output; } | 202 void set_output(MachineRepresentation output) { representation_ = output; } |
255 | 203 |
256 MachineRepresentation representation() const { return representation_; } | 204 MachineRepresentation representation() const { return representation_; } |
257 | 205 |
| 206 // Helpers for feedback typing. |
| 207 void set_feedback_type(Type* type) { feedback_type_ = type; } |
| 208 Type* feedback_type() { return feedback_type_; } |
| 209 void set_weakened() { weakened_ = true; } |
| 210 bool weakened() { return weakened_; } |
| 211 TypeCheckKind type_check() { return type_check_; } |
| 212 void set_type_check(TypeCheckKind type_check) { type_check_ = type_check; } |
| 213 |
258 private: | 214 private: |
259 bool queued_ = false; // Bookkeeping for the traversal. | 215 enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued }; |
260 bool visited_ = false; // Bookkeeping for the traversal. | 216 State state_ = kUnvisited; |
261 MachineRepresentation representation_ = | 217 MachineRepresentation representation_ = |
262 MachineRepresentation::kNone; // Output representation. | 218 MachineRepresentation::kNone; // Output representation. |
263 Truncation truncation_ = Truncation::None(); // Information about uses. | 219 Truncation truncation_ = Truncation::None(); // Information about uses. |
| 220 TypeCheckKind type_check_ = TypeCheckKind::kNone; // Runtime check kind. |
| 221 |
| 222 Type* feedback_type_ = nullptr; |
| 223 bool weakened_ = false; |
264 }; | 224 }; |
265 | 225 |
266 RepresentationSelector(JSGraph* jsgraph, Zone* zone, | 226 RepresentationSelector(JSGraph* jsgraph, Zone* zone, |
267 RepresentationChanger* changer, | 227 RepresentationChanger* changer, |
268 SourcePositionTable* source_positions) | 228 SourcePositionTable* source_positions) |
269 : jsgraph_(jsgraph), | 229 : jsgraph_(jsgraph), |
| 230 zone_(zone), |
270 count_(jsgraph->graph()->NodeCount()), | 231 count_(jsgraph->graph()->NodeCount()), |
271 info_(count_, zone), | 232 info_(count_, zone), |
272 #ifdef DEBUG | 233 #ifdef DEBUG |
273 node_input_use_infos_(count_, InputUseInfos(zone), zone), | 234 node_input_use_infos_(count_, InputUseInfos(zone), zone), |
274 #endif | 235 #endif |
275 nodes_(zone), | 236 nodes_(zone), |
276 replacements_(zone), | 237 replacements_(zone), |
277 phase_(PROPAGATE), | 238 phase_(PROPAGATE), |
278 changer_(changer), | 239 changer_(changer), |
279 queue_(zone), | 240 queue_(zone), |
| 241 typing_stack_(zone), |
280 source_positions_(source_positions), | 242 source_positions_(source_positions), |
281 type_cache_(TypeCache::Get()) { | 243 type_cache_(TypeCache::Get()), |
282 } | 244 op_typer_(jsgraph->isolate(), graph_zone()) { |
283 | 245 } |
284 void Run(SimplifiedLowering* lowering) { | 246 |
| 247 // Forward propagation of types from type feedback. |
| 248 void RunTypePropagationPhase() { |
| 249 DCHECK(typing_stack_.empty()); |
| 250 |
| 251 typing_stack_.push({graph()->end(), 0}); |
| 252 GetInfo(graph()->end())->set_pushed(); |
| 253 while (!typing_stack_.empty()) { |
| 254 NodeState& current = typing_stack_.top(); |
| 255 |
| 256 // If there is an unvisited input, push it and continue. |
| 257 bool pushed_unvisited = false; |
| 258 while (current.input_index < current.node->InputCount()) { |
| 259 Node* input = current.node->InputAt(current.input_index); |
| 260 NodeInfo* input_info = GetInfo(input); |
| 261 current.input_index++; |
| 262 if (input_info->unvisited()) { |
| 263 input_info->set_pushed(); |
| 264 typing_stack_.push({input, 0}); |
| 265 pushed_unvisited = true; |
| 266 break; |
| 267 } |
| 268 } |
| 269 if (pushed_unvisited) continue; |
| 270 |
| 271 // Process the top of the stack. |
| 272 Node* node = current.node; |
| 273 typing_stack_.pop(); |
| 274 NodeInfo* info = GetInfo(node); |
| 275 info->set_visited(); |
| 276 bool updated = UpdateFeedbackType(node); |
| 277 if (updated) { |
| 278 for (Node* const user : node->uses()) { |
| 279 if (GetInfo(user)->visited()) { |
| 280 GetInfo(user)->set_queued(); |
| 281 queue_.push(user); |
| 282 } |
| 283 } |
| 284 } |
| 285 } |
| 286 |
| 287 // Process the revisit queue. |
| 288 while (!queue_.empty()) { |
| 289 Node* node = queue_.front(); |
| 290 queue_.pop(); |
| 291 NodeInfo* info = GetInfo(node); |
| 292 info->set_visited(); |
| 293 bool updated = UpdateFeedbackType(node); |
| 294 if (updated) { |
| 295 for (Node* const user : node->uses()) { |
| 296 if (GetInfo(user)->visited()) { |
| 297 GetInfo(user)->set_queued(); |
| 298 queue_.push(user); |
| 299 } |
| 300 } |
| 301 } |
| 302 } |
| 303 } |
| 304 |
| 305 void ResetNodeInfoState() { |
| 306 // Clean up for the next phase. |
| 307 for (NodeInfo& info : info_) { |
| 308 info.reset_state(); |
| 309 } |
| 310 } |
| 311 |
| 312 Type* TypeOf(Node* node) { |
| 313 Type* type = GetInfo(node)->feedback_type(); |
| 314 return type == nullptr ? NodeProperties::GetType(node) : type; |
| 315 } |
| 316 |
| 317 Type* FeedbackTypeOf(Node* node) { |
| 318 Type* type = GetInfo(node)->feedback_type(); |
| 319 return type == nullptr ? Type::None() : type; |
| 320 } |
| 321 |
| 322 Type* TypePhi(Node* node) { |
| 323 int arity = node->op()->ValueInputCount(); |
| 324 Type* type = FeedbackTypeOf(node->InputAt(0)); |
| 325 for (int i = 1; i < arity; ++i) { |
| 326 type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i))); |
| 327 } |
| 328 return type; |
| 329 } |
| 330 |
| 331 Type* TypeSelect(Node* node) { |
| 332 return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)), |
| 333 FeedbackTypeOf(node->InputAt(2))); |
| 334 } |
| 335 |
| 336 static Type* TypeOfSpeculativeOp(TypeCheckKind type_check) { |
| 337 switch (type_check) { |
| 338 case TypeCheckKind::kNone: |
| 339 return Type::Any(); |
| 340 case TypeCheckKind::kSigned32: |
| 341 return Type::Signed32(); |
| 342 case TypeCheckKind::kNumber: |
| 343 return Type::Number(); |
| 344 // Unexpected cases. |
| 345 case TypeCheckKind::kNumberOrUndefined: |
| 346 FATAL("Unexpected checked type."); |
| 347 break; |
| 348 } |
| 349 UNREACHABLE(); |
| 350 return nullptr; |
| 351 } |
| 352 |
| 353 bool UpdateFeedbackType(Node* node) { |
| 354 if (node->op()->ValueOutputCount() == 0) return false; |
| 355 |
| 356 NodeInfo* info = GetInfo(node); |
| 357 Type* type = info->feedback_type(); |
| 358 Type* new_type = type; |
| 359 |
| 360 switch (node->opcode()) { |
| 361 case IrOpcode::kSpeculativeNumberAdd: { |
| 362 Type* lhs = FeedbackTypeOf(node->InputAt(0)); |
| 363 Type* rhs = FeedbackTypeOf(node->InputAt(1)); |
| 364 if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false; |
| 365 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 366 // e.g. it will treat true as 1 even though the number check will |
| 367 // fail on a boolean. OperationTyper should have a function that |
| 368 // computes a more precise type. |
| 369 lhs = op_typer_.ToNumber(lhs); |
| 370 rhs = op_typer_.ToNumber(rhs); |
| 371 Type* static_type = op_typer_.NumericAdd(lhs, rhs); |
| 372 if (info->type_check() == TypeCheckKind::kNone) { |
| 373 new_type = static_type; |
| 374 } else { |
| 375 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
| 376 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
| 377 } |
| 378 break; |
| 379 } |
| 380 |
| 381 case IrOpcode::kSpeculativeNumberSubtract: { |
| 382 Type* lhs = FeedbackTypeOf(node->InputAt(0)); |
| 383 Type* rhs = FeedbackTypeOf(node->InputAt(1)); |
| 384 if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false; |
| 385 // TODO(jarin) The ToNumber conversion is too conservative here, |
| 386 // e.g. it will treat true as 1 even though the number check will |
| 387 // fail on a boolean. OperationTyper should have a function that |
| 388 // computes a more precise type. |
| 389 lhs = op_typer_.ToNumber(lhs); |
| 390 rhs = op_typer_.ToNumber(rhs); |
| 391 Type* static_type = op_typer_.NumericSubtract(lhs, rhs); |
| 392 if (info->type_check() == TypeCheckKind::kNone) { |
| 393 new_type = static_type; |
| 394 } else { |
| 395 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
| 396 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
| 397 } |
| 398 break; |
| 399 } |
| 400 |
| 401 case IrOpcode::kPhi: { |
| 402 new_type = TypePhi(node); |
| 403 if (type != nullptr) { |
| 404 new_type = Weaken(node, type, new_type); |
| 405 } |
| 406 // Recompute the phi representation based on the new type. |
| 407 MachineRepresentation output = |
| 408 GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type); |
| 409 ResetOutput(node, output); |
| 410 break; |
| 411 } |
| 412 |
| 413 case IrOpcode::kSelect: { |
| 414 new_type = TypeSelect(node); |
| 415 // Recompute representation based on the new type. |
| 416 MachineRepresentation output = |
| 417 GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type); |
| 418 ResetOutput(node, output); |
| 419 break; |
| 420 } |
| 421 |
| 422 default: |
| 423 // Shortcut for operations that we do not handle. |
| 424 if (type == nullptr) { |
| 425 GetInfo(node)->set_feedback_type(NodeProperties::GetType(node)); |
| 426 return true; |
| 427 } |
| 428 return false; |
| 429 } |
| 430 if (type != nullptr && new_type->Is(type)) return false; |
| 431 GetInfo(node)->set_feedback_type(new_type); |
| 432 if (FLAG_trace_representation) { |
| 433 PrintNodeFeedbackType(node); |
| 434 } |
| 435 return true; |
| 436 } |
| 437 |
| 438 void PrintNodeFeedbackType(Node* n) { |
| 439 OFStream os(stdout); |
| 440 os << "#" << n->id() << ":" << *n->op() << "("; |
| 441 int j = 0; |
| 442 for (Node* const i : n->inputs()) { |
| 443 if (j++ > 0) os << ", "; |
| 444 os << "#" << i->id() << ":" << i->op()->mnemonic(); |
| 445 } |
| 446 os << ")"; |
| 447 if (NodeProperties::IsTyped(n)) { |
| 448 os << " [Static type: "; |
| 449 Type* static_type = NodeProperties::GetType(n); |
| 450 static_type->PrintTo(os); |
| 451 Type* feedback_type = GetInfo(n)->feedback_type(); |
| 452 if (feedback_type != nullptr && feedback_type != static_type) { |
| 453 os << ", Feedback type: "; |
| 454 feedback_type->PrintTo(os); |
| 455 } |
| 456 os << "]"; |
| 457 } |
| 458 os << std::endl; |
| 459 } |
| 460 |
| 461 Type* Weaken(Node* node, Type* previous_type, Type* current_type) { |
| 462 // If the types have nothing to do with integers, return the types. |
| 463 Type* const integer = type_cache_.kInteger; |
| 464 if (!previous_type->Maybe(integer)) { |
| 465 return current_type; |
| 466 } |
| 467 DCHECK(current_type->Maybe(integer)); |
| 468 |
| 469 Type* current_integer = |
| 470 Type::Intersect(current_type, integer, graph_zone()); |
| 471 Type* previous_integer = |
| 472 Type::Intersect(previous_type, integer, graph_zone()); |
| 473 |
| 474 // Once we start weakening a node, we should always weaken. |
| 475 if (!GetInfo(node)->weakened()) { |
| 476 // Only weaken if there is range involved; we should converge quickly |
| 477 // for all other types (the exception is a union of many constants, |
| 478 // but we currently do not increase the number of constants in unions). |
| 479 Type* previous = previous_integer->GetRange(); |
| 480 Type* current = current_integer->GetRange(); |
| 481 if (current == nullptr || previous == nullptr) { |
| 482 return current_type; |
| 483 } |
| 484 // Range is involved => we are weakening. |
| 485 GetInfo(node)->set_weakened(); |
| 486 } |
| 487 |
| 488 return Type::Union(current_type, |
| 489 op_typer_.WeakenRange(previous_integer, current_integer), |
| 490 graph_zone()); |
| 491 } |
| 492 |
| 493 // Backward propagation of truncations. |
| 494 void RunTruncationPropagationPhase() { |
285 // Run propagation phase to a fixpoint. | 495 // Run propagation phase to a fixpoint. |
286 TRACE("--{Propagation phase}--\n"); | 496 TRACE("--{Propagation phase}--\n"); |
287 phase_ = PROPAGATE; | 497 phase_ = PROPAGATE; |
288 EnqueueInitial(jsgraph_->graph()->end()); | 498 EnqueueInitial(jsgraph_->graph()->end()); |
289 // Process nodes from the queue until it is empty. | 499 // Process nodes from the queue until it is empty. |
290 while (!queue_.empty()) { | 500 while (!queue_.empty()) { |
291 Node* node = queue_.front(); | 501 Node* node = queue_.front(); |
292 NodeInfo* info = GetInfo(node); | 502 NodeInfo* info = GetInfo(node); |
293 queue_.pop(); | 503 queue_.pop(); |
294 info->set_queued(false); | 504 info->set_visited(); |
295 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); | 505 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); |
296 VisitNode(node, info->truncation(), nullptr); | 506 VisitNode(node, info->truncation(), nullptr); |
297 TRACE(" ==> output "); | 507 TRACE(" ==> output "); |
298 PrintOutputInfo(info); | 508 PrintOutputInfo(info); |
299 TRACE("\n"); | 509 TRACE("\n"); |
300 } | 510 } |
| 511 } |
| 512 |
| 513 void Run(SimplifiedLowering* lowering) { |
| 514 RunTruncationPropagationPhase(); |
| 515 |
| 516 if (lowering->flags() & SimplifiedLowering::kTypeFeedbackEnabled) { |
| 517 ResetNodeInfoState(); |
| 518 RunTypePropagationPhase(); |
| 519 } |
301 | 520 |
302 // Run lowering and change insertion phase. | 521 // Run lowering and change insertion phase. |
303 TRACE("--{Simplified lowering phase}--\n"); | 522 TRACE("--{Simplified lowering phase}--\n"); |
304 phase_ = LOWER; | 523 phase_ = LOWER; |
305 // Process nodes from the collected {nodes_} vector. | 524 // Process nodes from the collected {nodes_} vector. |
306 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) { | 525 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) { |
307 Node* node = *i; | 526 Node* node = *i; |
308 NodeInfo* info = GetInfo(node); | 527 NodeInfo* info = GetInfo(node); |
309 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); | 528 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); |
310 // Reuse {VisitNode()} so the representation rules are in one place. | 529 // Reuse {VisitNode()} so the representation rules are in one place. |
311 SourcePositionTable::Scope scope( | 530 SourcePositionTable::Scope scope( |
312 source_positions_, source_positions_->GetSourcePosition(node)); | 531 source_positions_, source_positions_->GetSourcePosition(node)); |
313 VisitNode(node, info->truncation(), lowering); | 532 VisitNode(node, info->truncation(), lowering); |
314 } | 533 } |
315 | 534 |
316 // Perform the final replacements. | 535 // Perform the final replacements. |
317 for (NodeVector::iterator i = replacements_.begin(); | 536 for (NodeVector::iterator i = replacements_.begin(); |
318 i != replacements_.end(); ++i) { | 537 i != replacements_.end(); ++i) { |
319 Node* node = *i; | 538 Node* node = *i; |
320 Node* replacement = *(++i); | 539 Node* replacement = *(++i); |
321 node->ReplaceUses(replacement); | 540 node->ReplaceUses(replacement); |
| 541 node->Kill(); |
322 // We also need to replace the node in the rest of the vector. | 542 // We also need to replace the node in the rest of the vector. |
323 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) { | 543 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) { |
324 ++j; | 544 ++j; |
325 if (*j == node) *j = replacement; | 545 if (*j == node) *j = replacement; |
326 } | 546 } |
327 } | 547 } |
328 } | 548 } |
329 | 549 |
330 void EnqueueInitial(Node* node) { | 550 void EnqueueInitial(Node* node) { |
331 NodeInfo* info = GetInfo(node); | 551 NodeInfo* info = GetInfo(node); |
332 info->set_visited(); | 552 info->set_queued(); |
333 info->set_queued(true); | |
334 nodes_.push_back(node); | 553 nodes_.push_back(node); |
335 queue_.push(node); | 554 queue_.push(node); |
336 } | 555 } |
337 | 556 |
338 // Enqueue {use_node}'s {index} input if the {use} contains new information | 557 // 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 | 558 // for that input node. Add the input to {nodes_} if this is the first time |
340 // it's been visited. | 559 // it's been visited. |
341 void EnqueueInput(Node* use_node, int index, | 560 void EnqueueInput(Node* use_node, int index, |
342 UseInfo use_info = UseInfo::None()) { | 561 UseInfo use_info = UseInfo::None()) { |
343 Node* node = use_node->InputAt(index); | 562 Node* node = use_node->InputAt(index); |
344 if (phase_ != PROPAGATE) return; | 563 if (phase_ != PROPAGATE) return; |
345 NodeInfo* info = GetInfo(node); | 564 NodeInfo* info = GetInfo(node); |
346 #ifdef DEBUG | 565 #ifdef DEBUG |
347 // Check monotonicity of input requirements. | 566 // Check monotonicity of input requirements. |
348 node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index, | 567 node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index, |
349 use_info); | 568 use_info); |
350 #endif // DEBUG | 569 #endif // DEBUG |
351 if (!info->visited()) { | 570 if (info->unvisited()) { |
352 // First visit of this node. | 571 // First visit of this node. |
353 info->set_visited(); | 572 info->set_queued(); |
354 info->set_queued(true); | |
355 nodes_.push_back(node); | 573 nodes_.push_back(node); |
356 queue_.push(node); | 574 queue_.push(node); |
357 TRACE(" initial: "); | 575 TRACE(" initial: "); |
358 info->AddUse(use_info); | 576 info->AddUse(use_info); |
359 PrintTruncation(info->truncation()); | 577 PrintTruncation(info->truncation()); |
360 return; | 578 return; |
361 } | 579 } |
362 TRACE(" queue?: "); | 580 TRACE(" queue?: "); |
363 PrintTruncation(info->truncation()); | 581 PrintTruncation(info->truncation()); |
364 if (info->AddUse(use_info)) { | 582 if (info->AddUse(use_info)) { |
365 // New usage information for the node is available. | 583 // New usage information for the node is available. |
366 if (!info->queued()) { | 584 if (!info->queued()) { |
367 queue_.push(node); | 585 queue_.push(node); |
368 info->set_queued(true); | 586 info->set_queued(); |
369 TRACE(" added: "); | 587 TRACE(" added: "); |
370 } else { | 588 } else { |
371 TRACE(" inqueue: "); | 589 TRACE(" inqueue: "); |
372 } | 590 } |
373 PrintTruncation(info->truncation()); | 591 PrintTruncation(info->truncation()); |
374 } | 592 } |
375 } | 593 } |
376 | 594 |
377 bool lower() { return phase_ == LOWER; } | 595 bool lower() { return phase_ == LOWER; } |
| 596 bool propagate() { return phase_ == PROPAGATE; } |
378 | 597 |
379 void EnqueueUses(Node* node) { | 598 void SetOutput(Node* node, MachineRepresentation representation, |
380 for (Edge edge : node->use_edges()) { | 599 TypeCheckKind type_check = TypeCheckKind::kNone) { |
381 if (NodeProperties::IsValueEdge(edge)) { | 600 DCHECK(MachineRepresentationIsSubtype(GetInfo(node)->representation(), |
382 Node* const user = edge.from(); | 601 representation)); |
383 if (user->id() < count_) { | 602 ResetOutput(node, representation, type_check); |
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 } | |
393 } | |
394 } | |
395 } | 603 } |
396 | 604 |
397 void SetOutput(Node* node, MachineRepresentation representation) { | 605 void ResetOutput(Node* node, MachineRepresentation representation, |
| 606 TypeCheckKind type_check = TypeCheckKind::kNone) { |
398 NodeInfo* info = GetInfo(node); | 607 NodeInfo* info = GetInfo(node); |
399 DCHECK( | |
400 MachineRepresentationIsSubtype(info->representation(), representation)); | |
401 info->set_output(representation); | 608 info->set_output(representation); |
| 609 info->set_type_check(type_check); |
402 } | 610 } |
403 | 611 |
404 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); } | 612 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); } |
405 | 613 |
406 bool BothInputsAreSigned32(Node* node) { | 614 bool BothInputsAreSigned32(Node* node) { |
407 DCHECK_EQ(2, node->InputCount()); | 615 DCHECK_EQ(2, node->InputCount()); |
408 return GetUpperBound(node->InputAt(0))->Is(Type::Signed32()) && | 616 return GetUpperBound(node->InputAt(0))->Is(Type::Signed32()) && |
409 GetUpperBound(node->InputAt(1))->Is(Type::Signed32()); | 617 GetUpperBound(node->InputAt(1))->Is(Type::Signed32()); |
410 } | 618 } |
411 | 619 |
412 bool BothInputsAreUnsigned32(Node* node) { | 620 bool BothInputsAreUnsigned32(Node* node) { |
413 DCHECK_EQ(2, node->InputCount()); | 621 DCHECK_EQ(2, node->InputCount()); |
414 return GetUpperBound(node->InputAt(0))->Is(Type::Unsigned32()) && | 622 return GetUpperBound(node->InputAt(0))->Is(Type::Unsigned32()) && |
415 GetUpperBound(node->InputAt(1))->Is(Type::Unsigned32()); | 623 GetUpperBound(node->InputAt(1))->Is(Type::Unsigned32()); |
416 } | 624 } |
417 | 625 |
418 bool BothInputsAre(Node* node, Type* type) { | 626 bool BothInputsAre(Node* node, Type* type) { |
419 DCHECK_EQ(2, node->InputCount()); | 627 DCHECK_EQ(2, node->op()->ValueInputCount()); |
420 return GetUpperBound(node->InputAt(0))->Is(type) && | 628 return GetUpperBound(node->InputAt(0))->Is(type) && |
421 GetUpperBound(node->InputAt(1))->Is(type); | 629 GetUpperBound(node->InputAt(1))->Is(type); |
422 } | 630 } |
423 | 631 |
424 void ConvertInput(Node* node, int index, UseInfo use) { | 632 void ConvertInput(Node* node, int index, UseInfo use) { |
425 Node* input = node->InputAt(index); | 633 Node* input = node->InputAt(index); |
426 // In the change phase, insert a change before the use if necessary. | 634 // In the change phase, insert a change before the use if necessary. |
427 if (use.preferred() == MachineRepresentation::kNone) | 635 if (use.representation() == MachineRepresentation::kNone) |
428 return; // No input requirement on the use. | 636 return; // No input requirement on the use. |
429 NodeInfo* input_info = GetInfo(input); | 637 NodeInfo* input_info = GetInfo(input); |
430 MachineRepresentation input_rep = input_info->representation(); | 638 MachineRepresentation input_rep = input_info->representation(); |
431 if (input_rep != use.preferred()) { | 639 if (input_rep != use.representation() || |
| 640 use.type_check() != TypeCheckKind::kNone) { |
432 // Output representation doesn't match usage. | 641 // Output representation doesn't match usage. |
433 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(), | 642 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(), |
434 index, input->id(), input->op()->mnemonic()); | 643 index, input->id(), input->op()->mnemonic()); |
435 TRACE(" from "); | 644 TRACE(" from "); |
436 PrintOutputInfo(input_info); | 645 PrintOutputInfo(input_info); |
437 TRACE(" to "); | 646 TRACE(" to "); |
438 PrintUseInfo(use); | 647 PrintUseInfo(use); |
439 TRACE("\n"); | 648 TRACE("\n"); |
440 Node* n = changer_->GetRepresentationFor( | 649 Node* n = changer_->GetRepresentationFor( |
441 input, input_info->representation(), GetUpperBound(input), | 650 input, input_info->representation(), TypeOf(input), node, use); |
442 use.preferred(), use.truncation()); | |
443 node->ReplaceInput(index, n); | 651 node->ReplaceInput(index, n); |
444 } | 652 } |
445 } | 653 } |
446 | 654 |
447 void ProcessInput(Node* node, int index, UseInfo use) { | 655 void ProcessInput(Node* node, int index, UseInfo use) { |
448 if (phase_ == PROPAGATE) { | 656 if (phase_ == PROPAGATE) { |
449 EnqueueInput(node, index, use); | 657 EnqueueInput(node, index, use); |
450 } else { | 658 } else { |
451 ConvertInput(node, index, use); | 659 ConvertInput(node, index, use); |
452 } | 660 } |
(...skipping 24 matching lines...) Expand all Loading... |
477 ProcessInput(node, i, UseInfo::AnyTagged()); | 685 ProcessInput(node, i, UseInfo::AnyTagged()); |
478 } | 686 } |
479 // Only enqueue other inputs (framestates, effects, control). | 687 // Only enqueue other inputs (framestates, effects, control). |
480 for (int i = tagged_count; i < node->InputCount(); i++) { | 688 for (int i = tagged_count; i < node->InputCount(); i++) { |
481 EnqueueInput(node, i); | 689 EnqueueInput(node, i); |
482 } | 690 } |
483 } | 691 } |
484 | 692 |
485 // Helper for binops of the R x L -> O variety. | 693 // Helper for binops of the R x L -> O variety. |
486 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use, | 694 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use, |
487 MachineRepresentation output) { | 695 MachineRepresentation output, |
| 696 TypeCheckKind type_check = TypeCheckKind::kNone) { |
488 DCHECK_EQ(2, node->op()->ValueInputCount()); | 697 DCHECK_EQ(2, node->op()->ValueInputCount()); |
489 ProcessInput(node, 0, left_use); | 698 ProcessInput(node, 0, left_use); |
490 ProcessInput(node, 1, right_use); | 699 ProcessInput(node, 1, right_use); |
491 for (int i = 2; i < node->InputCount(); i++) { | 700 for (int i = 2; i < node->InputCount(); i++) { |
492 EnqueueInput(node, i); | 701 EnqueueInput(node, i); |
493 } | 702 } |
494 SetOutput(node, output); | 703 SetOutput(node, output, type_check); |
495 } | 704 } |
496 | 705 |
497 // Helper for binops of the I x I -> O variety. | 706 // Helper for binops of the I x I -> O variety. |
498 void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output) { | 707 void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output, |
499 VisitBinop(node, input_use, input_use, output); | 708 TypeCheckKind type_check = TypeCheckKind::kNone) { |
| 709 VisitBinop(node, input_use, input_use, output, type_check); |
500 } | 710 } |
501 | 711 |
502 // Helper for unops of the I -> O variety. | 712 // Helper for unops of the I -> O variety. |
503 void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) { | 713 void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) { |
504 DCHECK_EQ(1, node->InputCount()); | 714 DCHECK_EQ(1, node->InputCount()); |
505 ProcessInput(node, 0, input_use); | 715 ProcessInput(node, 0, input_use); |
506 SetOutput(node, output); | 716 SetOutput(node, output); |
507 } | 717 } |
508 | 718 |
509 // Helper for leaf nodes. | 719 // Helper for leaf nodes. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit); | 757 VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit); |
548 } | 758 } |
549 void VisitInt64Cmp(Node* node) { | 759 void VisitInt64Cmp(Node* node) { |
550 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit); | 760 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit); |
551 } | 761 } |
552 void VisitUint64Cmp(Node* node) { | 762 void VisitUint64Cmp(Node* node) { |
553 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit); | 763 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit); |
554 } | 764 } |
555 | 765 |
556 // Infer representation for phi-like nodes. | 766 // Infer representation for phi-like nodes. |
557 MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use) { | 767 MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use, |
| 768 Type* type = nullptr) { |
558 // Compute the representation. | 769 // Compute the representation. |
559 Type* type = GetUpperBound(node); | 770 if (type == nullptr) { |
| 771 type = TypeOf(node); |
| 772 } |
560 if (type->Is(Type::None())) { | 773 if (type->Is(Type::None())) { |
561 return MachineRepresentation::kNone; | 774 return MachineRepresentation::kNone; |
562 } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) { | 775 } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) { |
563 return MachineRepresentation::kWord32; | 776 return MachineRepresentation::kWord32; |
564 } else if (use.TruncatesToWord32()) { | 777 } else if (use.TruncatesToWord32()) { |
565 return MachineRepresentation::kWord32; | 778 return MachineRepresentation::kWord32; |
566 } else if (type->Is(Type::Boolean())) { | 779 } else if (type->Is(Type::Boolean())) { |
567 return MachineRepresentation::kBit; | 780 return MachineRepresentation::kBit; |
568 } else if (type->Is(Type::Number())) { | 781 } else if (type->Is(Type::Number())) { |
569 return MachineRepresentation::kFloat64; | 782 return MachineRepresentation::kFloat64; |
570 } else if (use.TruncatesToFloat64()) { | 783 } else if (use.TruncatesToFloat64()) { |
571 return MachineRepresentation::kFloat64; | 784 return MachineRepresentation::kFloat64; |
572 } else if (type->Is(Type::Internal())) { | 785 } else if (type->Is(Type::Internal())) { |
573 // We mark (u)int64 as Type::Internal. | 786 // We mark (u)int64 as Type::Internal. |
574 // TODO(jarin) This is a workaround for our lack of (u)int64 | 787 // TODO(jarin) This is a workaround for our lack of (u)int64 |
575 // types. This can be removed once we can represent (u)int64 | 788 // types. This can be removed once we can represent (u)int64 |
576 // unambiguously. (At the moment internal objects, such as the hole, | 789 // unambiguously. (At the moment internal objects, such as the hole, |
577 // are also Type::Internal()). | 790 // are also Type::Internal()). |
578 bool is_word64 = GetInfo(node->InputAt(0))->representation() == | 791 bool is_word64 = GetInfo(node->InputAt(0))->representation() == |
579 MachineRepresentation::kWord64; | 792 MachineRepresentation::kWord64; |
580 #ifdef DEBUG | 793 #ifdef DEBUG |
581 // Check that all the inputs agree on being Word64. | 794 // Check that all the inputs agree on being Word64. |
| 795 DCHECK_EQ(IrOpcode::kPhi, node->opcode()); // This only works for phis. |
582 for (int i = 1; i < node->op()->ValueInputCount(); i++) { | 796 for (int i = 1; i < node->op()->ValueInputCount(); i++) { |
583 DCHECK_EQ(is_word64, GetInfo(node->InputAt(i))->representation() == | 797 DCHECK_EQ(is_word64, GetInfo(node->InputAt(i))->representation() == |
584 MachineRepresentation::kWord64); | 798 MachineRepresentation::kWord64); |
585 } | 799 } |
586 #endif | 800 #endif |
587 return is_word64 ? MachineRepresentation::kWord64 | 801 return is_word64 ? MachineRepresentation::kWord64 |
588 : MachineRepresentation::kTagged; | 802 : MachineRepresentation::kTagged; |
589 } | 803 } |
590 return MachineRepresentation::kTagged; | 804 return MachineRepresentation::kTagged; |
591 } | 805 } |
(...skipping 18 matching lines...) Expand all Loading... |
610 // truncation truncation along. | 824 // truncation truncation along. |
611 UseInfo input_use(output, truncation); | 825 UseInfo input_use(output, truncation); |
612 ProcessInput(node, 1, input_use); | 826 ProcessInput(node, 1, input_use); |
613 ProcessInput(node, 2, input_use); | 827 ProcessInput(node, 2, input_use); |
614 } | 828 } |
615 | 829 |
616 // Helper for handling phis. | 830 // Helper for handling phis. |
617 void VisitPhi(Node* node, Truncation truncation, | 831 void VisitPhi(Node* node, Truncation truncation, |
618 SimplifiedLowering* lowering) { | 832 SimplifiedLowering* lowering) { |
619 MachineRepresentation output = GetOutputInfoForPhi(node, truncation); | 833 MachineRepresentation output = GetOutputInfoForPhi(node, truncation); |
| 834 // Only set the output representation if not running with type |
| 835 // feedback. (Feedback typing will set the representation.) |
620 SetOutput(node, output); | 836 SetOutput(node, output); |
621 | 837 |
622 int values = node->op()->ValueInputCount(); | 838 int values = node->op()->ValueInputCount(); |
623 if (lower()) { | 839 if (lower()) { |
624 // Update the phi operator. | 840 // Update the phi operator. |
625 if (output != PhiRepresentationOf(node->op())) { | 841 if (output != PhiRepresentationOf(node->op())) { |
626 NodeProperties::ChangeOp(node, lowering->common()->Phi(output, values)); | 842 NodeProperties::ChangeOp(node, lowering->common()->Phi(output, values)); |
627 } | 843 } |
628 } | 844 } |
629 | 845 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 } | 895 } |
680 } else { | 896 } else { |
681 Zone* zone = jsgraph_->zone(); | 897 Zone* zone = jsgraph_->zone(); |
682 ZoneVector<MachineType>* types = | 898 ZoneVector<MachineType>* types = |
683 new (zone->New(sizeof(ZoneVector<MachineType>))) | 899 new (zone->New(sizeof(ZoneVector<MachineType>))) |
684 ZoneVector<MachineType>(node->InputCount(), zone); | 900 ZoneVector<MachineType>(node->InputCount(), zone); |
685 for (int i = 0; i < node->InputCount(); i++) { | 901 for (int i = 0; i < node->InputCount(); i++) { |
686 Node* input = node->InputAt(i); | 902 Node* input = node->InputAt(i); |
687 NodeInfo* input_info = GetInfo(input); | 903 NodeInfo* input_info = GetInfo(input); |
688 MachineType machine_type(input_info->representation(), | 904 MachineType machine_type(input_info->representation(), |
689 DeoptValueSemanticOf(GetUpperBound(input))); | 905 DeoptValueSemanticOf(TypeOf(input))); |
690 DCHECK(machine_type.representation() != | 906 DCHECK(machine_type.representation() != |
691 MachineRepresentation::kWord32 || | 907 MachineRepresentation::kWord32 || |
692 machine_type.semantic() == MachineSemantic::kInt32 || | 908 machine_type.semantic() == MachineSemantic::kInt32 || |
693 machine_type.semantic() == MachineSemantic::kUint32); | 909 machine_type.semantic() == MachineSemantic::kUint32); |
694 (*types)[i] = machine_type; | 910 (*types)[i] = machine_type; |
695 } | 911 } |
696 NodeProperties::ChangeOp(node, | 912 NodeProperties::ChangeOp(node, |
697 jsgraph_->common()->TypedStateValues(types)); | 913 jsgraph_->common()->TypedStateValues(types)); |
698 } | 914 } |
699 SetOutput(node, MachineRepresentation::kTagged); | 915 SetOutput(node, MachineRepresentation::kTagged); |
700 } | 916 } |
701 | 917 |
702 const Operator* Int32Op(Node* node) { | 918 const Operator* Int32Op(Node* node) { |
703 return changer_->Int32OperatorFor(node->opcode()); | 919 return changer_->Int32OperatorFor(node->opcode()); |
704 } | 920 } |
705 | 921 |
| 922 const Operator* Int32OverflowOp(Node* node) { |
| 923 return changer_->Int32OverflowOperatorFor(node->opcode()); |
| 924 } |
| 925 |
706 const Operator* Uint32Op(Node* node) { | 926 const Operator* Uint32Op(Node* node) { |
707 return changer_->Uint32OperatorFor(node->opcode()); | 927 return changer_->Uint32OperatorFor(node->opcode()); |
708 } | 928 } |
709 | 929 |
710 const Operator* Float64Op(Node* node) { | 930 const Operator* Float64Op(Node* node) { |
711 return changer_->Float64OperatorFor(node->opcode()); | 931 return changer_->Float64OperatorFor(node->opcode()); |
712 } | 932 } |
713 | 933 |
714 WriteBarrierKind WriteBarrierKindFor( | 934 WriteBarrierKind WriteBarrierKindFor( |
715 BaseTaggedness base_taggedness, | 935 BaseTaggedness base_taggedness, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 MachineRepresentation field_representation, int field_offset, | 989 MachineRepresentation field_representation, int field_offset, |
770 Type* field_type, Node* value) { | 990 Type* field_type, Node* value) { |
771 if (base_taggedness == kTaggedBase && | 991 if (base_taggedness == kTaggedBase && |
772 field_offset == HeapObject::kMapOffset) { | 992 field_offset == HeapObject::kMapOffset) { |
773 return kMapWriteBarrier; | 993 return kMapWriteBarrier; |
774 } | 994 } |
775 return WriteBarrierKindFor(base_taggedness, field_representation, | 995 return WriteBarrierKindFor(base_taggedness, field_representation, |
776 field_type, value); | 996 field_type, value); |
777 } | 997 } |
778 | 998 |
| 999 Graph* graph() const { return jsgraph_->graph(); } |
| 1000 CommonOperatorBuilder* common() const { return jsgraph_->common(); } |
| 1001 SimplifiedOperatorBuilder* simplified() const { |
| 1002 return jsgraph_->simplified(); |
| 1003 } |
| 1004 |
| 1005 void ChangeToPureOp(Node* node, const Operator* new_op) { |
| 1006 // Disconnect the node from effect and control chains. |
| 1007 Node* control = NodeProperties::GetControlInput(node); |
| 1008 Node* effect = NodeProperties::GetEffectInput(node); |
| 1009 for (Edge edge : node->use_edges()) { |
| 1010 if (NodeProperties::IsControlEdge(edge)) { |
| 1011 edge.UpdateTo(control); |
| 1012 } else if (NodeProperties::IsEffectEdge(edge)) { |
| 1013 edge.UpdateTo(effect); |
| 1014 } else { |
| 1015 DCHECK(NodeProperties::IsValueEdge(edge)); |
| 1016 } |
| 1017 } |
| 1018 |
| 1019 node->TrimInputCount(new_op->ValueInputCount()); |
| 1020 NodeProperties::ChangeOp(node, new_op); |
| 1021 } |
| 1022 |
| 1023 void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) { |
| 1024 for (Edge edge : node->use_edges()) { |
| 1025 if (NodeProperties::IsControlEdge(edge)) { |
| 1026 edge.UpdateTo(control); |
| 1027 } else if (NodeProperties::IsEffectEdge(edge)) { |
| 1028 edge.UpdateTo(effect); |
| 1029 } else { |
| 1030 DCHECK(NodeProperties::IsValueEdge(edge)); |
| 1031 } |
| 1032 } |
| 1033 } |
| 1034 |
| 1035 void ChangeToInt32OverflowOp(Node* node, const Operator* op) { |
| 1036 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0); |
| 1037 Node* effect = NodeProperties::GetEffectInput(node); |
| 1038 Node* control = NodeProperties::GetControlInput(node); |
| 1039 Node* arith = graph()->NewNode(op, node->InputAt(0), node->InputAt(1)); |
| 1040 Node* overflow = graph()->NewNode(common()->Projection(1), arith); |
| 1041 control = effect = graph()->NewNode(common()->DeoptimizeIf(), overflow, |
| 1042 frame_state, effect, control); |
| 1043 |
| 1044 Node* value = graph()->NewNode(common()->Projection(0), arith); |
| 1045 ReplaceEffectControlUses(node, effect, control); |
| 1046 DeferReplacement(node, value); |
| 1047 } |
| 1048 |
| 1049 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, |
| 1050 SimplifiedLowering* lowering) { |
| 1051 if (BothInputsAre(node, Type::Signed32()) && |
| 1052 NodeProperties::GetType(node)->Is(Type::Signed32())) { |
| 1053 // int32 + int32 = int32 ==> signed Int32Add/Sub |
| 1054 VisitInt32Binop(node); |
| 1055 if (lower()) ChangeToPureOp(node, Int32Op(node)); |
| 1056 return; |
| 1057 } |
| 1058 |
| 1059 // Use truncation if available. |
| 1060 if (BothInputsAre(node, type_cache_.kAdditiveSafeInteger) && |
| 1061 truncation.TruncatesToWord32()) { |
| 1062 // safe-int + safe-int = x (truncated to int32) |
| 1063 // => signed Int32Add/Sub (truncated) |
| 1064 VisitWord32TruncatingBinop(node); |
| 1065 if (lower()) ChangeToPureOp(node, Int32Op(node)); |
| 1066 return; |
| 1067 } |
| 1068 |
| 1069 // Try to use type feedback. |
| 1070 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op()); |
| 1071 |
| 1072 // TODO(jarin) This might not be necessary (covered by the next case). |
| 1073 // The only real difference is that this one actually treats the |
| 1074 // inputs as truncated to word32. |
| 1075 if (BothInputsAre(node, Type::Signed32())) { |
| 1076 // If both the inputs the feedback are int32, use the overflow op. |
| 1077 if (hint == BinaryOperationHints::kSignedSmall || |
| 1078 hint == BinaryOperationHints::kSigned32) { |
| 1079 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1080 MachineRepresentation::kWord32, TypeCheckKind::kSigned32); |
| 1081 if (lower()) { |
| 1082 ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); |
| 1083 } |
| 1084 return; |
| 1085 } |
| 1086 } |
| 1087 |
| 1088 if (hint == BinaryOperationHints::kSignedSmall || |
| 1089 hint == BinaryOperationHints::kSigned32) { |
| 1090 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), |
| 1091 MachineRepresentation::kWord32, TypeCheckKind::kSigned32); |
| 1092 if (lower()) { |
| 1093 ChangeToInt32OverflowOp(node, Int32OverflowOp(node)); |
| 1094 } |
| 1095 return; |
| 1096 } |
| 1097 |
| 1098 // default case => Float64Add/Sub |
| 1099 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), |
| 1100 MachineRepresentation::kFloat64, TypeCheckKind::kNumber); |
| 1101 if (lower()) { |
| 1102 ChangeToPureOp(node, Float64Op(node)); |
| 1103 } |
| 1104 return; |
| 1105 } |
| 1106 |
779 // Dispatching routine for visiting the node {node} with the usage {use}. | 1107 // Dispatching routine for visiting the node {node} with the usage {use}. |
780 // Depending on the operator, propagate new usage info to the inputs. | 1108 // Depending on the operator, propagate new usage info to the inputs. |
781 void VisitNode(Node* node, Truncation truncation, | 1109 void VisitNode(Node* node, Truncation truncation, |
782 SimplifiedLowering* lowering) { | 1110 SimplifiedLowering* lowering) { |
783 switch (node->opcode()) { | 1111 switch (node->opcode()) { |
784 //------------------------------------------------------------------ | 1112 //------------------------------------------------------------------ |
785 // Common operators. | 1113 // Common operators. |
786 //------------------------------------------------------------------ | 1114 //------------------------------------------------------------------ |
787 case IrOpcode::kStart: | 1115 case IrOpcode::kStart: |
788 case IrOpcode::kDead: | 1116 case IrOpcode::kDead: |
(...skipping 17 matching lines...) Expand all Loading... |
806 case IrOpcode::kNumberConstant: | 1134 case IrOpcode::kNumberConstant: |
807 return VisitLeaf(node, MachineRepresentation::kTagged); | 1135 return VisitLeaf(node, MachineRepresentation::kTagged); |
808 case IrOpcode::kHeapConstant: | 1136 case IrOpcode::kHeapConstant: |
809 return VisitLeaf(node, MachineRepresentation::kTagged); | 1137 return VisitLeaf(node, MachineRepresentation::kTagged); |
810 | 1138 |
811 case IrOpcode::kDeoptimizeIf: | 1139 case IrOpcode::kDeoptimizeIf: |
812 case IrOpcode::kDeoptimizeUnless: | 1140 case IrOpcode::kDeoptimizeUnless: |
813 ProcessInput(node, 0, UseInfo::Bool()); | 1141 ProcessInput(node, 0, UseInfo::Bool()); |
814 ProcessInput(node, 1, UseInfo::AnyTagged()); | 1142 ProcessInput(node, 1, UseInfo::AnyTagged()); |
815 ProcessRemainingInputs(node, 2); | 1143 ProcessRemainingInputs(node, 2); |
816 break; | 1144 return; |
817 case IrOpcode::kBranch: | 1145 case IrOpcode::kBranch: |
818 ProcessInput(node, 0, UseInfo::Bool()); | 1146 ProcessInput(node, 0, UseInfo::Bool()); |
819 EnqueueInput(node, NodeProperties::FirstControlIndex(node)); | 1147 EnqueueInput(node, NodeProperties::FirstControlIndex(node)); |
820 break; | 1148 return; |
821 case IrOpcode::kSwitch: | 1149 case IrOpcode::kSwitch: |
822 ProcessInput(node, 0, UseInfo::TruncatingWord32()); | 1150 ProcessInput(node, 0, UseInfo::TruncatingWord32()); |
823 EnqueueInput(node, NodeProperties::FirstControlIndex(node)); | 1151 EnqueueInput(node, NodeProperties::FirstControlIndex(node)); |
824 break; | 1152 return; |
825 case IrOpcode::kSelect: | 1153 case IrOpcode::kSelect: |
826 return VisitSelect(node, truncation, lowering); | 1154 return VisitSelect(node, truncation, lowering); |
827 case IrOpcode::kPhi: | 1155 case IrOpcode::kPhi: |
828 return VisitPhi(node, truncation, lowering); | 1156 return VisitPhi(node, truncation, lowering); |
829 case IrOpcode::kCall: | 1157 case IrOpcode::kCall: |
830 return VisitCall(node, lowering); | 1158 return VisitCall(node, lowering); |
831 | 1159 |
832 //------------------------------------------------------------------ | 1160 //------------------------------------------------------------------ |
833 // JavaScript operators. | 1161 // JavaScript operators. |
834 //------------------------------------------------------------------ | 1162 //------------------------------------------------------------------ |
835 case IrOpcode::kJSToNumber: { | 1163 case IrOpcode::kJSToNumber: { |
836 VisitInputs(node); | 1164 VisitInputs(node); |
837 // TODO(bmeurer): Optimize somewhat based on input type? | 1165 // TODO(bmeurer): Optimize somewhat based on input type? |
838 if (truncation.TruncatesToWord32()) { | 1166 if (truncation.TruncatesToWord32()) { |
839 SetOutput(node, MachineRepresentation::kWord32); | 1167 SetOutput(node, MachineRepresentation::kWord32); |
840 if (lower()) lowering->DoJSToNumberTruncatesToWord32(node, this); | 1168 if (lower()) lowering->DoJSToNumberTruncatesToWord32(node, this); |
841 } else if (truncation.TruncatesToFloat64()) { | 1169 } else if (truncation.TruncatesToFloat64()) { |
842 SetOutput(node, MachineRepresentation::kFloat64); | 1170 SetOutput(node, MachineRepresentation::kFloat64); |
843 if (lower()) lowering->DoJSToNumberTruncatesToFloat64(node, this); | 1171 if (lower()) lowering->DoJSToNumberTruncatesToFloat64(node, this); |
844 } else { | 1172 } else { |
845 SetOutput(node, MachineRepresentation::kTagged); | 1173 SetOutput(node, MachineRepresentation::kTagged); |
846 } | 1174 } |
847 break; | 1175 return; |
848 } | 1176 } |
849 | 1177 |
850 //------------------------------------------------------------------ | 1178 //------------------------------------------------------------------ |
851 // Simplified operators. | 1179 // Simplified operators. |
852 //------------------------------------------------------------------ | 1180 //------------------------------------------------------------------ |
853 case IrOpcode::kBooleanNot: { | 1181 case IrOpcode::kBooleanNot: { |
854 if (lower()) { | 1182 if (lower()) { |
855 NodeInfo* input_info = GetInfo(node->InputAt(0)); | 1183 NodeInfo* input_info = GetInfo(node->InputAt(0)); |
856 if (input_info->representation() == MachineRepresentation::kBit) { | 1184 if (input_info->representation() == MachineRepresentation::kBit) { |
857 // BooleanNot(x: kRepBit) => Word32Equal(x, #0) | 1185 // BooleanNot(x: kRepBit) => Word32Equal(x, #0) |
858 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); | 1186 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); |
859 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal()); | 1187 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal()); |
860 } else { | 1188 } else { |
861 // BooleanNot(x: kRepTagged) => WordEqual(x, #false) | 1189 // BooleanNot(x: kRepTagged) => WordEqual(x, #false) |
862 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant()); | 1190 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant()); |
863 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); | 1191 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); |
864 } | 1192 } |
865 } else { | 1193 } else { |
866 // No input representation requirement; adapt during lowering. | 1194 // No input representation requirement; adapt during lowering. |
867 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); | 1195 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); |
868 SetOutput(node, MachineRepresentation::kBit); | 1196 SetOutput(node, MachineRepresentation::kBit); |
869 } | 1197 } |
870 break; | 1198 return; |
871 } | 1199 } |
872 case IrOpcode::kBooleanToNumber: { | 1200 case IrOpcode::kBooleanToNumber: { |
873 if (lower()) { | 1201 if (lower()) { |
874 NodeInfo* input_info = GetInfo(node->InputAt(0)); | 1202 NodeInfo* input_info = GetInfo(node->InputAt(0)); |
875 if (input_info->representation() == MachineRepresentation::kBit) { | 1203 if (input_info->representation() == MachineRepresentation::kBit) { |
876 // BooleanToNumber(x: kRepBit) => x | 1204 // BooleanToNumber(x: kRepBit) => x |
877 DeferReplacement(node, node->InputAt(0)); | 1205 DeferReplacement(node, node->InputAt(0)); |
878 } else { | 1206 } else { |
879 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true) | 1207 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true) |
880 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant()); | 1208 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant()); |
881 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); | 1209 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); |
882 } | 1210 } |
883 } else { | 1211 } else { |
884 // No input representation requirement; adapt during lowering. | 1212 // No input representation requirement; adapt during lowering. |
885 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); | 1213 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); |
886 SetOutput(node, MachineRepresentation::kWord32); | 1214 SetOutput(node, MachineRepresentation::kWord32); |
887 } | 1215 } |
888 break; | 1216 return; |
889 } | 1217 } |
890 case IrOpcode::kNumberEqual: | 1218 case IrOpcode::kNumberEqual: |
891 case IrOpcode::kNumberLessThan: | 1219 case IrOpcode::kNumberLessThan: |
892 case IrOpcode::kNumberLessThanOrEqual: { | 1220 case IrOpcode::kNumberLessThanOrEqual: { |
893 // Number comparisons reduce to integer comparisons for integer inputs. | 1221 // Number comparisons reduce to integer comparisons for integer inputs. |
894 if (BothInputsAreSigned32(node)) { | 1222 if (BothInputsAreSigned32(node)) { |
895 // => signed Int32Cmp | 1223 // => signed Int32Cmp |
896 VisitInt32Cmp(node); | 1224 VisitInt32Cmp(node); |
897 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 1225 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
898 } else if (BothInputsAreUnsigned32(node)) { | 1226 } else if (BothInputsAreUnsigned32(node)) { |
899 // => unsigned Int32Cmp | 1227 // => unsigned Int32Cmp |
900 VisitUint32Cmp(node); | 1228 VisitUint32Cmp(node); |
901 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); | 1229 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); |
902 } else { | 1230 } else { |
903 // => Float64Cmp | 1231 // => Float64Cmp |
904 VisitFloat64Cmp(node); | 1232 VisitFloat64Cmp(node); |
905 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 1233 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
906 } | 1234 } |
907 break; | 1235 return; |
908 } | 1236 } |
| 1237 |
| 1238 case IrOpcode::kSpeculativeNumberAdd: |
| 1239 case IrOpcode::kSpeculativeNumberSubtract: |
| 1240 return VisitSpeculativeAdditiveOp(node, truncation, lowering); |
| 1241 |
909 case IrOpcode::kNumberAdd: | 1242 case IrOpcode::kNumberAdd: |
910 case IrOpcode::kNumberSubtract: { | 1243 case IrOpcode::kNumberSubtract: { |
911 if (BothInputsAre(node, Type::Signed32()) && | 1244 if (BothInputsAre(node, Type::Signed32()) && |
912 NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1245 NodeProperties::GetType(node)->Is(Type::Signed32())) { |
913 // int32 + int32 = int32 | 1246 // int32 + int32 = int32 |
914 // => signed Int32Add/Sub | 1247 // => signed Int32Add/Sub |
915 VisitInt32Binop(node); | 1248 VisitInt32Binop(node); |
916 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 1249 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
917 } else if (BothInputsAre(node, type_cache_.kAdditiveSafeInteger) && | 1250 } else if (BothInputsAre(node, type_cache_.kAdditiveSafeInteger) && |
918 truncation.TruncatesToWord32()) { | 1251 truncation.TruncatesToWord32()) { |
919 // safe-int + safe-int = x (truncated to int32) | 1252 // safe-int + safe-int = x (truncated to int32) |
920 // => signed Int32Add/Sub (truncated) | 1253 // => signed Int32Add/Sub (truncated) |
921 VisitWord32TruncatingBinop(node); | 1254 VisitWord32TruncatingBinop(node); |
922 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 1255 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
923 } else { | 1256 } else { |
924 // => Float64Add/Sub | 1257 // => Float64Add/Sub |
925 VisitFloat64Binop(node); | 1258 VisitFloat64Binop(node); |
926 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 1259 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
927 } | 1260 } |
928 break; | 1261 return; |
929 } | 1262 } |
930 case IrOpcode::kNumberMultiply: { | 1263 case IrOpcode::kNumberMultiply: { |
931 if (BothInputsAreSigned32(node)) { | 1264 if (BothInputsAreSigned32(node)) { |
932 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1265 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { |
933 // Multiply reduces to Int32Mul if the inputs and the output | 1266 // Multiply reduces to Int32Mul if the inputs and the output |
934 // are integers. | 1267 // are integers. |
935 VisitInt32Binop(node); | 1268 VisitInt32Binop(node); |
936 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 1269 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
937 break; | 1270 return; |
938 } | 1271 } |
939 if (truncation.TruncatesToWord32() && | 1272 if (truncation.TruncatesToWord32() && |
940 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger)) { | 1273 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger)) { |
941 // Multiply reduces to Int32Mul if the inputs are integers, | 1274 // Multiply reduces to Int32Mul if the inputs are integers, |
942 // the uses are truncating and the result is in the safe | 1275 // the uses are truncating and the result is in the safe |
943 // integer range. | 1276 // integer range. |
944 VisitWord32TruncatingBinop(node); | 1277 VisitWord32TruncatingBinop(node); |
945 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 1278 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
946 break; | 1279 return; |
947 } | 1280 } |
948 } | 1281 } |
949 // => Float64Mul | 1282 // => Float64Mul |
950 VisitFloat64Binop(node); | 1283 VisitFloat64Binop(node); |
951 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 1284 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
952 break; | 1285 return; |
953 } | 1286 } |
954 case IrOpcode::kNumberDivide: { | 1287 case IrOpcode::kNumberDivide: { |
955 if (BothInputsAreSigned32(node)) { | 1288 if (BothInputsAreSigned32(node)) { |
956 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1289 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { |
957 // => signed Int32Div | 1290 // => signed Int32Div |
958 VisitInt32Binop(node); | 1291 VisitInt32Binop(node); |
959 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 1292 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); |
960 break; | 1293 return; |
961 } | 1294 } |
962 if (truncation.TruncatesToWord32()) { | 1295 if (truncation.TruncatesToWord32()) { |
963 // => signed Int32Div | 1296 // => signed Int32Div |
964 VisitWord32TruncatingBinop(node); | 1297 VisitWord32TruncatingBinop(node); |
965 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); | 1298 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); |
966 break; | 1299 return; |
967 } | 1300 } |
968 } | 1301 } |
969 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 1302 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { |
970 // => unsigned Uint32Div | 1303 // => unsigned Uint32Div |
971 VisitWord32TruncatingBinop(node); | 1304 VisitWord32TruncatingBinop(node); |
972 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); | 1305 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); |
973 break; | 1306 return; |
974 } | 1307 } |
975 // => Float64Div | 1308 // => Float64Div |
976 VisitFloat64Binop(node); | 1309 VisitFloat64Binop(node); |
977 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 1310 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
978 break; | 1311 return; |
979 } | 1312 } |
980 case IrOpcode::kNumberModulus: { | 1313 case IrOpcode::kNumberModulus: { |
981 if (BothInputsAreSigned32(node)) { | 1314 if (BothInputsAreSigned32(node)) { |
982 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { | 1315 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { |
983 // => signed Int32Mod | 1316 // => signed Int32Mod |
984 VisitInt32Binop(node); | 1317 VisitInt32Binop(node); |
985 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 1318 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
986 break; | 1319 return; |
987 } | 1320 } |
988 if (truncation.TruncatesToWord32()) { | 1321 if (truncation.TruncatesToWord32()) { |
989 // => signed Int32Mod | 1322 // => signed Int32Mod |
990 VisitWord32TruncatingBinop(node); | 1323 VisitWord32TruncatingBinop(node); |
991 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); | 1324 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); |
992 break; | 1325 return; |
993 } | 1326 } |
994 } | 1327 } |
995 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { | 1328 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { |
996 // => unsigned Uint32Mod | 1329 // => unsigned Uint32Mod |
997 VisitWord32TruncatingBinop(node); | 1330 VisitWord32TruncatingBinop(node); |
998 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); | 1331 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); |
999 break; | 1332 return; |
1000 } | 1333 } |
1001 // => Float64Mod | 1334 // => Float64Mod |
1002 VisitFloat64Binop(node); | 1335 VisitFloat64Binop(node); |
1003 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 1336 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
1004 break; | 1337 return; |
1005 } | 1338 } |
1006 case IrOpcode::kNumberBitwiseOr: | 1339 case IrOpcode::kNumberBitwiseOr: |
1007 case IrOpcode::kNumberBitwiseXor: | 1340 case IrOpcode::kNumberBitwiseXor: |
1008 case IrOpcode::kNumberBitwiseAnd: { | 1341 case IrOpcode::kNumberBitwiseAnd: { |
1009 VisitInt32Binop(node); | 1342 VisitInt32Binop(node); |
1010 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); | 1343 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); |
1011 break; | 1344 return; |
1012 } | 1345 } |
1013 case IrOpcode::kNumberShiftLeft: { | 1346 case IrOpcode::kNumberShiftLeft: { |
1014 Type* rhs_type = GetUpperBound(node->InputAt(1)); | 1347 Type* rhs_type = GetUpperBound(node->InputAt(1)); |
1015 VisitBinop(node, UseInfo::TruncatingWord32(), | 1348 VisitBinop(node, UseInfo::TruncatingWord32(), |
1016 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); | 1349 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); |
1017 if (lower()) { | 1350 if (lower()) { |
1018 lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type); | 1351 lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type); |
1019 } | 1352 } |
1020 break; | 1353 return; |
1021 } | 1354 } |
1022 case IrOpcode::kNumberShiftRight: { | 1355 case IrOpcode::kNumberShiftRight: { |
1023 Type* rhs_type = GetUpperBound(node->InputAt(1)); | 1356 Type* rhs_type = GetUpperBound(node->InputAt(1)); |
1024 VisitBinop(node, UseInfo::TruncatingWord32(), | 1357 VisitBinop(node, UseInfo::TruncatingWord32(), |
1025 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); | 1358 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); |
1026 if (lower()) { | 1359 if (lower()) { |
1027 lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type); | 1360 lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type); |
1028 } | 1361 } |
1029 break; | 1362 return; |
1030 } | 1363 } |
1031 case IrOpcode::kNumberShiftRightLogical: { | 1364 case IrOpcode::kNumberShiftRightLogical: { |
1032 Type* rhs_type = GetUpperBound(node->InputAt(1)); | 1365 Type* rhs_type = GetUpperBound(node->InputAt(1)); |
1033 VisitBinop(node, UseInfo::TruncatingWord32(), | 1366 VisitBinop(node, UseInfo::TruncatingWord32(), |
1034 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); | 1367 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); |
1035 if (lower()) { | 1368 if (lower()) { |
1036 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); | 1369 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); |
1037 } | 1370 } |
1038 break; | 1371 return; |
1039 } | 1372 } |
1040 case IrOpcode::kNumberClz32: { | 1373 case IrOpcode::kNumberClz32: { |
1041 VisitUnop(node, UseInfo::TruncatingWord32(), | 1374 VisitUnop(node, UseInfo::TruncatingWord32(), |
1042 MachineRepresentation::kWord32); | 1375 MachineRepresentation::kWord32); |
1043 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); | 1376 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); |
1044 break; | 1377 return; |
1045 } | 1378 } |
1046 case IrOpcode::kNumberImul: { | 1379 case IrOpcode::kNumberImul: { |
1047 VisitBinop(node, UseInfo::TruncatingWord32(), | 1380 VisitBinop(node, UseInfo::TruncatingWord32(), |
1048 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); | 1381 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); |
1049 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); | 1382 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); |
1050 break; | 1383 return; |
1051 } | 1384 } |
1052 case IrOpcode::kNumberCeil: { | 1385 case IrOpcode::kNumberCeil: { |
1053 VisitUnop(node, UseInfo::TruncatingFloat64(), | 1386 VisitUnop(node, UseInfo::TruncatingFloat64(), |
1054 MachineRepresentation::kFloat64); | 1387 MachineRepresentation::kFloat64); |
1055 if (lower()) DeferReplacement(node, lowering->Float64Ceil(node)); | 1388 if (lower()) DeferReplacement(node, lowering->Float64Ceil(node)); |
1056 break; | 1389 return; |
1057 } | 1390 } |
1058 case IrOpcode::kNumberFloor: { | 1391 case IrOpcode::kNumberFloor: { |
1059 VisitUnop(node, UseInfo::TruncatingFloat64(), | 1392 VisitUnop(node, UseInfo::TruncatingFloat64(), |
1060 MachineRepresentation::kFloat64); | 1393 MachineRepresentation::kFloat64); |
1061 if (lower()) DeferReplacement(node, lowering->Float64Floor(node)); | 1394 if (lower()) DeferReplacement(node, lowering->Float64Floor(node)); |
1062 break; | 1395 return; |
1063 } | 1396 } |
1064 case IrOpcode::kNumberRound: { | 1397 case IrOpcode::kNumberRound: { |
1065 VisitUnop(node, UseInfo::TruncatingFloat64(), | 1398 VisitUnop(node, UseInfo::TruncatingFloat64(), |
1066 MachineRepresentation::kFloat64); | 1399 MachineRepresentation::kFloat64); |
1067 if (lower()) DeferReplacement(node, lowering->Float64Round(node)); | 1400 if (lower()) DeferReplacement(node, lowering->Float64Round(node)); |
1068 break; | 1401 return; |
1069 } | 1402 } |
1070 case IrOpcode::kNumberTrunc: { | 1403 case IrOpcode::kNumberTrunc: { |
1071 VisitUnop(node, UseInfo::TruncatingFloat64(), | 1404 VisitUnop(node, UseInfo::TruncatingFloat64(), |
1072 MachineRepresentation::kFloat64); | 1405 MachineRepresentation::kFloat64); |
1073 if (lower()) DeferReplacement(node, lowering->Float64Trunc(node)); | 1406 if (lower()) DeferReplacement(node, lowering->Float64Trunc(node)); |
1074 break; | 1407 return; |
1075 } | 1408 } |
1076 case IrOpcode::kNumberToInt32: { | 1409 case IrOpcode::kNumberToInt32: { |
1077 // Just change representation if necessary. | 1410 // Just change representation if necessary. |
1078 VisitUnop(node, UseInfo::TruncatingWord32(), | 1411 VisitUnop(node, UseInfo::TruncatingWord32(), |
1079 MachineRepresentation::kWord32); | 1412 MachineRepresentation::kWord32); |
1080 if (lower()) DeferReplacement(node, node->InputAt(0)); | 1413 if (lower()) DeferReplacement(node, node->InputAt(0)); |
1081 break; | 1414 return; |
1082 } | 1415 } |
1083 case IrOpcode::kNumberToUint32: { | 1416 case IrOpcode::kNumberToUint32: { |
1084 // Just change representation if necessary. | 1417 // Just change representation if necessary. |
1085 VisitUnop(node, UseInfo::TruncatingWord32(), | 1418 VisitUnop(node, UseInfo::TruncatingWord32(), |
1086 MachineRepresentation::kWord32); | 1419 MachineRepresentation::kWord32); |
1087 if (lower()) DeferReplacement(node, node->InputAt(0)); | 1420 if (lower()) DeferReplacement(node, node->InputAt(0)); |
1088 break; | 1421 return; |
1089 } | 1422 } |
1090 case IrOpcode::kNumberIsHoleNaN: { | 1423 case IrOpcode::kNumberIsHoleNaN: { |
1091 VisitUnop(node, UseInfo::TruncatingFloat64(), | 1424 VisitUnop(node, UseInfo::TruncatingFloat64(), |
1092 MachineRepresentation::kBit); | 1425 MachineRepresentation::kBit); |
1093 if (lower()) { | 1426 if (lower()) { |
1094 // NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x), | 1427 // NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x), |
1095 // #HoleNaNLower32) | 1428 // #HoleNaNLower32) |
1096 node->ReplaceInput(0, | 1429 node->ReplaceInput(0, |
1097 jsgraph_->graph()->NewNode( | 1430 jsgraph_->graph()->NewNode( |
1098 lowering->machine()->Float64ExtractLowWord32(), | 1431 lowering->machine()->Float64ExtractLowWord32(), |
1099 node->InputAt(0))); | 1432 node->InputAt(0))); |
1100 node->AppendInput(jsgraph_->zone(), | 1433 node->AppendInput(jsgraph_->zone(), |
1101 jsgraph_->Int32Constant(kHoleNanLower32)); | 1434 jsgraph_->Int32Constant(kHoleNanLower32)); |
1102 NodeProperties::ChangeOp(node, jsgraph_->machine()->Word32Equal()); | 1435 NodeProperties::ChangeOp(node, jsgraph_->machine()->Word32Equal()); |
1103 } | 1436 } |
1104 break; | 1437 return; |
1105 } | 1438 } |
1106 case IrOpcode::kReferenceEqual: { | 1439 case IrOpcode::kReferenceEqual: { |
1107 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); | 1440 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); |
1108 if (lower()) { | 1441 if (lower()) { |
1109 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); | 1442 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); |
1110 } | 1443 } |
1111 break; | 1444 return; |
1112 } | 1445 } |
1113 case IrOpcode::kStringEqual: { | 1446 case IrOpcode::kStringEqual: { |
1114 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); | 1447 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); |
1115 if (lower()) { | 1448 if (lower()) { |
1116 // StringEqual(x, y) => Call(StringEqualStub, x, y, no-context) | 1449 // StringEqual(x, y) => Call(StringEqualStub, x, y, no-context) |
1117 Operator::Properties properties = | 1450 Operator::Properties properties = |
1118 Operator::kCommutative | Operator::kNoThrow; | 1451 Operator::kCommutative | Operator::kNoThrow; |
1119 Callable callable = CodeFactory::StringEqual(jsgraph_->isolate()); | 1452 Callable callable = CodeFactory::StringEqual(jsgraph_->isolate()); |
1120 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 1453 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
1121 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 1454 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
1122 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, | 1455 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, |
1123 flags, properties); | 1456 flags, properties); |
1124 node->InsertInput(jsgraph_->zone(), 0, | 1457 node->InsertInput(jsgraph_->zone(), 0, |
1125 jsgraph_->HeapConstant(callable.code())); | 1458 jsgraph_->HeapConstant(callable.code())); |
1126 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); | 1459 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); |
1127 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); | 1460 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); |
1128 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); | 1461 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); |
1129 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); | 1462 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); |
1130 } | 1463 } |
1131 break; | 1464 return; |
1132 } | 1465 } |
1133 case IrOpcode::kStringLessThan: { | 1466 case IrOpcode::kStringLessThan: { |
1134 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); | 1467 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); |
1135 if (lower()) { | 1468 if (lower()) { |
1136 // StringLessThan(x, y) => Call(StringLessThanStub, x, y, no-context) | 1469 // StringLessThan(x, y) => Call(StringLessThanStub, x, y, no-context) |
1137 Operator::Properties properties = Operator::kNoThrow; | 1470 Operator::Properties properties = Operator::kNoThrow; |
1138 Callable callable = CodeFactory::StringLessThan(jsgraph_->isolate()); | 1471 Callable callable = CodeFactory::StringLessThan(jsgraph_->isolate()); |
1139 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 1472 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
1140 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 1473 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
1141 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, | 1474 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, |
1142 flags, properties); | 1475 flags, properties); |
1143 node->InsertInput(jsgraph_->zone(), 0, | 1476 node->InsertInput(jsgraph_->zone(), 0, |
1144 jsgraph_->HeapConstant(callable.code())); | 1477 jsgraph_->HeapConstant(callable.code())); |
1145 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); | 1478 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); |
1146 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); | 1479 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); |
1147 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); | 1480 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); |
1148 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); | 1481 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); |
1149 } | 1482 } |
1150 break; | 1483 return; |
1151 } | 1484 } |
1152 case IrOpcode::kStringLessThanOrEqual: { | 1485 case IrOpcode::kStringLessThanOrEqual: { |
1153 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); | 1486 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); |
1154 if (lower()) { | 1487 if (lower()) { |
1155 // StringLessThanOrEqual(x, y) | 1488 // StringLessThanOrEqual(x, y) |
1156 // => Call(StringLessThanOrEqualStub, x, y, no-context) | 1489 // => Call(StringLessThanOrEqualStub, x, y, no-context) |
1157 Operator::Properties properties = Operator::kNoThrow; | 1490 Operator::Properties properties = Operator::kNoThrow; |
1158 Callable callable = | 1491 Callable callable = |
1159 CodeFactory::StringLessThanOrEqual(jsgraph_->isolate()); | 1492 CodeFactory::StringLessThanOrEqual(jsgraph_->isolate()); |
1160 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 1493 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
1161 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 1494 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
1162 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, | 1495 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, |
1163 flags, properties); | 1496 flags, properties); |
1164 node->InsertInput(jsgraph_->zone(), 0, | 1497 node->InsertInput(jsgraph_->zone(), 0, |
1165 jsgraph_->HeapConstant(callable.code())); | 1498 jsgraph_->HeapConstant(callable.code())); |
1166 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); | 1499 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); |
1167 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); | 1500 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); |
1168 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); | 1501 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); |
1169 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); | 1502 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); |
1170 } | 1503 } |
1171 break; | 1504 return; |
1172 } | 1505 } |
1173 case IrOpcode::kStringToNumber: { | 1506 case IrOpcode::kStringToNumber: { |
1174 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); | 1507 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); |
1175 if (lower()) { | 1508 if (lower()) { |
1176 // StringToNumber(x) => Call(StringToNumberStub, x, no-context) | 1509 // StringToNumber(x) => Call(StringToNumberStub, x, no-context) |
1177 Operator::Properties properties = Operator::kNoThrow; | 1510 Operator::Properties properties = Operator::kNoThrow; |
1178 Callable callable = CodeFactory::StringToNumber(jsgraph_->isolate()); | 1511 Callable callable = CodeFactory::StringToNumber(jsgraph_->isolate()); |
1179 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 1512 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
1180 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 1513 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
1181 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, | 1514 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, |
1182 flags, properties); | 1515 flags, properties); |
1183 node->InsertInput(jsgraph_->zone(), 0, | 1516 node->InsertInput(jsgraph_->zone(), 0, |
1184 jsgraph_->HeapConstant(callable.code())); | 1517 jsgraph_->HeapConstant(callable.code())); |
1185 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); | 1518 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); |
1186 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); | 1519 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); |
1187 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); | 1520 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); |
1188 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); | 1521 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); |
1189 } | 1522 } |
1190 break; | 1523 return; |
1191 } | 1524 } |
1192 case IrOpcode::kAllocate: { | 1525 case IrOpcode::kAllocate: { |
1193 ProcessInput(node, 0, UseInfo::TruncatingWord32()); | 1526 ProcessInput(node, 0, UseInfo::TruncatingWord32()); |
1194 ProcessRemainingInputs(node, 1); | 1527 ProcessRemainingInputs(node, 1); |
1195 SetOutput(node, MachineRepresentation::kTagged); | 1528 SetOutput(node, MachineRepresentation::kTagged); |
1196 break; | 1529 return; |
1197 } | 1530 } |
1198 case IrOpcode::kLoadField: { | 1531 case IrOpcode::kLoadField: { |
1199 FieldAccess access = FieldAccessOf(node->op()); | 1532 FieldAccess access = FieldAccessOf(node->op()); |
1200 ProcessInput(node, 0, UseInfoForBasePointer(access)); | 1533 ProcessInput(node, 0, UseInfoForBasePointer(access)); |
1201 ProcessRemainingInputs(node, 1); | 1534 ProcessRemainingInputs(node, 1); |
1202 SetOutput(node, access.machine_type.representation()); | 1535 SetOutput(node, access.machine_type.representation()); |
1203 break; | 1536 return; |
1204 } | 1537 } |
1205 case IrOpcode::kStoreField: { | 1538 case IrOpcode::kStoreField: { |
1206 FieldAccess access = FieldAccessOf(node->op()); | 1539 FieldAccess access = FieldAccessOf(node->op()); |
1207 ProcessInput(node, 0, UseInfoForBasePointer(access)); | 1540 ProcessInput(node, 0, UseInfoForBasePointer(access)); |
1208 ProcessInput(node, 1, TruncatingUseInfoFromRepresentation( | 1541 ProcessInput(node, 1, TruncatingUseInfoFromRepresentation( |
1209 access.machine_type.representation())); | 1542 access.machine_type.representation())); |
1210 ProcessRemainingInputs(node, 2); | 1543 ProcessRemainingInputs(node, 2); |
1211 SetOutput(node, MachineRepresentation::kNone); | 1544 SetOutput(node, MachineRepresentation::kNone); |
1212 if (lower()) { | 1545 if (lower()) { |
1213 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor( | 1546 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor( |
1214 access.base_is_tagged, access.machine_type.representation(), | 1547 access.base_is_tagged, access.machine_type.representation(), |
1215 access.offset, access.type, node->InputAt(1)); | 1548 access.offset, access.type, node->InputAt(1)); |
1216 if (write_barrier_kind < access.write_barrier_kind) { | 1549 if (write_barrier_kind < access.write_barrier_kind) { |
1217 access.write_barrier_kind = write_barrier_kind; | 1550 access.write_barrier_kind = write_barrier_kind; |
1218 NodeProperties::ChangeOp( | 1551 NodeProperties::ChangeOp( |
1219 node, jsgraph_->simplified()->StoreField(access)); | 1552 node, jsgraph_->simplified()->StoreField(access)); |
1220 } | 1553 } |
1221 } | 1554 } |
1222 break; | 1555 return; |
1223 } | 1556 } |
1224 case IrOpcode::kLoadBuffer: { | 1557 case IrOpcode::kLoadBuffer: { |
1225 BufferAccess access = BufferAccessOf(node->op()); | 1558 BufferAccess access = BufferAccessOf(node->op()); |
1226 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer | 1559 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer |
1227 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset | 1560 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset |
1228 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length | 1561 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length |
1229 ProcessRemainingInputs(node, 3); | 1562 ProcessRemainingInputs(node, 3); |
1230 | 1563 |
1231 MachineRepresentation output; | 1564 MachineRepresentation output; |
1232 if (truncation.TruncatesUndefinedToZeroOrNaN()) { | 1565 if (truncation.TruncatesUndefinedToZeroOrNaN()) { |
(...skipping 12 matching lines...) Expand all Loading... |
1245 output = MachineRepresentation::kFloat64; | 1578 output = MachineRepresentation::kFloat64; |
1246 } | 1579 } |
1247 } | 1580 } |
1248 } else { | 1581 } else { |
1249 // If undefined is not truncated away, we need to have the tagged | 1582 // If undefined is not truncated away, we need to have the tagged |
1250 // representation. | 1583 // representation. |
1251 output = MachineRepresentation::kTagged; | 1584 output = MachineRepresentation::kTagged; |
1252 } | 1585 } |
1253 SetOutput(node, output); | 1586 SetOutput(node, output); |
1254 if (lower()) lowering->DoLoadBuffer(node, output, changer_); | 1587 if (lower()) lowering->DoLoadBuffer(node, output, changer_); |
1255 break; | 1588 return; |
1256 } | 1589 } |
1257 case IrOpcode::kStoreBuffer: { | 1590 case IrOpcode::kStoreBuffer: { |
1258 BufferAccess access = BufferAccessOf(node->op()); | 1591 BufferAccess access = BufferAccessOf(node->op()); |
1259 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer | 1592 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer |
1260 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset | 1593 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset |
1261 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length | 1594 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length |
1262 ProcessInput(node, 3, | 1595 ProcessInput(node, 3, |
1263 TruncatingUseInfoFromRepresentation( | 1596 TruncatingUseInfoFromRepresentation( |
1264 access.machine_type().representation())); // value | 1597 access.machine_type().representation())); // value |
1265 ProcessRemainingInputs(node, 4); | 1598 ProcessRemainingInputs(node, 4); |
1266 SetOutput(node, MachineRepresentation::kNone); | 1599 SetOutput(node, MachineRepresentation::kNone); |
1267 if (lower()) lowering->DoStoreBuffer(node); | 1600 if (lower()) lowering->DoStoreBuffer(node); |
1268 break; | 1601 return; |
1269 } | 1602 } |
1270 case IrOpcode::kLoadElement: { | 1603 case IrOpcode::kLoadElement: { |
1271 ElementAccess access = ElementAccessOf(node->op()); | 1604 ElementAccess access = ElementAccessOf(node->op()); |
1272 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base | 1605 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base |
1273 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index | 1606 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index |
1274 ProcessRemainingInputs(node, 2); | 1607 ProcessRemainingInputs(node, 2); |
1275 SetOutput(node, access.machine_type.representation()); | 1608 SetOutput(node, access.machine_type.representation()); |
1276 break; | 1609 return; |
1277 } | 1610 } |
1278 case IrOpcode::kStoreElement: { | 1611 case IrOpcode::kStoreElement: { |
1279 ElementAccess access = ElementAccessOf(node->op()); | 1612 ElementAccess access = ElementAccessOf(node->op()); |
1280 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base | 1613 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base |
1281 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index | 1614 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index |
1282 ProcessInput(node, 2, | 1615 ProcessInput(node, 2, |
1283 TruncatingUseInfoFromRepresentation( | 1616 TruncatingUseInfoFromRepresentation( |
1284 access.machine_type.representation())); // value | 1617 access.machine_type.representation())); // value |
1285 ProcessRemainingInputs(node, 3); | 1618 ProcessRemainingInputs(node, 3); |
1286 SetOutput(node, MachineRepresentation::kNone); | 1619 SetOutput(node, MachineRepresentation::kNone); |
1287 if (lower()) { | 1620 if (lower()) { |
1288 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor( | 1621 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor( |
1289 access.base_is_tagged, access.machine_type.representation(), | 1622 access.base_is_tagged, access.machine_type.representation(), |
1290 access.type, node->InputAt(2)); | 1623 access.type, node->InputAt(2)); |
1291 if (write_barrier_kind < access.write_barrier_kind) { | 1624 if (write_barrier_kind < access.write_barrier_kind) { |
1292 access.write_barrier_kind = write_barrier_kind; | 1625 access.write_barrier_kind = write_barrier_kind; |
1293 NodeProperties::ChangeOp( | 1626 NodeProperties::ChangeOp( |
1294 node, jsgraph_->simplified()->StoreElement(access)); | 1627 node, jsgraph_->simplified()->StoreElement(access)); |
1295 } | 1628 } |
1296 } | 1629 } |
1297 break; | 1630 return; |
1298 } | 1631 } |
1299 case IrOpcode::kObjectIsCallable: | 1632 case IrOpcode::kObjectIsCallable: |
1300 case IrOpcode::kObjectIsNumber: | 1633 case IrOpcode::kObjectIsNumber: |
1301 case IrOpcode::kObjectIsReceiver: | 1634 case IrOpcode::kObjectIsReceiver: |
1302 case IrOpcode::kObjectIsSmi: | 1635 case IrOpcode::kObjectIsSmi: |
1303 case IrOpcode::kObjectIsString: | 1636 case IrOpcode::kObjectIsString: |
1304 case IrOpcode::kObjectIsUndetectable: { | 1637 case IrOpcode::kObjectIsUndetectable: { |
1305 ProcessInput(node, 0, UseInfo::AnyTagged()); | 1638 ProcessInput(node, 0, UseInfo::AnyTagged()); |
1306 SetOutput(node, MachineRepresentation::kBit); | 1639 SetOutput(node, MachineRepresentation::kBit); |
1307 break; | 1640 return; |
1308 } | 1641 } |
1309 | 1642 |
1310 //------------------------------------------------------------------ | 1643 //------------------------------------------------------------------ |
1311 // Machine-level operators. | 1644 // Machine-level operators. |
1312 //------------------------------------------------------------------ | 1645 //------------------------------------------------------------------ |
1313 case IrOpcode::kLoad: { | 1646 case IrOpcode::kLoad: { |
1314 // TODO(jarin) Eventually, we should get rid of all machine stores | 1647 // TODO(jarin) Eventually, we should get rid of all machine stores |
1315 // from the high-level phases, then this becomes UNREACHABLE. | 1648 // from the high-level phases, then this becomes UNREACHABLE. |
1316 LoadRepresentation rep = LoadRepresentationOf(node->op()); | 1649 LoadRepresentation rep = LoadRepresentationOf(node->op()); |
1317 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer | 1650 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer |
1318 ProcessInput(node, 1, UseInfo::PointerInt()); // index | 1651 ProcessInput(node, 1, UseInfo::PointerInt()); // index |
1319 ProcessRemainingInputs(node, 2); | 1652 ProcessRemainingInputs(node, 2); |
1320 SetOutput(node, rep.representation()); | 1653 return SetOutput(node, rep.representation()); |
1321 break; | |
1322 } | 1654 } |
1323 case IrOpcode::kStore: { | 1655 case IrOpcode::kStore: { |
1324 // TODO(jarin) Eventually, we should get rid of all machine stores | 1656 // TODO(jarin) Eventually, we should get rid of all machine stores |
1325 // from the high-level phases, then this becomes UNREACHABLE. | 1657 // from the high-level phases, then this becomes UNREACHABLE. |
1326 StoreRepresentation rep = StoreRepresentationOf(node->op()); | 1658 StoreRepresentation rep = StoreRepresentationOf(node->op()); |
1327 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer | 1659 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer |
1328 ProcessInput(node, 1, UseInfo::PointerInt()); // index | 1660 ProcessInput(node, 1, UseInfo::PointerInt()); // index |
1329 ProcessInput(node, 2, | 1661 ProcessInput(node, 2, |
1330 TruncatingUseInfoFromRepresentation(rep.representation())); | 1662 TruncatingUseInfoFromRepresentation(rep.representation())); |
1331 ProcessRemainingInputs(node, 3); | 1663 ProcessRemainingInputs(node, 3); |
1332 SetOutput(node, MachineRepresentation::kNone); | 1664 return SetOutput(node, MachineRepresentation::kNone); |
1333 break; | |
1334 } | 1665 } |
1335 case IrOpcode::kWord32Shr: | 1666 case IrOpcode::kWord32Shr: |
1336 // We output unsigned int32 for shift right because JavaScript. | 1667 // We output unsigned int32 for shift right because JavaScript. |
1337 return VisitBinop(node, UseInfo::TruncatingWord32(), | 1668 return VisitBinop(node, UseInfo::TruncatingWord32(), |
1338 MachineRepresentation::kWord32); | 1669 MachineRepresentation::kWord32); |
1339 case IrOpcode::kWord32And: | 1670 case IrOpcode::kWord32And: |
1340 case IrOpcode::kWord32Or: | 1671 case IrOpcode::kWord32Or: |
1341 case IrOpcode::kWord32Xor: | 1672 case IrOpcode::kWord32Xor: |
1342 case IrOpcode::kWord32Shl: | 1673 case IrOpcode::kWord32Shl: |
1343 case IrOpcode::kWord32Sar: | 1674 case IrOpcode::kWord32Sar: |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1408 case IrOpcode::kChangeUint32ToUint64: | 1739 case IrOpcode::kChangeUint32ToUint64: |
1409 return VisitUnop(node, UseInfo::TruncatingWord32(), | 1740 return VisitUnop(node, UseInfo::TruncatingWord32(), |
1410 MachineRepresentation::kWord64); | 1741 MachineRepresentation::kWord64); |
1411 case IrOpcode::kTruncateFloat64ToFloat32: | 1742 case IrOpcode::kTruncateFloat64ToFloat32: |
1412 return VisitUnop(node, UseInfo::TruncatingFloat64(), | 1743 return VisitUnop(node, UseInfo::TruncatingFloat64(), |
1413 MachineRepresentation::kFloat32); | 1744 MachineRepresentation::kFloat32); |
1414 case IrOpcode::kTruncateFloat64ToWord32: | 1745 case IrOpcode::kTruncateFloat64ToWord32: |
1415 return VisitUnop(node, UseInfo::TruncatingFloat64(), | 1746 return VisitUnop(node, UseInfo::TruncatingFloat64(), |
1416 MachineRepresentation::kWord32); | 1747 MachineRepresentation::kWord32); |
1417 | 1748 |
1418 case IrOpcode::kChangeFloat32ToFloat64: | |
1419 UNREACHABLE(); | |
1420 return VisitUnop(node, UseInfo::TruncatingFloat32(), | |
1421 MachineRepresentation::kFloat64); | |
1422 case IrOpcode::kChangeInt32ToFloat64: | 1749 case IrOpcode::kChangeInt32ToFloat64: |
1423 return VisitUnop(node, UseInfo::TruncatingWord32(), | 1750 return VisitUnop(node, UseInfo::TruncatingWord32(), |
1424 MachineRepresentation::kFloat64); | 1751 MachineRepresentation::kFloat64); |
1425 case IrOpcode::kChangeUint32ToFloat64: | 1752 case IrOpcode::kChangeUint32ToFloat64: |
1426 return VisitUnop(node, UseInfo::TruncatingWord32(), | 1753 return VisitUnop(node, UseInfo::TruncatingWord32(), |
1427 MachineRepresentation::kFloat64); | 1754 MachineRepresentation::kFloat64); |
1428 case IrOpcode::kFloat64Add: | 1755 case IrOpcode::kFloat64Add: |
1429 case IrOpcode::kFloat64Sub: | 1756 case IrOpcode::kFloat64Sub: |
1430 case IrOpcode::kFloat64Mul: | 1757 case IrOpcode::kFloat64Mul: |
1431 case IrOpcode::kFloat64Div: | 1758 case IrOpcode::kFloat64Div: |
(...skipping 19 matching lines...) Expand all Loading... |
1451 case IrOpcode::kFloat64InsertLowWord32: | 1778 case IrOpcode::kFloat64InsertLowWord32: |
1452 case IrOpcode::kFloat64InsertHighWord32: | 1779 case IrOpcode::kFloat64InsertHighWord32: |
1453 return VisitBinop(node, UseInfo::TruncatingFloat64(), | 1780 return VisitBinop(node, UseInfo::TruncatingFloat64(), |
1454 UseInfo::TruncatingWord32(), | 1781 UseInfo::TruncatingWord32(), |
1455 MachineRepresentation::kFloat64); | 1782 MachineRepresentation::kFloat64); |
1456 case IrOpcode::kLoadStackPointer: | 1783 case IrOpcode::kLoadStackPointer: |
1457 case IrOpcode::kLoadFramePointer: | 1784 case IrOpcode::kLoadFramePointer: |
1458 case IrOpcode::kLoadParentFramePointer: | 1785 case IrOpcode::kLoadParentFramePointer: |
1459 return VisitLeaf(node, MachineType::PointerRepresentation()); | 1786 return VisitLeaf(node, MachineType::PointerRepresentation()); |
1460 case IrOpcode::kStateValues: | 1787 case IrOpcode::kStateValues: |
1461 VisitStateValues(node); | 1788 return VisitStateValues(node); |
1462 break; | |
1463 | 1789 |
1464 // The following opcodes are not produced before representation | 1790 // The following opcodes are not produced before representation |
1465 // inference runs, so we do not have any real test coverage. | 1791 // inference runs, so we do not have any real test coverage. |
1466 // Simply fail here. | 1792 // Simply fail here. |
1467 case IrOpcode::kChangeFloat64ToInt32: | 1793 case IrOpcode::kChangeFloat64ToInt32: |
1468 case IrOpcode::kChangeFloat64ToUint32: | 1794 case IrOpcode::kChangeFloat64ToUint32: |
1469 case IrOpcode::kTruncateInt64ToInt32: | 1795 case IrOpcode::kTruncateInt64ToInt32: |
| 1796 case IrOpcode::kChangeFloat32ToFloat64: |
| 1797 case IrOpcode::kCheckedUint32ToInt32: |
| 1798 case IrOpcode::kCheckedFloat64ToInt32: |
| 1799 case IrOpcode::kCheckedTaggedToInt32: |
| 1800 case IrOpcode::kCheckedTaggedToFloat64: |
1470 FATAL("Representation inference: unsupported opcodes."); | 1801 FATAL("Representation inference: unsupported opcodes."); |
| 1802 break; |
1471 | 1803 |
1472 default: | 1804 default: |
1473 VisitInputs(node); | 1805 VisitInputs(node); |
1474 // Assume the output is tagged. | 1806 // Assume the output is tagged. |
1475 SetOutput(node, MachineRepresentation::kTagged); | 1807 return SetOutput(node, MachineRepresentation::kTagged); |
1476 break; | |
1477 } | 1808 } |
| 1809 UNREACHABLE(); |
1478 } | 1810 } |
1479 | 1811 |
1480 void DeferReplacement(Node* node, Node* replacement) { | 1812 void DeferReplacement(Node* node, Node* replacement) { |
1481 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(), | 1813 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(), |
1482 node->op()->mnemonic(), replacement->id(), | 1814 node->op()->mnemonic(), replacement->id(), |
1483 replacement->op()->mnemonic()); | 1815 replacement->op()->mnemonic()); |
1484 | 1816 |
1485 if (replacement->id() < count_ && | 1817 if (replacement->id() < count_ && |
1486 GetUpperBound(node)->Is(GetUpperBound(replacement))) { | 1818 GetUpperBound(node)->Is(GetUpperBound(replacement)) && |
| 1819 TypeOf(node)->Is(TypeOf(replacement))) { |
1487 // Replace with a previously existing node eagerly only if the type is the | 1820 // Replace with a previously existing node eagerly only if the type is the |
1488 // same. | 1821 // same. |
1489 node->ReplaceUses(replacement); | 1822 node->ReplaceUses(replacement); |
1490 } else { | 1823 } else { |
1491 // Otherwise, we are replacing a node with a representation change. | 1824 // Otherwise, we are replacing a node with a representation change. |
1492 // Such a substitution must be done after all lowering is done, because | 1825 // Such a substitution must be done after all lowering is done, because |
1493 // changing the type could confuse the representation change | 1826 // changing the type could confuse the representation change |
1494 // insertion for uses of the node. | 1827 // insertion for uses of the node. |
1495 replacements_.push_back(node); | 1828 replacements_.push_back(node); |
1496 replacements_.push_back(replacement); | 1829 replacements_.push_back(replacement); |
(...skipping 11 matching lines...) Expand all Loading... |
1508 void PrintRepresentation(MachineRepresentation rep) { | 1841 void PrintRepresentation(MachineRepresentation rep) { |
1509 if (FLAG_trace_representation) { | 1842 if (FLAG_trace_representation) { |
1510 OFStream os(stdout); | 1843 OFStream os(stdout); |
1511 os << rep; | 1844 os << rep; |
1512 } | 1845 } |
1513 } | 1846 } |
1514 | 1847 |
1515 void PrintTruncation(Truncation truncation) { | 1848 void PrintTruncation(Truncation truncation) { |
1516 if (FLAG_trace_representation) { | 1849 if (FLAG_trace_representation) { |
1517 OFStream os(stdout); | 1850 OFStream os(stdout); |
1518 os << truncation.description(); | 1851 os << truncation.description() << std::endl; |
1519 } | 1852 } |
1520 } | 1853 } |
1521 | 1854 |
1522 void PrintUseInfo(UseInfo info) { | 1855 void PrintUseInfo(UseInfo info) { |
1523 if (FLAG_trace_representation) { | 1856 if (FLAG_trace_representation) { |
1524 OFStream os(stdout); | 1857 OFStream os(stdout); |
1525 os << info.preferred() << ":" << info.truncation().description(); | 1858 os << info.representation() << ":" << info.truncation().description(); |
1526 } | 1859 } |
1527 } | 1860 } |
1528 | 1861 |
1529 private: | 1862 private: |
1530 JSGraph* jsgraph_; | 1863 JSGraph* jsgraph_; |
| 1864 Zone* zone_; // Temporary zone. |
1531 size_t const count_; // number of nodes in the graph | 1865 size_t const count_; // number of nodes in the graph |
1532 ZoneVector<NodeInfo> info_; // node id -> usage information | 1866 ZoneVector<NodeInfo> info_; // node id -> usage information |
1533 #ifdef DEBUG | 1867 #ifdef DEBUG |
1534 ZoneVector<InputUseInfos> node_input_use_infos_; // Debug information about | 1868 ZoneVector<InputUseInfos> node_input_use_infos_; // Debug information about |
1535 // requirements on inputs. | 1869 // requirements on inputs. |
1536 #endif // DEBUG | 1870 #endif // DEBUG |
1537 NodeVector nodes_; // collected nodes | 1871 NodeVector nodes_; // collected nodes |
1538 NodeVector replacements_; // replacements to be done after lowering | 1872 NodeVector replacements_; // replacements to be done after lowering |
1539 Phase phase_; // current phase of algorithm | 1873 Phase phase_; // current phase of algorithm |
1540 RepresentationChanger* changer_; // for inserting representation changes | 1874 RepresentationChanger* changer_; // for inserting representation changes |
1541 ZoneQueue<Node*> queue_; // queue for traversing the graph | 1875 ZoneQueue<Node*> queue_; // queue for traversing the graph |
| 1876 |
| 1877 struct NodeState { |
| 1878 Node* node; |
| 1879 int input_index; |
| 1880 }; |
| 1881 ZoneStack<NodeState> typing_stack_; // stack for graph typing. |
1542 // TODO(danno): RepresentationSelector shouldn't know anything about the | 1882 // TODO(danno): RepresentationSelector shouldn't know anything about the |
1543 // source positions table, but must for now since there currently is no other | 1883 // 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 | 1884 // way to pass down source position information to nodes created during |
1545 // lowering. Once this phase becomes a vanilla reducer, it should get source | 1885 // lowering. Once this phase becomes a vanilla reducer, it should get source |
1546 // position information via the SourcePositionWrapper like all other reducers. | 1886 // position information via the SourcePositionWrapper like all other reducers. |
1547 SourcePositionTable* source_positions_; | 1887 SourcePositionTable* source_positions_; |
1548 TypeCache const& type_cache_; | 1888 TypeCache const& type_cache_; |
| 1889 OperationTyper op_typer_; // helper for the feedback typer |
1549 | 1890 |
1550 NodeInfo* GetInfo(Node* node) { | 1891 NodeInfo* GetInfo(Node* node) { |
1551 DCHECK(node->id() >= 0); | 1892 DCHECK(node->id() >= 0); |
1552 DCHECK(node->id() < count_); | 1893 DCHECK(node->id() < count_); |
1553 return &info_[node->id()]; | 1894 return &info_[node->id()]; |
1554 } | 1895 } |
| 1896 Zone* zone() { return zone_; } |
| 1897 Zone* graph_zone() { return jsgraph_->zone(); } |
1555 }; | 1898 }; |
1556 | 1899 |
1557 | |
1558 SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone, | 1900 SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone, |
1559 SourcePositionTable* source_positions) | 1901 SourcePositionTable* source_positions, |
| 1902 Flags flags) |
1560 : jsgraph_(jsgraph), | 1903 : jsgraph_(jsgraph), |
1561 zone_(zone), | 1904 zone_(zone), |
1562 type_cache_(TypeCache::Get()), | 1905 type_cache_(TypeCache::Get()), |
| 1906 flags_(flags), |
1563 source_positions_(source_positions) {} | 1907 source_positions_(source_positions) {} |
1564 | 1908 |
1565 | |
1566 void SimplifiedLowering::LowerAllNodes() { | 1909 void SimplifiedLowering::LowerAllNodes() { |
1567 RepresentationChanger changer(jsgraph(), jsgraph()->isolate()); | 1910 RepresentationChanger changer(jsgraph(), jsgraph()->isolate()); |
1568 RepresentationSelector selector(jsgraph(), zone_, &changer, | 1911 RepresentationSelector selector(jsgraph(), zone_, &changer, |
1569 source_positions_); | 1912 source_positions_); |
1570 selector.Run(this); | 1913 selector.Run(this); |
1571 } | 1914 } |
1572 | 1915 |
1573 void SimplifiedLowering::DoJSToNumberTruncatesToFloat64( | 1916 void SimplifiedLowering::DoJSToNumberTruncatesToFloat64( |
1574 Node* node, RepresentationSelector* selector) { | 1917 Node* node, RepresentationSelector* selector) { |
1575 DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode()); | 1918 DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode()); |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1751 Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length); | 2094 Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length); |
1752 Node* branch = | 2095 Node* branch = |
1753 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | 2096 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); |
1754 | 2097 |
1755 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 2098 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
1756 Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index, | 2099 Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index, |
1757 effect, if_true); | 2100 effect, if_true); |
1758 Type* element_type = | 2101 Type* element_type = |
1759 Type::Intersect(NodeProperties::GetType(node), Type::Number(), zone()); | 2102 Type::Intersect(NodeProperties::GetType(node), Type::Number(), zone()); |
1760 Node* vtrue = changer->GetRepresentationFor( | 2103 Node* vtrue = changer->GetRepresentationFor( |
1761 etrue, access_type.representation(), element_type, output_rep, | 2104 etrue, access_type.representation(), element_type, node, |
1762 Truncation::None()); | 2105 UseInfo(output_rep, Truncation::None())); |
1763 | 2106 |
1764 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 2107 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
1765 Node* efalse = effect; | 2108 Node* efalse = effect; |
1766 Node* vfalse; | 2109 Node* vfalse; |
1767 if (output_rep == MachineRepresentation::kTagged) { | 2110 if (output_rep == MachineRepresentation::kTagged) { |
1768 vfalse = jsgraph()->UndefinedConstant(); | 2111 vfalse = jsgraph()->UndefinedConstant(); |
1769 } else if (output_rep == MachineRepresentation::kFloat64) { | 2112 } else if (output_rep == MachineRepresentation::kFloat64) { |
1770 vfalse = | 2113 vfalse = |
1771 jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN()); | 2114 jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN()); |
1772 } else if (output_rep == MachineRepresentation::kFloat32) { | 2115 } else if (output_rep == MachineRepresentation::kFloat32) { |
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2466 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 2809 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
2467 Operator::kNoProperties); | 2810 Operator::kNoProperties); |
2468 to_number_operator_.set(common()->Call(desc)); | 2811 to_number_operator_.set(common()->Call(desc)); |
2469 } | 2812 } |
2470 return to_number_operator_.get(); | 2813 return to_number_operator_.get(); |
2471 } | 2814 } |
2472 | 2815 |
2473 } // namespace compiler | 2816 } // namespace compiler |
2474 } // namespace internal | 2817 } // namespace internal |
2475 } // namespace v8 | 2818 } // namespace v8 |
OLD | NEW |