Index: src/compiler/js-builtin-reducer.cc |
diff --git a/src/compiler/js-builtin-reducer.cc b/src/compiler/js-builtin-reducer.cc |
index 762020438878fdbc5566ba07848fd601c870b6ca..51ba0fe2c70f3c35f964f01c0be2d496e05d16ea 100644 |
--- a/src/compiler/js-builtin-reducer.cc |
+++ b/src/compiler/js-builtin-reducer.cc |
@@ -1026,6 +1026,166 @@ Reduction JSBuiltinReducer::ReduceStringCharCodeAt(Node* node) { |
return NoChange(); |
} |
+Reduction JSBuiltinReducer::ReduceStringIteratorPrototypeNext(Node* node) { |
+ Node* receiver = NodeProperties::GetValueInput(node, 1); |
+ Node* effect = NodeProperties::GetEffectInput(node); |
+ Node* control = NodeProperties::GetControlInput(node); |
+ Node* context = NodeProperties::GetContextInput(node); |
+ if (HasInstanceTypeWitness(receiver, effect, JS_STRING_ITERATOR_TYPE)) { |
+ Node* string = effect = graph()->NewNode( |
+ simplified()->LoadField(AccessBuilder::ForJSStringIteratorString()), |
+ receiver, effect, control); |
+ Node* index = effect = graph()->NewNode( |
+ simplified()->LoadField(AccessBuilder::ForJSStringIteratorIndex()), |
+ receiver, effect, control); |
+ Node* length = effect = graph()->NewNode( |
+ simplified()->LoadField(AccessBuilder::ForStringLength()), string, |
+ effect, control); |
+ |
+ // branch0: if (index < length) |
+ Node* check0 = |
+ graph()->NewNode(simplified()->NumberLessThan(), index, length); |
+ Node* branch0 = |
+ graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); |
+ |
+ Node* etrue0 = effect; |
+ Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
+ Node* done_true; |
+ Node* vtrue0; |
+ { |
+ done_true = jsgraph()->FalseConstant(); |
+ Node* lead = graph()->NewNode(simplified()->StringCharCodeAt(), string, |
+ index, if_true0); |
+ |
+ // branch1: if ((lead & 0xFC00) === 0xD800) |
+ Node* check1 = graph()->NewNode( |
+ simplified()->NumberEqual(), |
+ graph()->NewNode(simplified()->NumberBitwiseAnd(), lead, |
+ jsgraph()->Int32Constant(0xFC00)), |
+ jsgraph()->Int32Constant(0xD800)); |
+ Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse), |
+ check1, if_true0); |
+ Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
+ Node* vtrue1; |
+ { |
+ Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index, |
+ jsgraph()->OneConstant()); |
+ // branch2: if ((index + 1) < length) |
+ Node* check2 = graph()->NewNode(simplified()->NumberLessThan(), |
+ next_index, length); |
+ Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
+ check2, if_true1); |
+ Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); |
+ Node* vtrue2; |
+ { |
+ Node* trail = graph()->NewNode(simplified()->StringCharCodeAt(), |
+ string, next_index, if_true2); |
+ // branch3: if ((trail & 0xFC00) === 0xDC00) |
+ Node* check3 = graph()->NewNode( |
+ simplified()->NumberEqual(), |
+ graph()->NewNode(simplified()->NumberBitwiseAnd(), trail, |
+ jsgraph()->Int32Constant(0xFC00)), |
+ jsgraph()->Int32Constant(0xDC00)); |
+ Node* branch3 = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
+ check3, if_true2); |
+ Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3); |
+ Node* vtrue3; |
+ { |
+ vtrue3 = graph()->NewNode( |
+ simplified()->NumberBitwiseOr(), |
+ graph()->NewNode(simplified()->NumberShiftLeft(), trail, |
+ jsgraph()->Int32Constant(16)), |
+ lead); |
+ } |
+ |
+ Node* if_false3 = graph()->NewNode(common()->IfFalse(), branch3); |
+ Node* vfalse3 = lead; |
+ if_true2 = graph()->NewNode(common()->Merge(2), if_true3, if_false3); |
+ vtrue2 = |
+ graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
+ vtrue3, vfalse3, if_true2); |
+ } |
+ |
+ Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); |
+ Node* vfalse2 = lead; |
+ if_true1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); |
+ vtrue1 = |
+ graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
+ vtrue2, vfalse2, if_true1); |
+ } |
+ |
+ Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
+ Node* vfalse1 = lead; |
+ if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
+ vtrue0 = |
+ graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
+ vtrue1, vfalse1, if_true0); |
+ vtrue0 = graph()->NewNode( |
+ simplified()->StringFromCodePoint(UnicodeEncoding::UTF16), vtrue0); |
+ |
+ // Update iterator.[[NextIndex]] |
+ Node* char_length = etrue0 = graph()->NewNode( |
+ simplified()->LoadField(AccessBuilder::ForStringLength()), vtrue0, |
+ etrue0, if_true0); |
+ index = graph()->NewNode(simplified()->NumberAdd(), index, char_length); |
+ etrue0 = graph()->NewNode( |
+ simplified()->StoreField(AccessBuilder::ForJSStringIteratorIndex()), |
+ receiver, index, etrue0, if_true0); |
+ } |
+ |
+ Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); |
+ Node* done_false; |
+ Node* vfalse0; |
+ { |
+ vfalse0 = jsgraph()->UndefinedConstant(); |
+ done_false = jsgraph()->TrueConstant(); |
+ } |
+ |
+ control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
+ effect = graph()->NewNode(common()->EffectPhi(2), etrue0, effect, control); |
+ Node* value_phi = |
+ graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
+ vtrue0, vfalse0, control); |
+ Node* done_phi = |
+ graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
+ done_true, done_false, control); |
+ |
+ Node* native_context = effect = |
+ graph()->NewNode(jsgraph()->javascript()->LoadContext( |
+ 0, Context::NATIVE_CONTEXT_INDEX, true), |
+ context, context, effect); |
+ Node* map = effect = |
+ graph()->NewNode(jsgraph()->javascript()->LoadContext( |
+ 0, Context::ITERATOR_RESULT_MAP_INDEX, true), |
+ context, native_context, effect); |
+ |
+ // Allocate the IterResultObject. |
+ effect = graph()->NewNode( |
+ common()->BeginRegion(RegionObservability::kNotObservable), effect); |
+ Node* value = effect = graph()->NewNode( |
+ simplified()->Allocate(NOT_TENURED), |
+ jsgraph()->Int32Constant(JSIteratorResult::kSize), effect, control); |
Benedikt Meurer
2016/10/01 17:41:03
With your Typer change, you'll need to have a comp
Benedikt Meurer
2016/10/01 17:59:33
Actually I'd be even better to just use the existi
caitp
2016/10/01 18:02:43
Oh, I didn't realize there was an operator for thi
Benedikt Meurer
2016/10/01 18:18:31
Yes, you just pass in value and done (plus context
|
+ effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()), |
+ value, map, effect, control); |
+ effect = graph()->NewNode( |
+ simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value, |
+ jsgraph()->EmptyFixedArrayConstant(), effect, control); |
+ effect = graph()->NewNode( |
+ simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value, |
+ jsgraph()->EmptyFixedArrayConstant(), effect, control); |
+ effect = graph()->NewNode( |
+ simplified()->StoreField(AccessBuilder::ForJSIteratorResultDone()), |
+ value, done_phi, effect, control); |
+ effect = graph()->NewNode( |
+ simplified()->StoreField(AccessBuilder::ForJSIteratorResultValue()), |
+ value, value_phi, effect, control); |
+ value = effect = graph()->NewNode(common()->FinishRegion(), value, effect); |
+ ReplaceWithValue(node, value, effect, control); |
+ return Replace(value); |
+ } |
+ return NoChange(); |
+} |
+ |
Reduction JSBuiltinReducer::ReduceArrayBufferViewAccessor( |
Node* node, InstanceType instance_type, FieldAccess const& access) { |
Node* receiver = NodeProperties::GetValueInput(node, 1); |
@@ -1195,6 +1355,8 @@ Reduction JSBuiltinReducer::Reduce(Node* node) { |
return ReduceStringCharAt(node); |
case kStringCharCodeAt: |
return ReduceStringCharCodeAt(node); |
+ case kStringIteratorPrototypeNext: |
+ return ReduceStringIteratorPrototypeNext(node); |
case kDataViewByteLength: |
return ReduceArrayBufferViewAccessor( |
node, JS_DATA_VIEW_TYPE, |