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

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

Issue 2381523002: [Turbofan] Introduce OtherNumberConstant. (Closed)
Patch Set: Better DCHECK in HeapConstantType(). Created 4 years, 2 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-create-lowering.cc ('k') | src/compiler/operation-typer.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/compiler/js-typed-lowering.h" 5 #include "src/compiler/js-typed-lowering.h"
6 6
7 #include "src/builtins/builtins-utils.h" 7 #include "src/builtins/builtins-utils.h"
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/compilation-dependencies.h" 9 #include "src/compilation-dependencies.h"
10 #include "src/compiler/access-builder.h" 10 #include "src/compiler/access-builder.h"
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 } 75 }
76 76
77 // Check if a string addition will definitely result in creating a ConsString, 77 // Check if a string addition will definitely result in creating a ConsString,
78 // i.e. if the combined length of the resulting string exceeds the ConsString 78 // i.e. if the combined length of the resulting string exceeds the ConsString
79 // minimum length. 79 // minimum length.
80 bool ShouldCreateConsString() { 80 bool ShouldCreateConsString() {
81 DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode()); 81 DCHECK_EQ(IrOpcode::kJSAdd, node_->opcode());
82 if (BothInputsAre(Type::String()) || 82 if (BothInputsAre(Type::String()) ||
83 ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) && 83 ((lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) &&
84 BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) { 84 BinaryOperationHintOf(node_->op()) == BinaryOperationHint::kString)) {
85 if (left_type()->IsConstant() && 85 if (left_type()->IsHeapConstant() &&
86 left_type()->AsConstant()->Value()->IsString()) { 86 left_type()->AsHeapConstant()->Value()->IsString()) {
87 Handle<String> left_string = 87 Handle<String> left_string =
88 Handle<String>::cast(left_type()->AsConstant()->Value()); 88 Handle<String>::cast(left_type()->AsHeapConstant()->Value());
89 if (left_string->length() >= ConsString::kMinLength) return true; 89 if (left_string->length() >= ConsString::kMinLength) return true;
90 } 90 }
91 if (right_type()->IsConstant() && 91 if (right_type()->IsHeapConstant() &&
92 right_type()->AsConstant()->Value()->IsString()) { 92 right_type()->AsHeapConstant()->Value()->IsString()) {
93 Handle<String> right_string = 93 Handle<String> right_string =
94 Handle<String>::cast(right_type()->AsConstant()->Value()); 94 Handle<String>::cast(right_type()->AsHeapConstant()->Value());
95 if (right_string->length() >= ConsString::kMinLength) return true; 95 if (right_string->length() >= ConsString::kMinLength) return true;
96 } 96 }
97 } 97 }
98 return false; 98 return false;
99 } 99 }
100 100
101 void ConvertInputsToNumber() { 101 void ConvertInputsToNumber() {
102 // To convert the inputs to numbers, we have to provide frame states 102 // To convert the inputs to numbers, we have to provide frame states
103 // for lazy bailouts in the ToNumber conversions. 103 // for lazy bailouts in the ToNumber conversions.
104 // We use a little hack here: we take the frame state before the binary 104 // We use a little hack here: we take the frame state before the binary
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 void update_effect(Node* effect) { 440 void update_effect(Node* effect) {
441 NodeProperties::ReplaceEffectInput(node_, effect); 441 NodeProperties::ReplaceEffectInput(node_, effect);
442 } 442 }
443 }; 443 };
444 444
445 445
446 // TODO(turbofan): js-typed-lowering improvements possible 446 // TODO(turbofan): js-typed-lowering improvements possible
447 // - immediately put in type bounds for all new nodes 447 // - immediately put in type bounds for all new nodes
448 // - relax effects from generic but not-side-effecting operations 448 // - relax effects from generic but not-side-effecting operations
449 449
450
451 JSTypedLowering::JSTypedLowering(Editor* editor, 450 JSTypedLowering::JSTypedLowering(Editor* editor,
452 CompilationDependencies* dependencies, 451 CompilationDependencies* dependencies,
453 Flags flags, JSGraph* jsgraph, Zone* zone) 452 Flags flags, JSGraph* jsgraph, Zone* zone)
454 : AdvancedReducer(editor), 453 : AdvancedReducer(editor),
455 dependencies_(dependencies), 454 dependencies_(dependencies),
456 flags_(flags), 455 flags_(flags),
457 jsgraph_(jsgraph), 456 jsgraph_(jsgraph),
458 the_hole_type_( 457 the_hole_type_(
459 Type::Constant(factory()->the_hole_value(), graph()->zone())), 458 Type::HeapConstant(factory()->the_hole_value(), graph()->zone())),
460 type_cache_(TypeCache::Get()) { 459 type_cache_(TypeCache::Get()) {
461 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { 460 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) {
462 double min = kMinInt / (1 << k); 461 double min = kMinInt / (1 << k);
463 double max = kMaxInt / (1 << k); 462 double max = kMaxInt / (1 << k);
464 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); 463 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
465 } 464 }
466 } 465 }
467 466
468 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { 467 Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
469 JSBinopReduction r(this, node); 468 JSBinopReduction r(this, node);
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 // Make sure {second} is actually a String. 590 // Make sure {second} is actually a String.
592 Type* second_type = NodeProperties::GetType(second); 591 Type* second_type = NodeProperties::GetType(second);
593 if (!second_type->Is(Type::String())) { 592 if (!second_type->Is(Type::String())) {
594 second = effect = 593 second = effect =
595 graph()->NewNode(simplified()->CheckString(), second, effect, control); 594 graph()->NewNode(simplified()->CheckString(), second, effect, control);
596 second_type = NodeProperties::GetType(second); 595 second_type = NodeProperties::GetType(second);
597 } 596 }
598 597
599 // Determine the {first} length. 598 // Determine the {first} length.
600 Node* first_length = 599 Node* first_length =
601 first_type->IsConstant() 600 first_type->IsHeapConstant()
602 ? jsgraph()->Constant( 601 ? jsgraph()->Constant(
603 Handle<String>::cast(first_type->AsConstant()->Value()) 602 Handle<String>::cast(first_type->AsHeapConstant()->Value())
604 ->length()) 603 ->length())
605 : effect = graph()->NewNode( 604 : effect = graph()->NewNode(
606 simplified()->LoadField(AccessBuilder::ForStringLength()), 605 simplified()->LoadField(AccessBuilder::ForStringLength()),
607 first, effect, control); 606 first, effect, control);
608 607
609 // Determine the {second} length. 608 // Determine the {second} length.
610 Node* second_length = 609 Node* second_length =
611 second_type->IsConstant() 610 second_type->IsHeapConstant()
612 ? jsgraph()->Constant( 611 ? jsgraph()->Constant(
613 Handle<String>::cast(second_type->AsConstant()->Value()) 612 Handle<String>::cast(second_type->AsHeapConstant()->Value())
614 ->length()) 613 ->length())
615 : effect = graph()->NewNode( 614 : effect = graph()->NewNode(
616 simplified()->LoadField(AccessBuilder::ForStringLength()), 615 simplified()->LoadField(AccessBuilder::ForStringLength()),
617 second, effect, control); 616 second, effect, control);
618 617
619 // Compute the resulting length. 618 // Compute the resulting length.
620 Node* length = 619 Node* length =
621 graph()->NewNode(simplified()->NumberAdd(), first_length, second_length); 620 graph()->NewNode(simplified()->NumberAdd(), first_length, second_length);
622 621
623 // Check if we would overflow the allowed maximum string length. 622 // Check if we would overflow the allowed maximum string length.
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 } 972 }
974 ReplaceWithValue(node, input); 973 ReplaceWithValue(node, input);
975 return Replace(input); 974 return Replace(input);
976 } 975 }
977 return NoChange(); 976 return NoChange();
978 } 977 }
979 978
980 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { 979 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
981 // Try constant-folding of JSToNumber with constant inputs. 980 // Try constant-folding of JSToNumber with constant inputs.
982 Type* input_type = NodeProperties::GetType(input); 981 Type* input_type = NodeProperties::GetType(input);
983 if (input_type->IsConstant()) { 982 if (input_type->IsHeapConstant()) {
984 Handle<Object> input_value = input_type->AsConstant()->Value(); 983 Handle<Object> input_value = input_type->AsHeapConstant()->Value();
985 if (input_value->IsString()) { 984 if (input_value->IsString()) {
986 return Replace(jsgraph()->Constant( 985 return Replace(jsgraph()->Constant(
987 String::ToNumber(Handle<String>::cast(input_value)))); 986 String::ToNumber(Handle<String>::cast(input_value))));
988 } else if (input_value->IsOddball()) { 987 } else if (input_value->IsOddball()) {
989 return Replace(jsgraph()->Constant( 988 return Replace(jsgraph()->Constant(
990 Oddball::ToNumber(Handle<Oddball>::cast(input_value)))); 989 Oddball::ToNumber(Handle<Oddball>::cast(input_value))));
991 } 990 }
992 } 991 }
993 if (input_type->Is(Type::Number())) { 992 if (input_type->Is(Type::Number())) {
994 // JSToNumber(x:number) => x 993 // JSToNumber(x:number) => x
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
1273 1272
1274 // If we are in a try block, don't optimize since the runtime call 1273 // If we are in a try block, don't optimize since the runtime call
1275 // in the proxy case can throw. 1274 // in the proxy case can throw.
1276 if (NodeProperties::IsExceptionalCall(node)) return NoChange(); 1275 if (NodeProperties::IsExceptionalCall(node)) return NoChange();
1277 1276
1278 JSBinopReduction r(this, node); 1277 JSBinopReduction r(this, node);
1279 Node* object = r.left(); 1278 Node* object = r.left();
1280 Node* effect = r.effect(); 1279 Node* effect = r.effect();
1281 Node* control = r.control(); 1280 Node* control = r.control();
1282 1281
1283 if (!r.right_type()->IsConstant() || 1282 if (!r.right_type()->IsHeapConstant() ||
1284 !r.right_type()->AsConstant()->Value()->IsJSFunction()) { 1283 !r.right_type()->AsHeapConstant()->Value()->IsJSFunction()) {
1285 return NoChange(); 1284 return NoChange();
1286 } 1285 }
1287 1286
1288 Handle<JSFunction> function = 1287 Handle<JSFunction> function =
1289 Handle<JSFunction>::cast(r.right_type()->AsConstant()->Value()); 1288 Handle<JSFunction>::cast(r.right_type()->AsHeapConstant()->Value());
1290 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); 1289 Handle<SharedFunctionInfo> shared(function->shared(), isolate());
1291 1290
1292 // Make sure the prototype of {function} is the %FunctionPrototype%, and it 1291 // Make sure the prototype of {function} is the %FunctionPrototype%, and it
1293 // already has a meaningful initial map (i.e. we constructed at least one 1292 // already has a meaningful initial map (i.e. we constructed at least one
1294 // instance using the constructor {function}). 1293 // instance using the constructor {function}).
1295 if (function->map()->prototype() != function->native_context()->closure() || 1294 if (function->map()->prototype() != function->native_context()->closure() ||
1296 function->map()->has_non_instance_prototype() || 1295 function->map()->has_non_instance_prototype() ||
1297 !function->has_initial_map()) { 1296 !function->has_initial_map()) {
1298 return NoChange(); 1297 return NoChange();
1299 } 1298 }
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1478 // Check if {receiver} is known to be a receiver. 1477 // Check if {receiver} is known to be a receiver.
1479 if (receiver_type->Is(Type::Receiver())) { 1478 if (receiver_type->Is(Type::Receiver())) {
1480 ReplaceWithValue(node, receiver, effect, control); 1479 ReplaceWithValue(node, receiver, effect, control);
1481 return Replace(receiver); 1480 return Replace(receiver);
1482 } 1481 }
1483 1482
1484 // If the {receiver} is known to be null or undefined, we can just replace it 1483 // If the {receiver} is known to be null or undefined, we can just replace it
1485 // with the global proxy unconditionally. 1484 // with the global proxy unconditionally.
1486 if (receiver_type->Is(Type::NullOrUndefined()) || 1485 if (receiver_type->Is(Type::NullOrUndefined()) ||
1487 mode == ConvertReceiverMode::kNullOrUndefined) { 1486 mode == ConvertReceiverMode::kNullOrUndefined) {
1488 if (context_type->IsConstant()) { 1487 if (context_type->IsHeapConstant()) {
1489 Handle<JSObject> global_proxy( 1488 Handle<JSObject> global_proxy(
1490 Handle<Context>::cast(context_type->AsConstant()->Value()) 1489 Handle<Context>::cast(context_type->AsHeapConstant()->Value())
1491 ->global_proxy(), 1490 ->global_proxy(),
1492 isolate()); 1491 isolate());
1493 receiver = jsgraph()->Constant(global_proxy); 1492 receiver = jsgraph()->Constant(global_proxy);
1494 } else { 1493 } else {
1495 Node* native_context = effect = graph()->NewNode( 1494 Node* native_context = effect = graph()->NewNode(
1496 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), 1495 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
1497 context, context, effect); 1496 context, context, effect);
1498 receiver = effect = graph()->NewNode( 1497 receiver = effect = graph()->NewNode(
1499 javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true), 1498 javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
1500 native_context, native_context, effect); 1499 native_context, native_context, effect);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1583 rconvert = econvert = graph()->NewNode( 1582 rconvert = econvert = graph()->NewNode(
1584 common()->Call(desc), jsgraph()->HeapConstant(callable.code()), 1583 common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
1585 receiver, context, frame_state, econvert); 1584 receiver, context, frame_state, econvert);
1586 } 1585 }
1587 1586
1588 // Replace {receiver} with global proxy of {context}. 1587 // Replace {receiver} with global proxy of {context}.
1589 Node* if_global = graph()->NewNode(common()->Merge(2), if_true1, if_true2); 1588 Node* if_global = graph()->NewNode(common()->Merge(2), if_true1, if_true2);
1590 Node* eglobal = effect; 1589 Node* eglobal = effect;
1591 Node* rglobal; 1590 Node* rglobal;
1592 { 1591 {
1593 if (context_type->IsConstant()) { 1592 if (context_type->IsHeapConstant()) {
1594 Handle<JSObject> global_proxy( 1593 Handle<JSObject> global_proxy(
1595 Handle<Context>::cast(context_type->AsConstant()->Value()) 1594 Handle<Context>::cast(context_type->AsHeapConstant()->Value())
1596 ->global_proxy(), 1595 ->global_proxy(),
1597 isolate()); 1596 isolate());
1598 rglobal = jsgraph()->Constant(global_proxy); 1597 rglobal = jsgraph()->Constant(global_proxy);
1599 } else { 1598 } else {
1600 Node* native_context = eglobal = graph()->NewNode( 1599 Node* native_context = eglobal = graph()->NewNode(
1601 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), 1600 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
1602 context, context, eglobal); 1601 context, context, eglobal);
1603 rglobal = eglobal = graph()->NewNode( 1602 rglobal = eglobal = graph()->NewNode(
1604 javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true), 1603 javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
1605 native_context, native_context, eglobal); 1604 native_context, native_context, eglobal);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1708 CallConstructParameters const& p = CallConstructParametersOf(node->op()); 1707 CallConstructParameters const& p = CallConstructParametersOf(node->op());
1709 DCHECK_LE(2u, p.arity()); 1708 DCHECK_LE(2u, p.arity());
1710 int const arity = static_cast<int>(p.arity() - 2); 1709 int const arity = static_cast<int>(p.arity() - 2);
1711 Node* target = NodeProperties::GetValueInput(node, 0); 1710 Node* target = NodeProperties::GetValueInput(node, 0);
1712 Type* target_type = NodeProperties::GetType(target); 1711 Type* target_type = NodeProperties::GetType(target);
1713 Node* new_target = NodeProperties::GetValueInput(node, arity + 1); 1712 Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
1714 Node* effect = NodeProperties::GetEffectInput(node); 1713 Node* effect = NodeProperties::GetEffectInput(node);
1715 Node* control = NodeProperties::GetControlInput(node); 1714 Node* control = NodeProperties::GetControlInput(node);
1716 1715
1717 // Check if {target} is a known JSFunction. 1716 // Check if {target} is a known JSFunction.
1718 if (target_type->IsConstant() && 1717 if (target_type->IsHeapConstant() &&
1719 target_type->AsConstant()->Value()->IsJSFunction()) { 1718 target_type->AsHeapConstant()->Value()->IsJSFunction()) {
1720 Handle<JSFunction> function = 1719 Handle<JSFunction> function =
1721 Handle<JSFunction>::cast(target_type->AsConstant()->Value()); 1720 Handle<JSFunction>::cast(target_type->AsHeapConstant()->Value());
1722 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); 1721 Handle<SharedFunctionInfo> shared(function->shared(), isolate());
1723 const int builtin_index = shared->construct_stub()->builtin_index(); 1722 const int builtin_index = shared->construct_stub()->builtin_index();
1724 const bool is_builtin = (builtin_index != -1); 1723 const bool is_builtin = (builtin_index != -1);
1725 1724
1726 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; 1725 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
1727 1726
1728 if (is_builtin && Builtins::HasCppImplementation(builtin_index) && 1727 if (is_builtin && Builtins::HasCppImplementation(builtin_index) &&
1729 !NeedsArgumentAdaptorFrame(shared, arity)) { 1728 !NeedsArgumentAdaptorFrame(shared, arity)) {
1730 // Patch {node} to a direct CEntryStub call. 1729 // Patch {node} to a direct CEntryStub call.
1731 1730
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1793 Node* frame_state = NodeProperties::FindFrameStateBefore(node); 1792 Node* frame_state = NodeProperties::FindFrameStateBefore(node);
1794 1793
1795 // Try to infer receiver {convert_mode} from {receiver} type. 1794 // Try to infer receiver {convert_mode} from {receiver} type.
1796 if (receiver_type->Is(Type::NullOrUndefined())) { 1795 if (receiver_type->Is(Type::NullOrUndefined())) {
1797 convert_mode = ConvertReceiverMode::kNullOrUndefined; 1796 convert_mode = ConvertReceiverMode::kNullOrUndefined;
1798 } else if (!receiver_type->Maybe(Type::NullOrUndefined())) { 1797 } else if (!receiver_type->Maybe(Type::NullOrUndefined())) {
1799 convert_mode = ConvertReceiverMode::kNotNullOrUndefined; 1798 convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
1800 } 1799 }
1801 1800
1802 // Check if {target} is a known JSFunction. 1801 // Check if {target} is a known JSFunction.
1803 if (target_type->IsConstant() && 1802 if (target_type->IsHeapConstant() &&
1804 target_type->AsConstant()->Value()->IsJSFunction()) { 1803 target_type->AsHeapConstant()->Value()->IsJSFunction()) {
1805 Handle<JSFunction> function = 1804 Handle<JSFunction> function =
1806 Handle<JSFunction>::cast(target_type->AsConstant()->Value()); 1805 Handle<JSFunction>::cast(target_type->AsHeapConstant()->Value());
1807 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); 1806 Handle<SharedFunctionInfo> shared(function->shared(), isolate());
1808 const int builtin_index = shared->code()->builtin_index(); 1807 const int builtin_index = shared->code()->builtin_index();
1809 const bool is_builtin = (builtin_index != -1); 1808 const bool is_builtin = (builtin_index != -1);
1810 1809
1811 // Class constructors are callable, but [[Call]] will raise an exception. 1810 // Class constructors are callable, but [[Call]] will raise an exception.
1812 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ). 1811 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
1813 if (IsClassConstructor(shared->kind())) return NoChange(); 1812 if (IsClassConstructor(shared->kind())) return NoChange();
1814 1813
1815 // Load the context from the {target}. 1814 // Load the context from the {target}.
1816 Node* context = effect = graph()->NewNode( 1815 Node* context = effect = graph()->NewNode(
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
2141 } 2140 }
2142 2141
2143 2142
2144 CompilationDependencies* JSTypedLowering::dependencies() const { 2143 CompilationDependencies* JSTypedLowering::dependencies() const {
2145 return dependencies_; 2144 return dependencies_;
2146 } 2145 }
2147 2146
2148 } // namespace compiler 2147 } // namespace compiler
2149 } // namespace internal 2148 } // namespace internal
2150 } // namespace v8 2149 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-create-lowering.cc ('k') | src/compiler/operation-typer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698