Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(337)

Side by Side Diff: src/compiler/js-typed-lowering.cc

Issue 1921563002: [turbofan] Initial version of number type feedback. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | src/compiler/opcodes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/code-factory.h" 5 #include "src/code-factory.h"
6 #include "src/compilation-dependencies.h" 6 #include "src/compilation-dependencies.h"
7 #include "src/compiler/access-builder.h" 7 #include "src/compiler/access-builder.h"
8 #include "src/compiler/js-graph.h" 8 #include "src/compiler/js-graph.h"
9 #include "src/compiler/js-typed-lowering.h" 9 #include "src/compiler/js-typed-lowering.h"
10 #include "src/compiler/linkage.h" 10 #include "src/compiler/linkage.h"
11 #include "src/compiler/node-matchers.h" 11 #include "src/compiler/node-matchers.h"
12 #include "src/compiler/node-properties.h" 12 #include "src/compiler/node-properties.h"
13 #include "src/compiler/operator-properties.h" 13 #include "src/compiler/operator-properties.h"
14 #include "src/type-cache.h" 14 #include "src/type-cache.h"
15 #include "src/types.h" 15 #include "src/types.h"
16 16
17 namespace v8 { 17 namespace v8 {
18 namespace internal { 18 namespace internal {
19 namespace compiler { 19 namespace compiler {
20 20
21 // A helper class to simplify the process of reducing a single binop node with a 21 // A helper class to simplify the process of reducing a single binop node with a
22 // JSOperator. This class manages the rewriting of context, control, and effect 22 // JSOperator. This class manages the rewriting of context, control, and effect
23 // dependencies during lowering of a binop and contains numerous helper 23 // dependencies during lowering of a binop and contains numerous helper
24 // functions for matching the types of inputs to an operation. 24 // functions for matching the types of inputs to an operation.
25 class JSBinopReduction final { 25 class JSBinopReduction final {
26 public: 26 public:
27 JSBinopReduction(JSTypedLowering* lowering, Node* node) 27 JSBinopReduction(JSTypedLowering* lowering, Node* node)
28 : lowering_(lowering), node_(node) {} 28 : lowering_(lowering), node_(node) {}
29 29
30 BinaryOperationHints::Hint GetUsableNumberFeedback() {
31 if (!(lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) ||
32 !(lowering_->flags() & JSTypedLowering::kTypeFeedbackEnabled)) {
33 return BinaryOperationHints::kAny;
34 }
35 DCHECK_NE(0, node_->op()->ControlOutputCount());
36 DCHECK_EQ(1, node_->op()->EffectOutputCount());
37 DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node_->op()));
38 BinaryOperationHints hints = BinaryOperationHintsOf(node_->op());
39 BinaryOperationHints::Hint combined = hints.combined();
40 if (combined == BinaryOperationHints::kSignedSmall ||
41 combined == BinaryOperationHints::kSigned32 ||
42 combined == BinaryOperationHints::kNumberOrUndefined) {
43 return combined;
44 }
45 return BinaryOperationHints::kAny;
46 }
47
30 void ConvertInputsToNumberOrUndefined(Node* frame_state) { 48 void ConvertInputsToNumberOrUndefined(Node* frame_state) {
31 // To convert the inputs to numbers, we have to provide frame states 49 // To convert the inputs to numbers, we have to provide frame states
32 // for lazy bailouts in the ToNumber conversions. 50 // for lazy bailouts in the ToNumber conversions.
33 // We use a little hack here: we take the frame state before the binary 51 // We use a little hack here: we take the frame state before the binary
34 // operation and use it to construct the frame states for the conversion 52 // operation and use it to construct the frame states for the conversion
35 // so that after the deoptimization, the binary operation IC gets 53 // so that after the deoptimization, the binary operation IC gets
36 // already converted values from full code. This way we are sure that we 54 // already converted values from full code. This way we are sure that we
37 // will not re-do any of the side effects. 55 // will not re-do any of the side effects.
38 56
39 Node* left_input = nullptr; 57 Node* left_input = nullptr;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 // Insert an boolean not to invert the value. 118 // Insert an boolean not to invert the value.
101 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_); 119 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
102 node_->ReplaceUses(value); 120 node_->ReplaceUses(value);
103 // Note: ReplaceUses() smashes all uses, so smash it back here. 121 // Note: ReplaceUses() smashes all uses, so smash it back here.
104 value->ReplaceInput(0, node_); 122 value->ReplaceInput(0, node_);
105 return lowering_->Replace(value); 123 return lowering_->Replace(value);
106 } 124 }
107 return lowering_->Changed(node_); 125 return lowering_->Changed(node_);
108 } 126 }
109 127
128 Reduction ChangeToSpeculativeOperator(const Operator* op) {
129 DCHECK_EQ(1, op->EffectInputCount());
130 DCHECK_EQ(1, op->EffectOutputCount());
131 DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
132 DCHECK_EQ(1, op->ControlInputCount());
133 DCHECK_EQ(1, op->ControlOutputCount());
134 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(op));
135 DCHECK_EQ(2, op->ValueInputCount());
136
137 DCHECK_EQ(1, node_->op()->EffectInputCount());
138 DCHECK_EQ(1, node_->op()->EffectOutputCount());
139 DCHECK_EQ(1, node_->op()->ControlInputCount());
140 DCHECK_LT(1, node_->op()->ControlOutputCount());
141 DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node_->op()));
142 DCHECK_EQ(2, node_->op()->ValueInputCount());
143
144 // Reconnect the control output to bypass the IfSuccess node and
145 // possibly disconnect from the IfException node.
146 for (Edge edge : node_->use_edges()) {
147 Node* const user = edge.from();
148 DCHECK(!user->IsDead());
149 if (NodeProperties::IsControlEdge(edge)) {
150 if (user->opcode() == IrOpcode::kIfSuccess) {
151 user->ReplaceUses(node_);
152 user->Kill();
153 } else {
154 DCHECK_EQ(user->opcode(), IrOpcode::kIfException);
155 edge.UpdateTo(jsgraph()->Dead());
156 }
157 }
158 }
159
160 // Remove the lazy bailout frame state and the context.
161 node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_));
162 node_->RemoveInput(NodeProperties::FirstContextIndex(node_));
163
164 NodeProperties::ChangeOp(node_, op);
165
166 // Update the type to number.
167 Type* node_type = NodeProperties::GetType(node_);
168 NodeProperties::SetType(node_,
169 Type::Intersect(node_type, Type::Number(), zone()));
170
171 return lowering_->Changed(node_);
172 }
173
110 Reduction ChangeToPureOperator(const Operator* op, Type* type) { 174 Reduction ChangeToPureOperator(const Operator* op, Type* type) {
111 return ChangeToPureOperator(op, false, type); 175 return ChangeToPureOperator(op, false, type);
112 } 176 }
113 177
114 bool LeftInputIs(Type* t) { return left_type()->Is(t); } 178 bool LeftInputIs(Type* t) { return left_type()->Is(t); }
115 179
116 bool RightInputIs(Type* t) { return right_type()->Is(t); } 180 bool RightInputIs(Type* t) { return right_type()->Is(t); }
117 181
118 bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); } 182 bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); }
119 183
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 double max = kMaxInt / (1 << k); 397 double max = kMaxInt / (1 << k);
334 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); 398 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
335 } 399 }
336 } 400 }
337 401
338 402
339 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { 403 Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
340 if (flags() & kDisableBinaryOpReduction) return NoChange(); 404 if (flags() & kDisableBinaryOpReduction) return NoChange();
341 405
342 JSBinopReduction r(this, node); 406 JSBinopReduction r(this, node);
407
408 BinaryOperationHints::Hint feedback = r.GetUsableNumberFeedback();
409 if (feedback != BinaryOperationHints::kAny) {
410 // Lower to the optimistic number binop.
411 return r.ChangeToSpeculativeOperator(
412 simplified()->SpeculativeNumberAdd(feedback));
413 }
343 if (r.BothInputsAre(Type::NumberOrUndefined())) { 414 if (r.BothInputsAre(Type::NumberOrUndefined())) {
344 // JSAdd(x:number, y:number) => NumberAdd(x, y) 415 // JSAdd(x:number, y:number) => NumberAdd(x, y)
345 return ReduceNumberBinop(node, simplified()->NumberAdd()); 416 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
417 r.ConvertInputsToNumberOrUndefined(frame_state);
418 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
346 } 419 }
347 if (r.NeitherInputCanBe(Type::StringOrReceiver())) { 420 if (r.NeitherInputCanBe(Type::StringOrReceiver())) {
348 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) 421 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
349 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); 422 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
350 r.ConvertInputsToNumberOrUndefined(frame_state); 423 r.ConvertInputsToNumberOrUndefined(frame_state);
351 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); 424 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
352 } 425 }
353 if (r.OneInputIs(Type::String())) { 426 if (r.OneInputIs(Type::String())) {
354 StringAddFlags flags = STRING_ADD_CHECK_NONE; 427 StringAddFlags flags = STRING_ADD_CHECK_NONE;
355 if (!r.LeftInputIs(Type::String())) { 428 if (!r.LeftInputIs(Type::String())) {
(...skipping 24 matching lines...) Expand all
380 453
381 JSBinopReduction r(this, node); 454 JSBinopReduction r(this, node);
382 if (r.BothInputsAre(Type::Number())) { 455 if (r.BothInputsAre(Type::Number())) {
383 // JSModulus(x:number, x:number) => NumberModulus(x, y) 456 // JSModulus(x:number, x:number) => NumberModulus(x, y)
384 return r.ChangeToPureOperator(simplified()->NumberModulus(), 457 return r.ChangeToPureOperator(simplified()->NumberModulus(),
385 Type::Number()); 458 Type::Number());
386 } 459 }
387 return NoChange(); 460 return NoChange();
388 } 461 }
389 462
390 463 Reduction JSTypedLowering::ReduceJSSubtract(Node* node) {
391 Reduction JSTypedLowering::ReduceNumberBinop(Node* node,
392 const Operator* numberOp) {
393 if (flags() & kDisableBinaryOpReduction) return NoChange(); 464 if (flags() & kDisableBinaryOpReduction) return NoChange();
394
395 JSBinopReduction r(this, node); 465 JSBinopReduction r(this, node);
396 if (numberOp == simplified()->NumberModulus()) { 466 BinaryOperationHints::Hint feedback = r.GetUsableNumberFeedback();
397 if (r.BothInputsAre(Type::NumberOrUndefined())) { 467 if (feedback != BinaryOperationHints::kAny) {
398 return r.ChangeToPureOperator(numberOp, Type::Number()); 468 // Lower to the optimistic number binop.
399 } 469 return r.ChangeToSpeculativeOperator(
400 return NoChange(); 470 simplified()->SpeculativeNumberSubtract(feedback));
401 } 471 }
402 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); 472 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
403 r.ConvertInputsToNumberOrUndefined(frame_state); 473 r.ConvertInputsToNumberOrUndefined(frame_state);
404 return r.ChangeToPureOperator(numberOp, Type::Number()); 474 return r.ChangeToPureOperator(simplified()->NumberSubtract(), Type::Number());
475 }
476
477 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) {
478 if (flags() & kDisableBinaryOpReduction) return NoChange();
479 JSBinopReduction r(this, node);
480 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
481 r.ConvertInputsToNumberOrUndefined(frame_state);
482 return r.ChangeToPureOperator(simplified()->NumberMultiply(), Type::Number());
483 }
484
485 Reduction JSTypedLowering::ReduceJSDivide(Node* node) {
486 if (flags() & kDisableBinaryOpReduction) return NoChange();
487 JSBinopReduction r(this, node);
488 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
489 r.ConvertInputsToNumberOrUndefined(frame_state);
490 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number());
405 } 491 }
406 492
407 493
408 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) { 494 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) {
409 if (flags() & kDisableBinaryOpReduction) return NoChange(); 495 if (flags() & kDisableBinaryOpReduction) return NoChange();
410 496
411 JSBinopReduction r(this, node); 497 JSBinopReduction r(this, node);
412 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); 498 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
413 r.ConvertInputsToNumberOrUndefined(frame_state); 499 r.ConvertInputsToNumberOrUndefined(frame_state);
414 r.ConvertInputsToUI32(kSigned, kSigned); 500 r.ConvertInputsToUI32(kSigned, kSigned);
(...skipping 1363 matching lines...) Expand 10 before | Expand all | Expand 10 after
1778 case IrOpcode::kJSShiftLeft: 1864 case IrOpcode::kJSShiftLeft:
1779 return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftLeft()); 1865 return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftLeft());
1780 case IrOpcode::kJSShiftRight: 1866 case IrOpcode::kJSShiftRight:
1781 return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftRight()); 1867 return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftRight());
1782 case IrOpcode::kJSShiftRightLogical: 1868 case IrOpcode::kJSShiftRightLogical:
1783 return ReduceUI32Shift(node, kUnsigned, 1869 return ReduceUI32Shift(node, kUnsigned,
1784 simplified()->NumberShiftRightLogical()); 1870 simplified()->NumberShiftRightLogical());
1785 case IrOpcode::kJSAdd: 1871 case IrOpcode::kJSAdd:
1786 return ReduceJSAdd(node); 1872 return ReduceJSAdd(node);
1787 case IrOpcode::kJSSubtract: 1873 case IrOpcode::kJSSubtract:
1788 return ReduceNumberBinop(node, simplified()->NumberSubtract()); 1874 return ReduceJSSubtract(node);
1789 case IrOpcode::kJSMultiply: 1875 case IrOpcode::kJSMultiply:
1790 return ReduceNumberBinop(node, simplified()->NumberMultiply()); 1876 return ReduceJSMultiply(node);
1791 case IrOpcode::kJSDivide: 1877 case IrOpcode::kJSDivide:
1792 return ReduceNumberBinop(node, simplified()->NumberDivide()); 1878 return ReduceJSDivide(node);
1793 case IrOpcode::kJSModulus: 1879 case IrOpcode::kJSModulus:
1794 return ReduceJSModulus(node); 1880 return ReduceJSModulus(node);
1795 case IrOpcode::kJSToBoolean: 1881 case IrOpcode::kJSToBoolean:
1796 return ReduceJSToBoolean(node); 1882 return ReduceJSToBoolean(node);
1797 case IrOpcode::kJSToInteger: 1883 case IrOpcode::kJSToInteger:
1798 return ReduceJSToInteger(node); 1884 return ReduceJSToInteger(node);
1799 case IrOpcode::kJSToLength: 1885 case IrOpcode::kJSToLength:
1800 return ReduceJSToLength(node); 1886 return ReduceJSToLength(node);
1801 case IrOpcode::kJSToNumber: 1887 case IrOpcode::kJSToNumber:
1802 return ReduceJSToNumber(node); 1888 return ReduceJSToNumber(node);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1887 } 1973 }
1888 1974
1889 1975
1890 CompilationDependencies* JSTypedLowering::dependencies() const { 1976 CompilationDependencies* JSTypedLowering::dependencies() const {
1891 return dependencies_; 1977 return dependencies_;
1892 } 1978 }
1893 1979
1894 } // namespace compiler 1980 } // namespace compiler
1895 } // namespace internal 1981 } // namespace internal
1896 } // namespace v8 1982 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | src/compiler/opcodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698