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

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

Issue 1407413014: [turbofan] Pseudo-inline instanceof (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Pre-dinner try Created 5 years, 1 month 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/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"
11 #include "src/compiler/node-properties.h" 11 #include "src/compiler/node-properties.h"
12 #include "src/compiler/operator-properties.h" 12 #include "src/compiler/operator-properties.h"
13 #include "src/compiler/state-values-utils.h" 13 #include "src/compiler/state-values-utils.h"
14 #include "src/types.h" 14 #include "src/types.h"
15 15
16 namespace v8 { 16 namespace v8 {
17 namespace internal { 17 namespace internal {
18 namespace compiler { 18 namespace compiler {
19 19
20 // TODO(turbofan): js-typed-lowering improvements possible 20 // TODO(turbofan): js-typed-lowering improvements possible
21 // - immediately put in type bounds for all new nodes 21 // - immediately put in type bounds for all new nodes
22 // - relax effects from generic but not-side-effecting operations 22 // - relax effects from generic but not-side-effecting operations
23 23
24 24
25 JSTypedLowering::JSTypedLowering(Editor* editor, JSGraph* jsgraph, Zone* zone) 25 JSTypedLowering::JSTypedLowering(Editor* editor,
26 : AdvancedReducer(editor), jsgraph_(jsgraph) { 26 CompilationDependencies* dependencies,
27 JSGraph* jsgraph, Zone* zone)
28 : AdvancedReducer(editor), dependencies_(dependencies), jsgraph_(jsgraph) {
27 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) { 29 for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) {
28 double min = kMinInt / (1 << k); 30 double min = kMinInt / (1 << k);
29 double max = kMaxInt / (1 << k); 31 double max = kMaxInt / (1 << k);
30 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone()); 32 shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
31 } 33 }
32 } 34 }
33 35
34 36
35 // A helper class to construct inline allocations on the simplified operator 37 // A helper class to construct inline allocations on the simplified operator
36 // level. This keeps track of the effect chain for initial stores on a newly 38 // level. This keeps track of the effect chain for initial stores on a newly
(...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after
1052 node->TrimInputCount(6); 1054 node->TrimInputCount(6);
1053 NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access)); 1055 NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access));
1054 return Changed(node); 1056 return Changed(node);
1055 } 1057 }
1056 } 1058 }
1057 } 1059 }
1058 return NoChange(); 1060 return NoChange();
1059 } 1061 }
1060 1062
1061 1063
1064 Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
1065 DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode());
1066
1067 JSBinopReduction r(this, node);
1068
1069 Node* effect = r.effect();
1070 Node* control = r.control();
1071
1072 if (r.right_type()->IsConstant() &&
1073 r.right_type()->AsConstant()->Value()->IsJSFunction()) {
1074 Handle<JSFunction> function =
1075 Handle<JSFunction>::cast(r.right_type()->AsConstant()->Value());
1076 Handle<SharedFunctionInfo> shared(function->shared(), isolate());
1077 if (!function->map()->has_non_instance_prototype()) {
1078 JSFunction::EnsureHasInitialMap(function);
1079 DCHECK(function->has_initial_map());
1080 Handle<Map> initial_map(function->initial_map(), isolate());
1081 this->dependencies()->AssumeInitialMapCantChange(initial_map);
Benedikt Meurer 2015/11/09 19:24:39 This is only valid if deoptimization support is en
sigurds 2015/11/10 09:39:44 Done. I assume without deopt support, we can't do
1082 Node* prototype =
1083 jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
1084
1085 Node* if_is_smi = nullptr;
1086 Node* e_is_smi = nullptr;
1087 // If the left hand side is an object, no smi check is needed.
1088 if (!r.left_type()->Is(Type::Object())) {
Benedikt Meurer 2015/11/09 19:24:39 This should be done using if (r.left_type()->Maybe
sigurds 2015/11/10 09:39:44 Thanks, I did not know what the best check here wa
1089 Node* is_smi = graph()->NewNode(simplified()->ObjectIsSmi(), r.left());
1090 Node* branch_is_smi = graph()->NewNode(
1091 common()->Branch(BranchHint::kFalse), is_smi, control);
1092 if_is_smi = graph()->NewNode(common()->IfTrue(), branch_is_smi);
1093 e_is_smi = effect;
1094 control = graph()->NewNode(common()->IfFalse(), branch_is_smi);
1095 }
1096
1097 Node* object_map = effect =
1098 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1099 r.left(), effect, control);
1100
1101 // Loop through the {object}s prototype chain looking for the {prototype}.
1102 Node* loop = control =
1103 graph()->NewNode(common()->Loop(2), control, control);
1104
1105 Node* loop_effect = effect =
1106 graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
1107
1108 Node* loop_object_map = graph()->NewNode(common()->Phi(kMachAnyTagged, 2),
1109 object_map, r.left(), loop);
1110
1111
1112 Node* object_prototype = effect = graph()->NewNode(
1113 simplified()->LoadField(AccessBuilder::ForMapPrototype()),
1114 loop_object_map, loop_effect, control);
1115
1116 // Check if object prototype is equal to function prototype.
1117 Node* eq_proto =
1118 graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
1119 object_prototype, prototype);
1120 Node* branch_eq_proto = graph()->NewNode(
1121 common()->Branch(BranchHint::kFalse), eq_proto, control);
1122 Node* if_eq_proto = graph()->NewNode(common()->IfTrue(), branch_eq_proto);
1123 Node* e_eq_proto = effect;
1124
1125 control = graph()->NewNode(common()->IfFalse(), branch_eq_proto);
1126
1127 // If not, check if object prototype is the null prototype.
1128 Node* null_proto =
1129 graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
1130 object_prototype, jsgraph()->NullConstant());
1131 Node* branch_null_proto = graph()->NewNode(
1132 common()->Branch(BranchHint::kFalse), null_proto, control);
1133 Node* if_null_proto =
1134 graph()->NewNode(common()->IfTrue(), branch_null_proto);
1135 Node* e_null_proto = effect;
1136
1137 control = graph()->NewNode(common()->IfFalse(), branch_null_proto);
1138 Node* load_object_map = effect =
1139 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1140 object_prototype, effect, control);
1141 // Close the loop.
1142 loop_effect->ReplaceInput(1, effect);
1143 loop_object_map->ReplaceInput(1, load_object_map);
1144 loop->ReplaceInput(1, control);
1145
1146 control =
1147 graph()->NewNode(common()->Merge(2), if_eq_proto, if_null_proto);
1148 effect = graph()->NewNode(common()->EffectPhi(2), e_eq_proto,
1149 e_null_proto, control);
1150
1151
1152 Node* result = graph()->NewNode(common()->Phi(kTypeBool, 2),
1153 jsgraph()->TrueConstant(),
1154 jsgraph()->FalseConstant(), control);
1155
1156 if (!r.left_type()->Is(Type::Object())) {
Benedikt Meurer 2015/11/09 19:24:39 How about if (if_is_smi != nullptr) instead?
sigurds 2015/11/10 09:39:44 Done.
1157 DCHECK(if_is_smi != nullptr);
1158 DCHECK(e_is_smi != nullptr);
1159
1160 control = graph()->NewNode(common()->Merge(2), if_is_smi, control);
1161 effect =
1162 graph()->NewNode(common()->EffectPhi(2), e_is_smi, effect, control);
1163 result = graph()->NewNode(common()->Phi(kTypeBool, 2),
1164 jsgraph()->FalseConstant(), result, control);
1165 }
1166 ReplaceWithValue(node, result, effect, control);
1167 return Changed(result);
1168 }
1169 }
1170
1171 return NoChange();
1172 }
1173
1174
1062 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) { 1175 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) {
1063 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); 1176 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
1064 ContextAccess const& access = ContextAccessOf(node->op()); 1177 ContextAccess const& access = ContextAccessOf(node->op());
1065 Node* const effect = NodeProperties::GetEffectInput(node); 1178 Node* const effect = NodeProperties::GetEffectInput(node);
1066 Node* const control = graph()->start(); 1179 Node* const control = graph()->start();
1067 for (size_t i = 0; i < access.depth(); ++i) { 1180 for (size_t i = 0; i < access.depth(); ++i) {
1068 node->ReplaceInput( 1181 node->ReplaceInput(
1069 0, graph()->NewNode( 1182 0, graph()->NewNode(
1070 simplified()->LoadField( 1183 simplified()->LoadField(
1071 AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)), 1184 AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
(...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after
2021 case IrOpcode::kJSToString: 2134 case IrOpcode::kJSToString:
2022 return ReduceJSToString(node); 2135 return ReduceJSToString(node);
2023 case IrOpcode::kJSToObject: 2136 case IrOpcode::kJSToObject:
2024 return ReduceJSToObject(node); 2137 return ReduceJSToObject(node);
2025 case IrOpcode::kJSLoadNamed: 2138 case IrOpcode::kJSLoadNamed:
2026 return ReduceJSLoadNamed(node); 2139 return ReduceJSLoadNamed(node);
2027 case IrOpcode::kJSLoadProperty: 2140 case IrOpcode::kJSLoadProperty:
2028 return ReduceJSLoadProperty(node); 2141 return ReduceJSLoadProperty(node);
2029 case IrOpcode::kJSStoreProperty: 2142 case IrOpcode::kJSStoreProperty:
2030 return ReduceJSStoreProperty(node); 2143 return ReduceJSStoreProperty(node);
2144 case IrOpcode::kJSInstanceOf:
2145 return ReduceJSInstanceOf(node);
2031 case IrOpcode::kJSLoadContext: 2146 case IrOpcode::kJSLoadContext:
2032 return ReduceJSLoadContext(node); 2147 return ReduceJSLoadContext(node);
2033 case IrOpcode::kJSStoreContext: 2148 case IrOpcode::kJSStoreContext:
2034 return ReduceJSStoreContext(node); 2149 return ReduceJSStoreContext(node);
2035 case IrOpcode::kJSConvertReceiver: 2150 case IrOpcode::kJSConvertReceiver:
2036 return ReduceJSConvertReceiver(node); 2151 return ReduceJSConvertReceiver(node);
2037 case IrOpcode::kJSCreateArguments: 2152 case IrOpcode::kJSCreateArguments:
2038 return ReduceJSCreateArguments(node); 2153 return ReduceJSCreateArguments(node);
2039 case IrOpcode::kJSCreateClosure: 2154 case IrOpcode::kJSCreateClosure:
2040 return ReduceJSCreateClosure(node); 2155 return ReduceJSCreateClosure(node);
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2168 2283
2169 SimplifiedOperatorBuilder* JSTypedLowering::simplified() const { 2284 SimplifiedOperatorBuilder* JSTypedLowering::simplified() const {
2170 return jsgraph()->simplified(); 2285 return jsgraph()->simplified();
2171 } 2286 }
2172 2287
2173 2288
2174 MachineOperatorBuilder* JSTypedLowering::machine() const { 2289 MachineOperatorBuilder* JSTypedLowering::machine() const {
2175 return jsgraph()->machine(); 2290 return jsgraph()->machine();
2176 } 2291 }
2177 2292
2293
2294 CompilationDependencies* JSTypedLowering::dependencies() const {
2295 return dependencies_;
2296 }
2297
2178 } // namespace compiler 2298 } // namespace compiler
2179 } // namespace internal 2299 } // namespace internal
2180 } // namespace v8 2300 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698