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

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

Issue 1140583004: [turbofan] Add frame state before JavaScript comparisons. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Remove obsolete #if 0. Slightly refactor strong mode check. Created 5 years, 7 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/operator-properties.cc » ('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/compiler/access-builder.h" 6 #include "src/compiler/access-builder.h"
7 #include "src/compiler/js-graph.h" 7 #include "src/compiler/js-graph.h"
8 #include "src/compiler/js-typed-lowering.h" 8 #include "src/compiler/js-typed-lowering.h"
9 #include "src/compiler/linkage.h" 9 #include "src/compiler/linkage.h"
10 #include "src/compiler/node-matchers.h" 10 #include "src/compiler/node-matchers.h"
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 114
115 // A helper class to simplify the process of reducing a single binop node with a 115 // A helper class to simplify the process of reducing a single binop node with a
116 // JSOperator. This class manages the rewriting of context, control, and effect 116 // JSOperator. This class manages the rewriting of context, control, and effect
117 // dependencies during lowering of a binop and contains numerous helper 117 // dependencies during lowering of a binop and contains numerous helper
118 // functions for matching the types of inputs to an operation. 118 // functions for matching the types of inputs to an operation.
119 class JSBinopReduction final { 119 class JSBinopReduction final {
120 public: 120 public:
121 JSBinopReduction(JSTypedLowering* lowering, Node* node) 121 JSBinopReduction(JSTypedLowering* lowering, Node* node)
122 : lowering_(lowering), node_(node) {} 122 : lowering_(lowering), node_(node) {}
123 123
124 void ConvertPrimitiveInputsToNumber() {
125 node_->ReplaceInput(0, ConvertPrimitiveToNumber(left()));
126 node_->ReplaceInput(1, ConvertPrimitiveToNumber(right()));
127 }
128
129 void ConvertInputsToNumber(Node* frame_state) { 124 void ConvertInputsToNumber(Node* frame_state) {
130 // To convert the inputs to numbers, we have to provide frame states 125 // To convert the inputs to numbers, we have to provide frame states
131 // for lazy bailouts in the ToNumber conversions. 126 // for lazy bailouts in the ToNumber conversions.
132 // We use a little hack here: we take the frame state before the binary 127 // We use a little hack here: we take the frame state before the binary
133 // operation and use it to construct the frame states for the conversion 128 // operation and use it to construct the frame states for the conversion
134 // so that after the deoptimization, the binary operation IC gets 129 // so that after the deoptimization, the binary operation IC gets
135 // already converted values from full code. This way we are sure that we 130 // already converted values from full code. This way we are sure that we
136 // will not re-do any of the side effects. 131 // will not re-do any of the side effects.
137 132
138 Node* left_input = 133 Node* left_input =
139 left_type()->Is(Type::PlainPrimitive()) 134 left_type()->Is(Type::PlainPrimitive())
140 ? ConvertPrimitiveToNumber(left()) 135 ? ConvertPlainPrimitiveToNumber(left())
141 : ConvertToNumber(left(), 136 : ConvertToNumber(left(),
142 CreateFrameStateForLeftInput(frame_state)); 137 CreateFrameStateForLeftInput(frame_state));
143 138
144 Node* right_input = 139 Node* right_input =
145 right_type()->Is(Type::PlainPrimitive()) 140 right_type()->Is(Type::PlainPrimitive())
146 ? ConvertPrimitiveToNumber(right()) 141 ? ConvertPlainPrimitiveToNumber(right())
147 : ConvertToNumber(right(), CreateFrameStateForRightInput( 142 : ConvertToNumber(right(), CreateFrameStateForRightInput(
148 frame_state, left_input)); 143 frame_state, left_input));
149 144
150 node_->ReplaceInput(0, left_input); 145 node_->ReplaceInput(0, left_input);
151 node_->ReplaceInput(1, right_input); 146 node_->ReplaceInput(1, right_input);
152 } 147 }
153 148
154 void ConvertInputsToUI32(Signedness left_signedness, 149 void ConvertInputsToUI32(Signedness left_signedness,
155 Signedness right_signedness) { 150 Signedness right_signedness) {
156 node_->ReplaceInput(0, ConvertToUI32(left(), left_signedness)); 151 node_->ReplaceInput(0, ConvertToUI32(left(), left_signedness));
157 node_->ReplaceInput(1, ConvertToUI32(right(), right_signedness)); 152 node_->ReplaceInput(1, ConvertToUI32(right(), right_signedness));
158 } 153 }
159 154
160 void ConvertInputsToString() { 155 void ConvertInputsToString() {
161 node_->ReplaceInput(0, ConvertToString(left())); 156 node_->ReplaceInput(0, ConvertToString(left()));
162 node_->ReplaceInput(1, ConvertToString(right())); 157 node_->ReplaceInput(1, ConvertToString(right()));
163 } 158 }
164 159
165 // Convert inputs for bitwise shift operation (ES5 spec 11.7). 160 // Convert inputs for bitwise shift operation (ES5 spec 11.7).
166 void ConvertInputsForShift(Signedness left_signedness) { 161 void ConvertInputsForShift(Signedness left_signedness) {
167 node_->ReplaceInput( 162 node_->ReplaceInput(0, ConvertToUI32(ConvertPlainPrimitiveToNumber(left()),
168 0, ConvertToUI32(ConvertPrimitiveToNumber(left()), left_signedness)); 163 left_signedness));
169 Node* rnum = ConvertToUI32(ConvertPrimitiveToNumber(right()), kUnsigned); 164 Node* rnum =
165 ConvertToUI32(ConvertPlainPrimitiveToNumber(right()), kUnsigned);
170 Type* rnum_type = NodeProperties::GetBounds(rnum).upper; 166 Type* rnum_type = NodeProperties::GetBounds(rnum).upper;
171 if (!rnum_type->Is(lowering_->zero_thirtyone_range_)) { 167 if (!rnum_type->Is(lowering_->zero_thirtyone_range_)) {
172 rnum = graph()->NewNode(machine()->Word32And(), rnum, 168 rnum = graph()->NewNode(machine()->Word32And(), rnum,
173 jsgraph()->Int32Constant(0x1F)); 169 jsgraph()->Int32Constant(0x1F));
174 } 170 }
175 node_->ReplaceInput(1, rnum); 171 node_->ReplaceInput(1, rnum);
176 } 172 }
177 173
178 void SwapInputs() { 174 void SwapInputs() {
179 Node* l = left(); 175 Node* l = left();
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 } 322 }
327 } 323 }
328 Node* new_stack = 324 Node* new_stack =
329 graph()->NewNode(stack->op(), stack->InputCount(), &new_values.front()); 325 graph()->NewNode(stack->op(), stack->InputCount(), &new_values.front());
330 326
331 return graph()->NewNode(op, frame_state->InputAt(0), 327 return graph()->NewNode(op, frame_state->InputAt(0),
332 frame_state->InputAt(1), new_stack, 328 frame_state->InputAt(1), new_stack,
333 frame_state->InputAt(3), frame_state->InputAt(4)); 329 frame_state->InputAt(3), frame_state->InputAt(4));
334 } 330 }
335 331
336 Node* ConvertPrimitiveToNumber(Node* node) { 332 Node* ConvertPlainPrimitiveToNumber(Node* node) {
337 return lowering_->ConvertPrimitiveToNumber(node); 333 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive()));
334 // Avoid inserting too many eager ToNumber() operations.
335 Reduction const reduction = lowering_->ReduceJSToNumberInput(node);
336 if (reduction.Changed()) return reduction.replacement();
337 // TODO(jarin) Use PlainPrimitiveToNumber once we have it.
338 return graph()->NewNode(
339 javascript()->ToNumber(), node, jsgraph()->NoContextConstant(),
340 jsgraph()->EmptyFrameState(), graph()->start(), graph()->start());
338 } 341 }
339 342
340 Node* ConvertToNumber(Node* node, Node* frame_state) { 343 Node* ConvertToNumber(Node* node, Node* frame_state) {
341 if (NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive())) { 344 if (NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive())) {
342 return ConvertPrimitiveToNumber(node); 345 return ConvertPlainPrimitiveToNumber(node);
343 } else { 346 } else {
344 Node* const n = 347 Node* const n =
345 graph()->NewNode(javascript()->ToNumber(), node, context(), 348 graph()->NewNode(javascript()->ToNumber(), node, context(),
346 frame_state, effect(), control()); 349 frame_state, effect(), control());
347 update_effect(n); 350 update_effect(n);
348 return n; 351 return n;
349 } 352 }
350 } 353 }
351 354
352 Node* ConvertToUI32(Node* node, Signedness signedness) { 355 Node* ConvertToUI32(Node* node, Signedness signedness) {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 break; 466 break;
464 case IrOpcode::kJSGreaterThanOrEqual: 467 case IrOpcode::kJSGreaterThanOrEqual:
465 stringOp = simplified()->StringLessThanOrEqual(); 468 stringOp = simplified()->StringLessThanOrEqual();
466 r.SwapInputs(); // a >= b => b <= a 469 r.SwapInputs(); // a >= b => b <= a
467 break; 470 break;
468 default: 471 default:
469 return NoChange(); 472 return NoChange();
470 } 473 }
471 return r.ChangeToPureOperator(stringOp); 474 return r.ChangeToPureOperator(stringOp);
472 } 475 }
473 if (r.IsStrong() && !r.BothInputsAre(Type::Number())) { 476 if (r.OneInputCannotBe(Type::StringOrReceiver())) {
474 return NoChange();
475 }
476 #if 0
477 // TODO(turbofan): General ToNumber disabled for now because:
478 // a) The inserted ToNumber operation screws up observability of valueOf.
479 // b) Deoptimization at ToNumber doesn't have corresponding bailout id.
480 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone());
481 if (r.OneInputCannotBe(maybe_string)) {
482 // If one input cannot be a string, then emit a number comparison.
483 ...
484 }
485 #endif
486 if (r.BothInputsAre(Type::PlainPrimitive()) &&
487 r.OneInputCannotBe(Type::StringOrReceiver())) {
488 const Operator* less_than; 477 const Operator* less_than;
489 const Operator* less_than_or_equal; 478 const Operator* less_than_or_equal;
490 if (r.BothInputsAre(Type::Unsigned32())) { 479 if (r.BothInputsAre(Type::Unsigned32())) {
491 less_than = machine()->Uint32LessThan(); 480 less_than = machine()->Uint32LessThan();
492 less_than_or_equal = machine()->Uint32LessThanOrEqual(); 481 less_than_or_equal = machine()->Uint32LessThanOrEqual();
493 } else if (r.BothInputsAre(Type::Signed32())) { 482 } else if (r.BothInputsAre(Type::Signed32())) {
494 less_than = machine()->Int32LessThan(); 483 less_than = machine()->Int32LessThan();
495 less_than_or_equal = machine()->Int32LessThanOrEqual(); 484 less_than_or_equal = machine()->Int32LessThanOrEqual();
496 } else { 485 } else {
497 // TODO(turbofan): mixed signed/unsigned int32 comparisons. 486 // TODO(turbofan): mixed signed/unsigned int32 comparisons.
498 r.ConvertPrimitiveInputsToNumber(); 487 if (r.IsStrong() && !r.BothInputsAre(Type::Number())) {
488 return NoChange();
489 }
490 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
491 r.ConvertInputsToNumber(frame_state);
499 less_than = simplified()->NumberLessThan(); 492 less_than = simplified()->NumberLessThan();
500 less_than_or_equal = simplified()->NumberLessThanOrEqual(); 493 less_than_or_equal = simplified()->NumberLessThanOrEqual();
501 } 494 }
502 const Operator* comparison; 495 const Operator* comparison;
503 switch (node->opcode()) { 496 switch (node->opcode()) {
504 case IrOpcode::kJSLessThan: 497 case IrOpcode::kJSLessThan:
505 comparison = less_than; 498 comparison = less_than;
506 break; 499 break;
507 case IrOpcode::kJSGreaterThan: 500 case IrOpcode::kJSGreaterThan:
508 comparison = less_than; 501 comparison = less_than;
(...skipping 676 matching lines...) Expand 10 before | Expand all | Expand 10 after
1185 return ReduceJSCreateWithContext(node); 1178 return ReduceJSCreateWithContext(node);
1186 case IrOpcode::kJSCreateBlockContext: 1179 case IrOpcode::kJSCreateBlockContext:
1187 return ReduceJSCreateBlockContext(node); 1180 return ReduceJSCreateBlockContext(node);
1188 default: 1181 default:
1189 break; 1182 break;
1190 } 1183 }
1191 return NoChange(); 1184 return NoChange();
1192 } 1185 }
1193 1186
1194 1187
1195 Node* JSTypedLowering::ConvertPrimitiveToNumber(Node* input) {
1196 DCHECK(NodeProperties::GetBounds(input).upper->Is(Type::PlainPrimitive()));
1197 // Avoid inserting too many eager ToNumber() operations.
1198 Reduction const reduction = ReduceJSToNumberInput(input);
1199 if (reduction.Changed()) return reduction.replacement();
1200 // TODO(jarin) Use PlainPrimitiveToNumber once we have it.
1201 return graph()->NewNode(
1202 javascript()->ToNumber(), input, jsgraph()->NoContextConstant(),
1203 jsgraph()->EmptyFrameState(), graph()->start(), graph()->start());
1204 }
1205
1206
1207 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) { 1188 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) {
1208 if (rhs == 0) return lhs; 1189 if (rhs == 0) return lhs;
1209 return graph()->NewNode(machine()->Word32Shl(), lhs, 1190 return graph()->NewNode(machine()->Word32Shl(), lhs,
1210 jsgraph()->Int32Constant(rhs)); 1191 jsgraph()->Int32Constant(rhs));
1211 } 1192 }
1212 1193
1213 1194
1214 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); } 1195 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); }
1215 1196
1216 1197
(...skipping 10 matching lines...) Expand all
1227 } 1208 }
1228 1209
1229 1210
1230 MachineOperatorBuilder* JSTypedLowering::machine() const { 1211 MachineOperatorBuilder* JSTypedLowering::machine() const {
1231 return jsgraph()->machine(); 1212 return jsgraph()->machine();
1232 } 1213 }
1233 1214
1234 } // namespace compiler 1215 } // namespace compiler
1235 } // namespace internal 1216 } // namespace internal
1236 } // namespace v8 1217 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | src/compiler/operator-properties.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698