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

Side by Side Diff: src/compiler/js-builtin-reducer.cc

Issue 2874453002: [turbofan] Boost performance of Array.prototype.shift by 4x. (Closed)
Patch Set: Cosmetic fixes. Created 3 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-builtin-reducer.h ('k') | src/crankshaft/hydrogen.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-builtin-reducer.h" 5 #include "src/compiler/js-builtin-reducer.h"
6 6
7 #include "src/base/bits.h" 7 #include "src/base/bits.h"
8 #include "src/builtins/builtins-utils.h"
8 #include "src/code-factory.h" 9 #include "src/code-factory.h"
9 #include "src/compilation-dependencies.h" 10 #include "src/compilation-dependencies.h"
10 #include "src/compiler/access-builder.h" 11 #include "src/compiler/access-builder.h"
11 #include "src/compiler/js-graph.h" 12 #include "src/compiler/js-graph.h"
12 #include "src/compiler/linkage.h" 13 #include "src/compiler/linkage.h"
13 #include "src/compiler/node-matchers.h" 14 #include "src/compiler/node-matchers.h"
14 #include "src/compiler/node-properties.h" 15 #include "src/compiler/node-properties.h"
15 #include "src/compiler/simplified-operator.h" 16 #include "src/compiler/simplified-operator.h"
16 #include "src/compiler/type-cache.h" 17 #include "src/compiler/type-cache.h"
17 #include "src/compiler/types.h" 18 #include "src/compiler/types.h"
(...skipping 996 matching lines...) Expand 10 before | Expand all | Expand 10 after
1014 // Return the new length of the {receiver}. 1015 // Return the new length of the {receiver}.
1015 value = graph()->NewNode(simplified()->NumberAdd(), length, 1016 value = graph()->NewNode(simplified()->NumberAdd(), length,
1016 jsgraph()->OneConstant()); 1017 jsgraph()->OneConstant());
1017 1018
1018 ReplaceWithValue(node, value, effect, control); 1019 ReplaceWithValue(node, value, effect, control);
1019 return Replace(value); 1020 return Replace(value);
1020 } 1021 }
1021 return NoChange(); 1022 return NoChange();
1022 } 1023 }
1023 1024
1025 // ES6 section 22.1.3.22 Array.prototype.shift ( )
1026 Reduction JSBuiltinReducer::ReduceArrayShift(Node* node) {
1027 Node* target = NodeProperties::GetValueInput(node, 0);
1028 Node* receiver = NodeProperties::GetValueInput(node, 1);
1029 Node* context = NodeProperties::GetContextInput(node);
1030 Node* frame_state = NodeProperties::GetFrameStateInput(node);
1031 Node* effect = NodeProperties::GetEffectInput(node);
1032 Node* control = NodeProperties::GetControlInput(node);
1033
1034 // TODO(turbofan): Extend this to also handle fast holey double elements
1035 // once we got the hole NaN mess sorted out in TurboFan/V8.
1036 Handle<Map> receiver_map;
1037 if (GetMapWitness(node).ToHandle(&receiver_map) &&
1038 CanInlineArrayResizeOperation(receiver_map) &&
1039 receiver_map->elements_kind() != FAST_HOLEY_DOUBLE_ELEMENTS) {
1040 // Install code dependencies on the {receiver} prototype maps and the
1041 // global array protector cell.
1042 dependencies()->AssumePropertyCell(factory()->array_protector());
1043 dependencies()->AssumePrototypeMapsStable(receiver_map);
1044
1045 // Load length of the {receiver}.
1046 Node* length = effect = graph()->NewNode(
1047 simplified()->LoadField(
1048 AccessBuilder::ForJSArrayLength(receiver_map->elements_kind())),
1049 receiver, effect, control);
1050
1051 // Return undefined if {receiver} has no elements.
1052 Node* check0 = graph()->NewNode(simplified()->NumberEqual(), length,
1053 jsgraph()->ZeroConstant());
1054 Node* branch0 =
1055 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
1056
1057 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1058 Node* etrue0 = effect;
1059 Node* vtrue0 = jsgraph()->UndefinedConstant();
1060
1061 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1062 Node* efalse0 = effect;
1063 Node* vfalse0;
1064 {
1065 // Check if we should take the fast-path.
1066 Node* check1 =
1067 graph()->NewNode(simplified()->NumberLessThanOrEqual(), length,
1068 jsgraph()->Constant(JSArray::kMaxCopyElements));
1069 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
1070 check1, if_false0);
1071
1072 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1073 Node* etrue1 = efalse0;
1074 Node* vtrue1;
1075 {
1076 Node* elements = etrue1 = graph()->NewNode(
1077 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
1078 receiver, etrue1, if_true1);
1079
1080 // Load the first element here, which we return below.
1081 vtrue1 = etrue1 = graph()->NewNode(
1082 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement(
1083 receiver_map->elements_kind())),
1084 elements, jsgraph()->ZeroConstant(), etrue1, if_true1);
1085
1086 // Ensure that we aren't shifting a copy-on-write backing store.
1087 if (IsFastSmiOrObjectElementsKind(receiver_map->elements_kind())) {
1088 elements = etrue1 =
1089 graph()->NewNode(simplified()->EnsureWritableFastElements(),
1090 receiver, elements, etrue1, if_true1);
1091 }
1092
1093 // Shift the remaining {elements} by one towards the start.
1094 Node* loop = graph()->NewNode(common()->Loop(2), if_true1, if_true1);
1095 Node* eloop =
1096 graph()->NewNode(common()->EffectPhi(2), etrue1, etrue1, loop);
1097 Node* index = graph()->NewNode(
1098 common()->Phi(MachineRepresentation::kTagged, 2),
1099 jsgraph()->OneConstant(),
1100 jsgraph()->Constant(JSArray::kMaxCopyElements - 1), loop);
1101
1102 {
1103 Node* check2 =
1104 graph()->NewNode(simplified()->NumberLessThan(), index, length);
1105 Node* branch2 = graph()->NewNode(common()->Branch(), check2, loop);
1106
1107 if_true1 = graph()->NewNode(common()->IfFalse(), branch2);
1108 etrue1 = eloop;
1109
1110 Node* control = graph()->NewNode(common()->IfTrue(), branch2);
1111 Node* effect = etrue1;
1112
1113 ElementAccess const access = AccessBuilder::ForFixedArrayElement(
1114 receiver_map->elements_kind());
1115 Node* value = effect =
1116 graph()->NewNode(simplified()->LoadElement(access), elements,
1117 index, effect, control);
1118 effect = graph()->NewNode(
1119 simplified()->StoreElement(access), elements,
1120 graph()->NewNode(simplified()->NumberSubtract(), index,
1121 jsgraph()->OneConstant()),
1122 value, effect, control);
1123
1124 loop->ReplaceInput(1, control);
1125 eloop->ReplaceInput(1, effect);
1126 index->ReplaceInput(1,
1127 graph()->NewNode(simplified()->NumberAdd(), index,
1128 jsgraph()->OneConstant()));
1129 }
1130
1131 // Compute the new {length}.
1132 length = graph()->NewNode(simplified()->NumberSubtract(), length,
1133 jsgraph()->OneConstant());
1134
1135 // Store the new {length} to the {receiver}.
1136 etrue1 = graph()->NewNode(
1137 simplified()->StoreField(
1138 AccessBuilder::ForJSArrayLength(receiver_map->elements_kind())),
1139 receiver, length, etrue1, if_true1);
1140
1141 // Store a hole to the element we just removed from the {receiver}.
1142 etrue1 = graph()->NewNode(
1143 simplified()->StoreElement(AccessBuilder::ForFixedArrayElement(
1144 GetHoleyElementsKind(receiver_map->elements_kind()))),
1145 elements, length, jsgraph()->TheHoleConstant(), etrue1, if_true1);
1146 }
1147
1148 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1149 Node* efalse1 = efalse0;
1150 Node* vfalse1;
1151 {
1152 // Call the generic C++ implementation.
1153 const int builtin_index = Builtins::kArrayShift;
1154 CallDescriptor const* const desc = Linkage::GetCEntryStubCallDescriptor(
1155 graph()->zone(), 1, BuiltinArguments::kNumExtraArgsWithReceiver,
1156 Builtins::name(builtin_index), node->op()->properties(),
1157 CallDescriptor::kNeedsFrameState);
1158 Node* stub_code = jsgraph()->CEntryStubConstant(1, kDontSaveFPRegs,
1159 kArgvOnStack, true);
1160 Address builtin_entry = Builtins::CppEntryOf(builtin_index);
1161 Node* entry = jsgraph()->ExternalConstant(
1162 ExternalReference(builtin_entry, isolate()));
1163 Node* argc =
1164 jsgraph()->Constant(BuiltinArguments::kNumExtraArgsWithReceiver);
1165 if_false1 = efalse1 = vfalse1 =
1166 graph()->NewNode(common()->Call(desc), stub_code, receiver, argc,
1167 target, jsgraph()->UndefinedConstant(), entry,
1168 argc, context, frame_state, efalse1, if_false1);
1169 }
1170
1171 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
1172 efalse0 =
1173 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
1174 vfalse0 =
1175 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
1176 vtrue1, vfalse1, if_false0);
1177 }
1178
1179 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
1180 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
1181 Node* value =
1182 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
1183 vtrue0, vfalse0, control);
1184
1185 // Convert the hole to undefined. Do this last, so that we can optimize
1186 // conversion operator via some smart strength reduction in many cases.
1187 if (IsFastHoleyElementsKind(receiver_map->elements_kind())) {
1188 value =
1189 graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), value);
1190 }
1191
1192 ReplaceWithValue(node, value, effect, control);
1193 return Replace(value);
1194 }
1195 return NoChange();
1196 }
1197
1024 namespace { 1198 namespace {
1025 1199
1026 bool HasInstanceTypeWitness(Node* receiver, Node* effect, 1200 bool HasInstanceTypeWitness(Node* receiver, Node* effect,
1027 InstanceType instance_type) { 1201 InstanceType instance_type) {
1028 for (Node* dominator = effect;;) { 1202 for (Node* dominator = effect;;) {
1029 if (dominator->opcode() == IrOpcode::kCheckMaps && 1203 if (dominator->opcode() == IrOpcode::kCheckMaps &&
1030 NodeProperties::IsSame(dominator->InputAt(0), receiver)) { 1204 NodeProperties::IsSame(dominator->InputAt(0), receiver)) {
1031 ZoneHandleSet<Map> const& maps = 1205 ZoneHandleSet<Map> const& maps =
1032 CheckMapsParametersOf(dominator->op()).maps(); 1206 CheckMapsParametersOf(dominator->op()).maps();
1033 // Check if all maps have the given {instance_type}. 1207 // Check if all maps have the given {instance_type}.
(...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after
2134 case kArrayValues: 2308 case kArrayValues:
2135 return ReduceArrayIterator(node, IterationKind::kValues); 2309 return ReduceArrayIterator(node, IterationKind::kValues);
2136 case kArrayIteratorNext: 2310 case kArrayIteratorNext:
2137 return ReduceArrayIteratorNext(node); 2311 return ReduceArrayIteratorNext(node);
2138 case kArrayIsArray: 2312 case kArrayIsArray:
2139 return ReduceArrayIsArray(node); 2313 return ReduceArrayIsArray(node);
2140 case kArrayPop: 2314 case kArrayPop:
2141 return ReduceArrayPop(node); 2315 return ReduceArrayPop(node);
2142 case kArrayPush: 2316 case kArrayPush:
2143 return ReduceArrayPush(node); 2317 return ReduceArrayPush(node);
2318 case kArrayShift:
2319 return ReduceArrayShift(node);
2144 case kDateNow: 2320 case kDateNow:
2145 return ReduceDateNow(node); 2321 return ReduceDateNow(node);
2146 case kDateGetTime: 2322 case kDateGetTime:
2147 return ReduceDateGetTime(node); 2323 return ReduceDateGetTime(node);
2148 case kGlobalIsFinite: 2324 case kGlobalIsFinite:
2149 reduction = ReduceGlobalIsFinite(node); 2325 reduction = ReduceGlobalIsFinite(node);
2150 break; 2326 break;
2151 case kGlobalIsNaN: 2327 case kGlobalIsNaN:
2152 reduction = ReduceGlobalIsNaN(node); 2328 reduction = ReduceGlobalIsNaN(node);
2153 break; 2329 break;
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
2348 return jsgraph()->simplified(); 2524 return jsgraph()->simplified();
2349 } 2525 }
2350 2526
2351 JSOperatorBuilder* JSBuiltinReducer::javascript() const { 2527 JSOperatorBuilder* JSBuiltinReducer::javascript() const {
2352 return jsgraph()->javascript(); 2528 return jsgraph()->javascript();
2353 } 2529 }
2354 2530
2355 } // namespace compiler 2531 } // namespace compiler
2356 } // namespace internal 2532 } // namespace internal
2357 } // namespace v8 2533 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-builtin-reducer.h ('k') | src/crankshaft/hydrogen.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698