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

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: Add tests for the checks and fix check insertion 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
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
174 Reduction ChangeToStringComparisonOperator(const Operator* op,
Benedikt Meurer 2016/05/30 18:39:50 This seems to reintroduce dead code. ChangeToStrin
Jarin 2016/05/31 20:28:52 Done.
175 bool invert = false) {
176 if (node_->op()->ControlInputCount() > 0) {
177 lowering_->RelaxControls(node_);
178 }
179 // String comparison operators need effect and control inputs, so copy them
180 // over.
181 Node* effect = NodeProperties::GetEffectInput(node_);
182 Node* control = NodeProperties::GetControlInput(node_);
183 node_->ReplaceInput(2, effect);
184 node_->ReplaceInput(3, control);
185
186 node_->TrimInputCount(4);
187 NodeProperties::ChangeOp(node_, op);
188
189 if (invert) {
190 // Insert a boolean-not to invert the value.
191 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
192 node_->ReplaceUses(value);
193 // Note: ReplaceUses() smashes all uses, so smash it back here.
194 value->ReplaceInput(0, node_);
195 return lowering_->Replace(value);
196 }
197 return lowering_->Changed(node_);
198 }
199
110 Reduction ChangeToPureOperator(const Operator* op, Type* type) { 200 Reduction ChangeToPureOperator(const Operator* op, Type* type) {
111 return ChangeToPureOperator(op, false, type); 201 return ChangeToPureOperator(op, false, type);
112 } 202 }
113 203
114 bool LeftInputIs(Type* t) { return left_type()->Is(t); } 204 bool LeftInputIs(Type* t) { return left_type()->Is(t); }
115 205
116 bool RightInputIs(Type* t) { return right_type()->Is(t); } 206 bool RightInputIs(Type* t) { return right_type()->Is(t); }
117 207
118 bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); } 208 bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); }
119 209
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 double max = kMaxInt / (1 << k); 423 double max = kMaxInt / (1 << k);
334 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); 424 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
335 } 425 }
336 } 426 }
337 427
338 428
339 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { 429 Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
340 if (flags() & kDisableBinaryOpReduction) return NoChange(); 430 if (flags() & kDisableBinaryOpReduction) return NoChange();
341 431
342 JSBinopReduction r(this, node); 432 JSBinopReduction r(this, node);
433
434 BinaryOperationHints::Hint feedback = r.GetUsableNumberFeedback();
435 if (feedback != BinaryOperationHints::kAny) {
436 // Lower to the optimistic number binop.
437 return r.ChangeToSpeculativeOperator(
438 simplified()->SpeculativeNumberAdd(feedback));
439 }
343 if (r.BothInputsAre(Type::NumberOrUndefined())) { 440 if (r.BothInputsAre(Type::NumberOrUndefined())) {
344 // JSAdd(x:number, y:number) => NumberAdd(x, y) 441 // JSAdd(x:number, y:number) => NumberAdd(x, y)
345 return ReduceNumberBinop(node, simplified()->NumberAdd()); 442 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
443 r.ConvertInputsToNumberOrUndefined(frame_state);
444 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
346 } 445 }
347 if (r.NeitherInputCanBe(Type::StringOrReceiver())) { 446 if (r.NeitherInputCanBe(Type::StringOrReceiver())) {
348 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) 447 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
349 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); 448 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
350 r.ConvertInputsToNumberOrUndefined(frame_state); 449 r.ConvertInputsToNumberOrUndefined(frame_state);
351 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); 450 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
352 } 451 }
353 if (r.OneInputIs(Type::String())) { 452 if (r.OneInputIs(Type::String())) {
354 StringAddFlags flags = STRING_ADD_CHECK_NONE; 453 StringAddFlags flags = STRING_ADD_CHECK_NONE;
355 if (!r.LeftInputIs(Type::String())) { 454 if (!r.LeftInputIs(Type::String())) {
(...skipping 24 matching lines...) Expand all
380 479
381 JSBinopReduction r(this, node); 480 JSBinopReduction r(this, node);
382 if (r.BothInputsAre(Type::Number())) { 481 if (r.BothInputsAre(Type::Number())) {
383 // JSModulus(x:number, x:number) => NumberModulus(x, y) 482 // JSModulus(x:number, x:number) => NumberModulus(x, y)
384 return r.ChangeToPureOperator(simplified()->NumberModulus(), 483 return r.ChangeToPureOperator(simplified()->NumberModulus(),
385 Type::Number()); 484 Type::Number());
386 } 485 }
387 return NoChange(); 486 return NoChange();
388 } 487 }
389 488
390 489 Reduction JSTypedLowering::ReduceJSSubtract(Node* node) {
391 Reduction JSTypedLowering::ReduceNumberBinop(Node* node,
392 const Operator* numberOp) {
393 if (flags() & kDisableBinaryOpReduction) return NoChange(); 490 if (flags() & kDisableBinaryOpReduction) return NoChange();
394
395 JSBinopReduction r(this, node); 491 JSBinopReduction r(this, node);
396 if (numberOp == simplified()->NumberModulus()) { 492 BinaryOperationHints::Hint feedback = r.GetUsableNumberFeedback();
397 if (r.BothInputsAre(Type::NumberOrUndefined())) { 493 if (feedback != BinaryOperationHints::kAny) {
398 return r.ChangeToPureOperator(numberOp, Type::Number()); 494 // Lower to the optimistic number binop.
399 } 495 return r.ChangeToSpeculativeOperator(
400 return NoChange(); 496 simplified()->SpeculativeNumberSubtract(feedback));
401 } 497 }
402 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); 498 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
403 r.ConvertInputsToNumberOrUndefined(frame_state); 499 r.ConvertInputsToNumberOrUndefined(frame_state);
404 return r.ChangeToPureOperator(numberOp, Type::Number()); 500 return r.ChangeToPureOperator(simplified()->NumberSubtract(), Type::Number());
501 }
502
503 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) {
504 if (flags() & kDisableBinaryOpReduction) return NoChange();
505 JSBinopReduction r(this, node);
506 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
507 r.ConvertInputsToNumberOrUndefined(frame_state);
508 return r.ChangeToPureOperator(simplified()->NumberMultiply(), Type::Number());
509 }
510
511 Reduction JSTypedLowering::ReduceJSDivide(Node* node) {
512 if (flags() & kDisableBinaryOpReduction) return NoChange();
513 JSBinopReduction r(this, node);
514 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
515 r.ConvertInputsToNumberOrUndefined(frame_state);
516 return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number());
405 } 517 }
406 518
407 519
408 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) { 520 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) {
409 if (flags() & kDisableBinaryOpReduction) return NoChange(); 521 if (flags() & kDisableBinaryOpReduction) return NoChange();
410 522
411 JSBinopReduction r(this, node); 523 JSBinopReduction r(this, node);
412 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); 524 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
413 r.ConvertInputsToNumberOrUndefined(frame_state); 525 r.ConvertInputsToNumberOrUndefined(frame_state);
414 r.ConvertInputsToUI32(kSigned, kSigned); 526 r.ConvertInputsToUI32(kSigned, kSigned);
(...skipping 1374 matching lines...) Expand 10 before | Expand all | Expand 10 after
1789 case IrOpcode::kJSShiftLeft: 1901 case IrOpcode::kJSShiftLeft:
1790 return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftLeft()); 1902 return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftLeft());
1791 case IrOpcode::kJSShiftRight: 1903 case IrOpcode::kJSShiftRight:
1792 return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftRight()); 1904 return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftRight());
1793 case IrOpcode::kJSShiftRightLogical: 1905 case IrOpcode::kJSShiftRightLogical:
1794 return ReduceUI32Shift(node, kUnsigned, 1906 return ReduceUI32Shift(node, kUnsigned,
1795 simplified()->NumberShiftRightLogical()); 1907 simplified()->NumberShiftRightLogical());
1796 case IrOpcode::kJSAdd: 1908 case IrOpcode::kJSAdd:
1797 return ReduceJSAdd(node); 1909 return ReduceJSAdd(node);
1798 case IrOpcode::kJSSubtract: 1910 case IrOpcode::kJSSubtract:
1799 return ReduceNumberBinop(node, simplified()->NumberSubtract()); 1911 return ReduceJSSubtract(node);
1800 case IrOpcode::kJSMultiply: 1912 case IrOpcode::kJSMultiply:
1801 return ReduceNumberBinop(node, simplified()->NumberMultiply()); 1913 return ReduceJSMultiply(node);
1802 case IrOpcode::kJSDivide: 1914 case IrOpcode::kJSDivide:
1803 return ReduceNumberBinop(node, simplified()->NumberDivide()); 1915 return ReduceJSDivide(node);
1804 case IrOpcode::kJSModulus: 1916 case IrOpcode::kJSModulus:
1805 return ReduceJSModulus(node); 1917 return ReduceJSModulus(node);
1806 case IrOpcode::kJSToBoolean: 1918 case IrOpcode::kJSToBoolean:
1807 return ReduceJSToBoolean(node); 1919 return ReduceJSToBoolean(node);
1808 case IrOpcode::kJSToInteger: 1920 case IrOpcode::kJSToInteger:
1809 return ReduceJSToInteger(node); 1921 return ReduceJSToInteger(node);
1810 case IrOpcode::kJSToLength: 1922 case IrOpcode::kJSToLength:
1811 return ReduceJSToLength(node); 1923 return ReduceJSToLength(node);
1812 case IrOpcode::kJSToNumber: 1924 case IrOpcode::kJSToNumber:
1813 return ReduceJSToNumber(node); 1925 return ReduceJSToNumber(node);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1898 } 2010 }
1899 2011
1900 2012
1901 CompilationDependencies* JSTypedLowering::dependencies() const { 2013 CompilationDependencies* JSTypedLowering::dependencies() const {
1902 return dependencies_; 2014 return dependencies_;
1903 } 2015 }
1904 2016
1905 } // namespace compiler 2017 } // namespace compiler
1906 } // namespace internal 2018 } // namespace internal
1907 } // namespace v8 2019 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698