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

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

Issue 1884713003: [turbofan] Change number operations to handle Undefined as well. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Tweaks Created 4 years, 8 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 void ConvertInputsToNumber(Node* frame_state) { 30 void ConvertInputsToNumberOrUndefined(Node* frame_state) {
31 // To convert the inputs to numbers, we have to provide frame states 31 // To convert the inputs to numbers, we have to provide frame states
32 // for lazy bailouts in the ToNumber conversions. 32 // for lazy bailouts in the ToNumber conversions.
33 // We use a little hack here: we take the frame state before the binary 33 // 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 34 // operation and use it to construct the frame states for the conversion
35 // so that after the deoptimization, the binary operation IC gets 35 // so that after the deoptimization, the binary operation IC gets
36 // already converted values from full code. This way we are sure that we 36 // already converted values from full code. This way we are sure that we
37 // will not re-do any of the side effects. 37 // will not re-do any of the side effects.
38 38
39 Node* left_input = nullptr; 39 Node* left_input = nullptr;
40 Node* right_input = nullptr; 40 Node* right_input = nullptr;
41 bool left_is_primitive = left_type()->Is(Type::PlainPrimitive()); 41 bool left_is_primitive = left_type()->Is(Type::PlainPrimitive());
42 bool right_is_primitive = right_type()->Is(Type::PlainPrimitive()); 42 bool right_is_primitive = right_type()->Is(Type::PlainPrimitive());
43 bool handles_exception = NodeProperties::IsExceptionalCall(node_); 43 bool handles_exception = NodeProperties::IsExceptionalCall(node_);
44 44
45 if (!left_is_primitive && !right_is_primitive && handles_exception) { 45 if (!left_is_primitive && !right_is_primitive && handles_exception) {
46 ConvertBothInputsToNumber(&left_input, &right_input, frame_state); 46 ConvertBothInputsToNumber(&left_input, &right_input, frame_state);
47 } else { 47 } else {
48 left_input = left_is_primitive 48 left_input = left_is_primitive
49 ? ConvertPlainPrimitiveToNumber(left()) 49 ? ConvertPlainPrimitiveToNumberOrUndefined(left())
50 : ConvertSingleInputToNumber( 50 : ConvertSingleInputToNumber(
51 left(), CreateFrameStateForLeftInput(frame_state)); 51 left(), CreateFrameStateForLeftInput(frame_state));
52 right_input = right_is_primitive 52 right_input = right_is_primitive
53 ? ConvertPlainPrimitiveToNumber(right()) 53 ? ConvertPlainPrimitiveToNumberOrUndefined(right())
54 : ConvertSingleInputToNumber( 54 : ConvertSingleInputToNumber(
55 right(), CreateFrameStateForRightInput( 55 right(), CreateFrameStateForRightInput(
56 frame_state, left_input)); 56 frame_state, left_input));
57 } 57 }
58 58
59 node_->ReplaceInput(0, left_input); 59 node_->ReplaceInput(0, left_input);
60 node_->ReplaceInput(1, right_input); 60 node_->ReplaceInput(1, right_input);
61 } 61 }
62 62
63 void ConvertInputsToUI32(Signedness left_signedness, 63 void ConvertInputsToUI32(Signedness left_signedness,
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 graph()->NewNode(stack->op(), stack->InputCount(), &new_values.front()); 235 graph()->NewNode(stack->op(), stack->InputCount(), &new_values.front());
236 236
237 return graph()->NewNode( 237 return graph()->NewNode(
238 op, frame_state->InputAt(kFrameStateParametersInput), 238 op, frame_state->InputAt(kFrameStateParametersInput),
239 frame_state->InputAt(kFrameStateLocalsInput), new_stack, 239 frame_state->InputAt(kFrameStateLocalsInput), new_stack,
240 frame_state->InputAt(kFrameStateContextInput), 240 frame_state->InputAt(kFrameStateContextInput),
241 frame_state->InputAt(kFrameStateFunctionInput), 241 frame_state->InputAt(kFrameStateFunctionInput),
242 frame_state->InputAt(kFrameStateOuterStateInput)); 242 frame_state->InputAt(kFrameStateOuterStateInput));
243 } 243 }
244 244
245 Node* ConvertPlainPrimitiveToNumber(Node* node) { 245 Node* ConvertPlainPrimitiveToNumberOrUndefined(Node* node) {
246 DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive())); 246 DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
247 if (NodeProperties::GetType(node)->Is(Type::NumberOrUndefined())) {
248 return node;
249 }
247 // Avoid inserting too many eager ToNumber() operations. 250 // Avoid inserting too many eager ToNumber() operations.
248 Reduction const reduction = lowering_->ReduceJSToNumberInput(node); 251 Reduction const reduction = lowering_->ReduceJSToNumberInput(node);
249 if (reduction.Changed()) return reduction.replacement(); 252 if (reduction.Changed()) return reduction.replacement();
250 // TODO(jarin) Use PlainPrimitiveToNumber once we have it. 253 // TODO(jarin) Use PlainPrimitiveToNumber once we have it.
251 return graph()->NewNode( 254 return graph()->NewNode(
252 javascript()->ToNumber(), node, jsgraph()->NoContextConstant(), 255 javascript()->ToNumber(), node, jsgraph()->NoContextConstant(),
253 jsgraph()->EmptyFrameState(), graph()->start(), graph()->start()); 256 jsgraph()->EmptyFrameState(), graph()->start(), graph()->start());
254 } 257 }
255 258
256 Node* ConvertSingleInputToNumber(Node* node, Node* frame_state) { 259 Node* ConvertSingleInputToNumber(Node* node, Node* frame_state) {
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 double max = kMaxInt / (1 << k); 357 double max = kMaxInt / (1 << k);
355 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); 358 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
356 } 359 }
357 } 360 }
358 361
359 362
360 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { 363 Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
361 if (flags() & kDisableBinaryOpReduction) return NoChange(); 364 if (flags() & kDisableBinaryOpReduction) return NoChange();
362 365
363 JSBinopReduction r(this, node); 366 JSBinopReduction r(this, node);
364 if (r.BothInputsAre(Type::Number())) { 367 if (r.BothInputsAre(Type::NumberOrUndefined())) {
365 // JSAdd(x:number, y:number) => NumberAdd(x, y) 368 // JSAdd(x:number, y:number) => NumberAdd(x, y)
366 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); 369 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
367 } 370 }
368 if (r.NeitherInputCanBe(Type::StringOrReceiver())) { 371 if (r.NeitherInputCanBe(Type::StringOrReceiver())) {
369 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) 372 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
370 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); 373 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
371 r.ConvertInputsToNumber(frame_state); 374 r.ConvertInputsToNumberOrUndefined(frame_state);
372 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); 375 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
373 } 376 }
374 if (r.BothInputsAre(Type::String())) { 377 if (r.BothInputsAre(Type::String())) {
375 // JSAdd(x:string, y:string) => CallStub[StringAdd](x, y) 378 // JSAdd(x:string, y:string) => CallStub[StringAdd](x, y)
376 Callable const callable = 379 Callable const callable =
377 CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED); 380 CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
378 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor( 381 CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
379 isolate(), graph()->zone(), callable.descriptor(), 0, 382 isolate(), graph()->zone(), callable.descriptor(), 0,
380 CallDescriptor::kNeedsFrameState, node->op()->properties()); 383 CallDescriptor::kNeedsFrameState, node->op()->properties());
381 DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node->op())); 384 DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node->op()));
(...skipping 19 matching lines...) Expand all
401 return NoChange(); 404 return NoChange();
402 } 405 }
403 406
404 407
405 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, 408 Reduction JSTypedLowering::ReduceNumberBinop(Node* node,
406 const Operator* numberOp) { 409 const Operator* numberOp) {
407 if (flags() & kDisableBinaryOpReduction) return NoChange(); 410 if (flags() & kDisableBinaryOpReduction) return NoChange();
408 411
409 JSBinopReduction r(this, node); 412 JSBinopReduction r(this, node);
410 if (numberOp == simplified()->NumberModulus()) { 413 if (numberOp == simplified()->NumberModulus()) {
411 if (r.BothInputsAre(Type::Number())) { 414 if (r.BothInputsAre(Type::NumberOrUndefined())) {
412 return r.ChangeToPureOperator(numberOp, Type::Number()); 415 return r.ChangeToPureOperator(numberOp, Type::Number());
413 } 416 }
414 return NoChange(); 417 return NoChange();
415 } 418 }
416 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); 419 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
417 r.ConvertInputsToNumber(frame_state); 420 r.ConvertInputsToNumberOrUndefined(frame_state);
418 return r.ChangeToPureOperator(numberOp, Type::Number()); 421 return r.ChangeToPureOperator(numberOp, Type::Number());
419 } 422 }
420 423
421 424
422 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) { 425 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) {
423 if (flags() & kDisableBinaryOpReduction) return NoChange(); 426 if (flags() & kDisableBinaryOpReduction) return NoChange();
424 427
425 JSBinopReduction r(this, node); 428 JSBinopReduction r(this, node);
426 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); 429 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
427 r.ConvertInputsToNumber(frame_state); 430 r.ConvertInputsToNumberOrUndefined(frame_state);
428 r.ConvertInputsToUI32(kSigned, kSigned); 431 r.ConvertInputsToUI32(kSigned, kSigned);
429 return r.ChangeToPureOperator(intOp, Type::Integral32()); 432 return r.ChangeToPureOperator(intOp, Type::Integral32());
430 } 433 }
431 434
432 435
433 Reduction JSTypedLowering::ReduceUI32Shift(Node* node, 436 Reduction JSTypedLowering::ReduceUI32Shift(Node* node,
434 Signedness left_signedness, 437 Signedness left_signedness,
435 const Operator* shift_op) { 438 const Operator* shift_op) {
436 if (flags() & kDisableBinaryOpReduction) return NoChange(); 439 if (flags() & kDisableBinaryOpReduction) return NoChange();
437 440
438 JSBinopReduction r(this, node); 441 JSBinopReduction r(this, node);
439 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); 442 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
440 r.ConvertInputsToNumber(frame_state); 443 // TODO(jarin) FIX
444 r.ConvertInputsToNumberOrUndefined(frame_state);
441 r.ConvertInputsToUI32(left_signedness, kUnsigned); 445 r.ConvertInputsToUI32(left_signedness, kUnsigned);
442 return r.ChangeToPureOperator(shift_op); 446 return r.ChangeToPureOperator(shift_op);
443 } 447 }
444 448
445 449
446 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { 450 Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
447 if (flags() & kDisableBinaryOpReduction) return NoChange(); 451 if (flags() & kDisableBinaryOpReduction) return NoChange();
448 452
449 JSBinopReduction r(this, node); 453 JSBinopReduction r(this, node);
450 if (r.BothInputsAre(Type::String())) { 454 if (r.BothInputsAre(Type::String())) {
(...skipping 25 matching lines...) Expand all
476 const Operator* less_than_or_equal; 480 const Operator* less_than_or_equal;
477 if (r.BothInputsAre(Type::Unsigned32())) { 481 if (r.BothInputsAre(Type::Unsigned32())) {
478 less_than = machine()->Uint32LessThan(); 482 less_than = machine()->Uint32LessThan();
479 less_than_or_equal = machine()->Uint32LessThanOrEqual(); 483 less_than_or_equal = machine()->Uint32LessThanOrEqual();
480 } else if (r.BothInputsAre(Type::Signed32())) { 484 } else if (r.BothInputsAre(Type::Signed32())) {
481 less_than = machine()->Int32LessThan(); 485 less_than = machine()->Int32LessThan();
482 less_than_or_equal = machine()->Int32LessThanOrEqual(); 486 less_than_or_equal = machine()->Int32LessThanOrEqual();
483 } else { 487 } else {
484 // TODO(turbofan): mixed signed/unsigned int32 comparisons. 488 // TODO(turbofan): mixed signed/unsigned int32 comparisons.
485 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); 489 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
486 r.ConvertInputsToNumber(frame_state); 490 // TODO(jarin) FIX
491 r.ConvertInputsToNumberOrUndefined(frame_state);
487 less_than = simplified()->NumberLessThan(); 492 less_than = simplified()->NumberLessThan();
488 less_than_or_equal = simplified()->NumberLessThanOrEqual(); 493 less_than_or_equal = simplified()->NumberLessThanOrEqual();
489 } 494 }
490 const Operator* comparison; 495 const Operator* comparison;
491 switch (node->opcode()) { 496 switch (node->opcode()) {
492 case IrOpcode::kJSLessThan: 497 case IrOpcode::kJSLessThan:
493 comparison = less_than; 498 comparison = less_than;
494 break; 499 break;
495 case IrOpcode::kJSGreaterThan: 500 case IrOpcode::kJSGreaterThan:
496 comparison = less_than; 501 comparison = less_than;
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 simplified()->ReferenceEqual(Type::Receiver()), invert); 603 simplified()->ReferenceEqual(Type::Receiver()), invert);
599 } 604 }
600 if (r.BothInputsAre(Type::Unique())) { 605 if (r.BothInputsAre(Type::Unique())) {
601 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Unique()), 606 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Unique()),
602 invert); 607 invert);
603 } 608 }
604 if (r.BothInputsAre(Type::String())) { 609 if (r.BothInputsAre(Type::String())) {
605 return r.ChangeToStringComparisonOperator(simplified()->StringEqual(), 610 return r.ChangeToStringComparisonOperator(simplified()->StringEqual(),
606 invert); 611 invert);
607 } 612 }
608 if (r.BothInputsAre(Type::Number())) { 613 if (r.BothInputsAre(Type::NumberOrUndefined())) {
609 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); 614 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
610 } 615 }
611 // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types) 616 // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types)
612 return NoChange(); 617 return NoChange();
613 } 618 }
614 619
615 620
616 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { 621 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
617 Node* const input = node->InputAt(0); 622 Node* const input = node->InputAt(0);
618 Type* const input_type = NodeProperties::GetType(input); 623 Type* const input_type = NodeProperties::GetType(input);
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
1005 key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) { 1010 key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
1006 // JSLoadProperty(typed-array, int32) 1011 // JSLoadProperty(typed-array, int32)
1007 Handle<FixedTypedArrayBase> elements = 1012 Handle<FixedTypedArrayBase> elements =
1008 Handle<FixedTypedArrayBase>::cast(handle(array->elements())); 1013 Handle<FixedTypedArrayBase>::cast(handle(array->elements()));
1009 Node* buffer = jsgraph()->PointerConstant(elements->external_pointer()); 1014 Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
1010 Node* length = jsgraph()->Constant(byte_length); 1015 Node* length = jsgraph()->Constant(byte_length);
1011 Node* context = NodeProperties::GetContextInput(node); 1016 Node* context = NodeProperties::GetContextInput(node);
1012 Node* effect = NodeProperties::GetEffectInput(node); 1017 Node* effect = NodeProperties::GetEffectInput(node);
1013 Node* control = NodeProperties::GetControlInput(node); 1018 Node* control = NodeProperties::GetControlInput(node);
1014 // Convert to a number first. 1019 // Convert to a number first.
1015 if (!value_type->Is(Type::Number())) { 1020 if (!value_type->Is(Type::NumberOrUndefined())) {
1016 Reduction number_reduction = ReduceJSToNumberInput(value); 1021 Reduction number_reduction = ReduceJSToNumberInput(value);
1017 if (number_reduction.Changed()) { 1022 if (number_reduction.Changed()) {
1018 value = number_reduction.replacement(); 1023 value = number_reduction.replacement();
1019 } else { 1024 } else {
1020 Node* frame_state_for_to_number = 1025 Node* frame_state_for_to_number =
1021 NodeProperties::GetFrameStateInput(node, 1); 1026 NodeProperties::GetFrameStateInput(node, 1);
1022 value = effect = 1027 value = effect =
1023 graph()->NewNode(javascript()->ToNumber(), value, context, 1028 graph()->NewNode(javascript()->ToNumber(), value, context,
1024 frame_state_for_to_number, effect, control); 1029 frame_state_for_to_number, effect, control);
1025 } 1030 }
(...skipping 781 matching lines...) Expand 10 before | Expand all | Expand 10 after
1807 } 1812 }
1808 1813
1809 1814
1810 CompilationDependencies* JSTypedLowering::dependencies() const { 1815 CompilationDependencies* JSTypedLowering::dependencies() const {
1811 return dependencies_; 1816 return dependencies_;
1812 } 1817 }
1813 1818
1814 } // namespace compiler 1819 } // namespace compiler
1815 } // namespace internal 1820 } // namespace internal
1816 } // namespace v8 1821 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698