| OLD | NEW | 
|     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  Loading... | 
|  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  Loading... | 
|  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  Loading... | 
|  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 | 
| OLD | NEW |