| 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 |