| 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/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/node-matchers.h" |    9 #include "src/compiler/node-matchers.h" | 
|   10 #include "src/compiler/node-properties.h" |   10 #include "src/compiler/node-properties.h" | 
| (...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  536     // String.fromCharCode(a:plain-primitive) -> StringFromCharCode(a) |  536     // String.fromCharCode(a:plain-primitive) -> StringFromCharCode(a) | 
|  537     Node* input = ToNumber(r.GetJSCallInput(0)); |  537     Node* input = ToNumber(r.GetJSCallInput(0)); | 
|  538     Node* value = graph()->NewNode(simplified()->StringFromCharCode(), input); |  538     Node* value = graph()->NewNode(simplified()->StringFromCharCode(), input); | 
|  539     return Replace(value); |  539     return Replace(value); | 
|  540   } |  540   } | 
|  541   return NoChange(); |  541   return NoChange(); | 
|  542 } |  542 } | 
|  543  |  543  | 
|  544 namespace { |  544 namespace { | 
|  545  |  545  | 
|  546 Node* GetStringReceiver(Node* node) { |  546 Node* GetStringWitness(Node* node) { | 
|  547   Node* receiver = NodeProperties::GetValueInput(node, 1); |  547   Node* receiver = NodeProperties::GetValueInput(node, 1); | 
|  548   Type* receiver_type = NodeProperties::GetType(receiver); |  548   Type* receiver_type = NodeProperties::GetType(receiver); | 
|  549   Node* effect = NodeProperties::GetEffectInput(node); |  549   Node* effect = NodeProperties::GetEffectInput(node); | 
|  550   if (receiver_type->Is(Type::String())) return receiver; |  550   if (receiver_type->Is(Type::String())) return receiver; | 
|  551   // Check if the {node} is dominated by a CheckString renaming for |  551   // Check if the {node} is dominated by a CheckString renaming for | 
|  552   // it's {receiver}, and if so use that renaming as {receiver} for |  552   // it's {receiver}, and if so use that renaming as {receiver} for | 
|  553   // the lowering below. |  553   // the lowering below. | 
|  554   for (Node* dominator = effect;;) { |  554   for (Node* dominator = effect;;) { | 
|  555     if (dominator->opcode() == IrOpcode::kCheckString && |  555     if (dominator->opcode() == IrOpcode::kCheckString && | 
|  556         dominator->InputAt(0) == receiver) { |  556         dominator->InputAt(0) == receiver) { | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
|  569 // ES6 section 21.1.3.1 String.prototype.charAt ( pos ) |  569 // ES6 section 21.1.3.1 String.prototype.charAt ( pos ) | 
|  570 Reduction JSBuiltinReducer::ReduceStringCharAt(Node* node) { |  570 Reduction JSBuiltinReducer::ReduceStringCharAt(Node* node) { | 
|  571   // We need at least target, receiver and index parameters. |  571   // We need at least target, receiver and index parameters. | 
|  572   if (node->op()->ValueInputCount() >= 3) { |  572   if (node->op()->ValueInputCount() >= 3) { | 
|  573     Node* index = NodeProperties::GetValueInput(node, 2); |  573     Node* index = NodeProperties::GetValueInput(node, 2); | 
|  574     Type* index_type = NodeProperties::GetType(index); |  574     Type* index_type = NodeProperties::GetType(index); | 
|  575     Node* effect = NodeProperties::GetEffectInput(node); |  575     Node* effect = NodeProperties::GetEffectInput(node); | 
|  576     Node* control = NodeProperties::GetControlInput(node); |  576     Node* control = NodeProperties::GetControlInput(node); | 
|  577  |  577  | 
|  578     if (index_type->Is(Type::Unsigned32())) { |  578     if (index_type->Is(Type::Unsigned32())) { | 
|  579       if (Node* receiver = GetStringReceiver(node)) { |  579       if (Node* receiver = GetStringWitness(node)) { | 
|  580         // Determine the {receiver} length. |  580         // Determine the {receiver} length. | 
|  581         Node* receiver_length = effect = graph()->NewNode( |  581         Node* receiver_length = effect = graph()->NewNode( | 
|  582             simplified()->LoadField(AccessBuilder::ForStringLength()), receiver, |  582             simplified()->LoadField(AccessBuilder::ForStringLength()), receiver, | 
|  583             effect, control); |  583             effect, control); | 
|  584  |  584  | 
|  585         // Check if {index} is less than {receiver} length. |  585         // Check if {index} is less than {receiver} length. | 
|  586         Node* check = graph()->NewNode(simplified()->NumberLessThan(), index, |  586         Node* check = graph()->NewNode(simplified()->NumberLessThan(), index, | 
|  587                                        receiver_length); |  587                                        receiver_length); | 
|  588         Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), |  588         Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 
|  589                                         check, control); |  589                                         check, control); | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
|  620 // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos ) |  620 // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos ) | 
|  621 Reduction JSBuiltinReducer::ReduceStringCharCodeAt(Node* node) { |  621 Reduction JSBuiltinReducer::ReduceStringCharCodeAt(Node* node) { | 
|  622   // We need at least target, receiver and index parameters. |  622   // We need at least target, receiver and index parameters. | 
|  623   if (node->op()->ValueInputCount() >= 3) { |  623   if (node->op()->ValueInputCount() >= 3) { | 
|  624     Node* index = NodeProperties::GetValueInput(node, 2); |  624     Node* index = NodeProperties::GetValueInput(node, 2); | 
|  625     Type* index_type = NodeProperties::GetType(index); |  625     Type* index_type = NodeProperties::GetType(index); | 
|  626     Node* effect = NodeProperties::GetEffectInput(node); |  626     Node* effect = NodeProperties::GetEffectInput(node); | 
|  627     Node* control = NodeProperties::GetControlInput(node); |  627     Node* control = NodeProperties::GetControlInput(node); | 
|  628  |  628  | 
|  629     if (index_type->Is(Type::Unsigned32())) { |  629     if (index_type->Is(Type::Unsigned32())) { | 
|  630       if (Node* receiver = GetStringReceiver(node)) { |  630       if (Node* receiver = GetStringWitness(node)) { | 
|  631         // Determine the {receiver} length. |  631         // Determine the {receiver} length. | 
|  632         Node* receiver_length = effect = graph()->NewNode( |  632         Node* receiver_length = effect = graph()->NewNode( | 
|  633             simplified()->LoadField(AccessBuilder::ForStringLength()), receiver, |  633             simplified()->LoadField(AccessBuilder::ForStringLength()), receiver, | 
|  634             effect, control); |  634             effect, control); | 
|  635  |  635  | 
|  636         // Check if {index} is less than {receiver} length. |  636         // Check if {index} is less than {receiver} length. | 
|  637         Node* check = graph()->NewNode(simplified()->NumberLessThan(), index, |  637         Node* check = graph()->NewNode(simplified()->NumberLessThan(), index, | 
|  638                                        receiver_length); |  638                                        receiver_length); | 
|  639         Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), |  639         Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 
|  640                                         check, control); |  640                                         check, control); | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
|  655  |  655  | 
|  656         ReplaceWithValue(node, value, effect, control); |  656         ReplaceWithValue(node, value, effect, control); | 
|  657         return Replace(value); |  657         return Replace(value); | 
|  658       } |  658       } | 
|  659     } |  659     } | 
|  660   } |  660   } | 
|  661  |  661  | 
|  662   return NoChange(); |  662   return NoChange(); | 
|  663 } |  663 } | 
|  664  |  664  | 
 |  665 namespace { | 
 |  666  | 
 |  667 bool HasInstanceTypeWitness(Node* receiver, Node* effect, | 
 |  668                             InstanceType instance_type) { | 
 |  669   for (Node* dominator = effect;;) { | 
 |  670     if (dominator->opcode() == IrOpcode::kCheckMaps && | 
 |  671         dominator->InputAt(0) == receiver) { | 
 |  672       // Check if all maps have the given {instance_type}. | 
 |  673       for (int i = 1; i < dominator->op()->ValueInputCount(); ++i) { | 
 |  674         Node* const map = NodeProperties::GetValueInput(dominator, i); | 
 |  675         Type* const map_type = NodeProperties::GetType(map); | 
 |  676         if (!map_type->IsConstant()) return false; | 
 |  677         Handle<Map> const map_value = | 
 |  678             Handle<Map>::cast(map_type->AsConstant()->Value()); | 
 |  679         if (map_value->instance_type() != instance_type) return false; | 
 |  680       } | 
 |  681       return true; | 
 |  682     } | 
 |  683     switch (dominator->opcode()) { | 
 |  684       case IrOpcode::kStoreField: { | 
 |  685         FieldAccess const& access = FieldAccessOf(dominator->op()); | 
 |  686         if (access.base_is_tagged == kTaggedBase && | 
 |  687             access.offset == HeapObject::kMapOffset) { | 
 |  688           return false; | 
 |  689         } | 
 |  690         break; | 
 |  691       } | 
 |  692       case IrOpcode::kStoreElement: | 
 |  693         break; | 
 |  694       default: { | 
 |  695         DCHECK_EQ(1, dominator->op()->EffectOutputCount()); | 
 |  696         if (dominator->op()->EffectInputCount() != 1 || | 
 |  697             !dominator->op()->HasProperty(Operator::kNoWrite)) { | 
 |  698           // Didn't find any appropriate CheckMaps node. | 
 |  699           return false; | 
 |  700         } | 
 |  701         break; | 
 |  702       } | 
 |  703     } | 
 |  704     dominator = NodeProperties::GetEffectInput(dominator); | 
 |  705   } | 
 |  706 } | 
 |  707  | 
 |  708 }  // namespace | 
 |  709  | 
 |  710 Reduction JSBuiltinReducer::ReduceArrayBufferViewAccessor( | 
 |  711     Node* node, InstanceType instance_type, FieldAccess const& access) { | 
 |  712   Node* receiver = NodeProperties::GetValueInput(node, 1); | 
 |  713   Node* effect = NodeProperties::GetEffectInput(node); | 
 |  714   Node* control = NodeProperties::GetControlInput(node); | 
 |  715   if (HasInstanceTypeWitness(receiver, effect, instance_type)) { | 
 |  716     // Load the {receiver}s field. | 
 |  717     Node* receiver_length = effect = graph()->NewNode( | 
 |  718         simplified()->LoadField(access), receiver, effect, control); | 
 |  719  | 
 |  720     // Check if the {receiver}s buffer was neutered. | 
 |  721     Node* receiver_buffer = effect = graph()->NewNode( | 
 |  722         simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()), | 
 |  723         receiver, effect, control); | 
 |  724     Node* receiver_buffer_bitfield = effect = graph()->NewNode( | 
 |  725         simplified()->LoadField(AccessBuilder::ForJSArrayBufferBitField()), | 
 |  726         receiver_buffer, effect, control); | 
 |  727     Node* check = graph()->NewNode( | 
 |  728         simplified()->NumberEqual(), | 
 |  729         graph()->NewNode( | 
 |  730             simplified()->NumberBitwiseAnd(), receiver_buffer_bitfield, | 
 |  731             jsgraph()->Constant(JSArrayBuffer::WasNeutered::kMask)), | 
 |  732         jsgraph()->ZeroConstant()); | 
 |  733  | 
 |  734     // Default to zero if the {receiver}s buffer was neutered. | 
 |  735     Node* value = | 
 |  736         graph()->NewNode(common()->Select(MachineRepresentation::kTagged), | 
 |  737                          check, receiver_length, jsgraph()->ZeroConstant()); | 
 |  738  | 
 |  739     ReplaceWithValue(node, value, effect, control); | 
 |  740     return Replace(value); | 
 |  741   } | 
 |  742   return NoChange(); | 
 |  743 } | 
 |  744  | 
|  665 Reduction JSBuiltinReducer::Reduce(Node* node) { |  745 Reduction JSBuiltinReducer::Reduce(Node* node) { | 
|  666   Reduction reduction = NoChange(); |  746   Reduction reduction = NoChange(); | 
|  667   JSCallReduction r(node); |  747   JSCallReduction r(node); | 
|  668  |  748  | 
|  669   // Dispatch according to the BuiltinFunctionId if present. |  749   // Dispatch according to the BuiltinFunctionId if present. | 
|  670   if (!r.HasBuiltinFunctionId()) return NoChange(); |  750   if (!r.HasBuiltinFunctionId()) return NoChange(); | 
|  671   switch (r.GetBuiltinFunctionId()) { |  751   switch (r.GetBuiltinFunctionId()) { | 
|  672     case kMathAbs: |  752     case kMathAbs: | 
|  673       reduction = ReduceMathAbs(node); |  753       reduction = ReduceMathAbs(node); | 
|  674       break; |  754       break; | 
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  771     case kNumberParseInt: |  851     case kNumberParseInt: | 
|  772       reduction = ReduceNumberParseInt(node); |  852       reduction = ReduceNumberParseInt(node); | 
|  773       break; |  853       break; | 
|  774     case kStringFromCharCode: |  854     case kStringFromCharCode: | 
|  775       reduction = ReduceStringFromCharCode(node); |  855       reduction = ReduceStringFromCharCode(node); | 
|  776       break; |  856       break; | 
|  777     case kStringCharAt: |  857     case kStringCharAt: | 
|  778       return ReduceStringCharAt(node); |  858       return ReduceStringCharAt(node); | 
|  779     case kStringCharCodeAt: |  859     case kStringCharCodeAt: | 
|  780       return ReduceStringCharCodeAt(node); |  860       return ReduceStringCharCodeAt(node); | 
 |  861     case kDataViewByteLength: | 
 |  862       return ReduceArrayBufferViewAccessor( | 
 |  863           node, JS_DATA_VIEW_TYPE, | 
 |  864           AccessBuilder::ForJSArrayBufferViewByteLength()); | 
 |  865     case kDataViewByteOffset: | 
 |  866       return ReduceArrayBufferViewAccessor( | 
 |  867           node, JS_DATA_VIEW_TYPE, | 
 |  868           AccessBuilder::ForJSArrayBufferViewByteOffset()); | 
 |  869     case kTypedArrayByteLength: | 
 |  870       return ReduceArrayBufferViewAccessor( | 
 |  871           node, JS_TYPED_ARRAY_TYPE, | 
 |  872           AccessBuilder::ForJSArrayBufferViewByteLength()); | 
 |  873     case kTypedArrayByteOffset: | 
 |  874       return ReduceArrayBufferViewAccessor( | 
 |  875           node, JS_TYPED_ARRAY_TYPE, | 
 |  876           AccessBuilder::ForJSArrayBufferViewByteOffset()); | 
 |  877     case kTypedArrayLength: | 
 |  878       return ReduceArrayBufferViewAccessor( | 
 |  879           node, JS_TYPED_ARRAY_TYPE, AccessBuilder::ForJSTypedArrayLength()); | 
|  781     default: |  880     default: | 
|  782       break; |  881       break; | 
|  783   } |  882   } | 
|  784  |  883  | 
|  785   // Replace builtin call assuming replacement nodes are pure values that don't |  884   // Replace builtin call assuming replacement nodes are pure values that don't | 
|  786   // produce an effect. Replaces {node} with {reduction} and relaxes effects. |  885   // produce an effect. Replaces {node} with {reduction} and relaxes effects. | 
|  787   if (reduction.Changed()) ReplaceWithValue(node, reduction.replacement()); |  886   if (reduction.Changed()) ReplaceWithValue(node, reduction.replacement()); | 
|  788  |  887  | 
|  789   return reduction; |  888   return reduction; | 
|  790 } |  889 } | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
|  813 } |  912 } | 
|  814  |  913  | 
|  815  |  914  | 
|  816 SimplifiedOperatorBuilder* JSBuiltinReducer::simplified() const { |  915 SimplifiedOperatorBuilder* JSBuiltinReducer::simplified() const { | 
|  817   return jsgraph()->simplified(); |  916   return jsgraph()->simplified(); | 
|  818 } |  917 } | 
|  819  |  918  | 
|  820 }  // namespace compiler |  919 }  // namespace compiler | 
|  821 }  // namespace internal |  920 }  // namespace internal | 
|  822 }  // namespace v8 |  921 }  // namespace v8 | 
| OLD | NEW |