Index: src/compiler/js-builtin-reducer.cc |
diff --git a/src/compiler/js-builtin-reducer.cc b/src/compiler/js-builtin-reducer.cc |
index a9af93c80ce9cb6e661d72ab5ff189ca6aa49884..e3bafadaef0ef1304680fa9553d4617000e3a57c 100644 |
--- a/src/compiler/js-builtin-reducer.cc |
+++ b/src/compiler/js-builtin-reducer.cc |
@@ -725,6 +725,104 @@ Reduction JSBuiltinReducer::ReduceArrayIteratorNext(Node* node) { |
return NoChange(); |
} |
+// ES6 section 22.1.2.2 Array.isArray ( arg ) |
+Reduction JSBuiltinReducer::ReduceArrayIsArray(Node* node) { |
+ // We certainly know that undefined is not an array. |
+ if (node->op()->ValueInputCount() < 3) { |
+ Node* value = jsgraph()->FalseConstant(); |
+ ReplaceWithValue(node, value); |
+ return Replace(value); |
+ } |
+ Node* value = NodeProperties::GetValueInput(node, 2); |
+ Node* context = NodeProperties::GetContextInput(node); |
+ Node* frame_state = NodeProperties::GetFrameStateInput(node); |
+ Node* effect = NodeProperties::GetEffectInput(node); |
+ Node* control = NodeProperties::GetControlInput(node); |
+ |
+ int count = 0; |
+ Node* values[5]; |
+ Node* effects[5]; |
+ Node* controls[4]; |
+ |
+ // Check if the {value} is a Smi. |
+ Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value); |
+ control = |
+ graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); |
+ |
+ // The {value} is a Smi. |
+ controls[count] = graph()->NewNode(common()->IfTrue(), control); |
+ effects[count] = effect; |
+ values[count] = jsgraph()->FalseConstant(); |
+ count++; |
+ |
+ control = graph()->NewNode(common()->IfFalse(), control); |
+ |
+ // Load the {value}s instance type. |
+ Node* value_map = effect = graph()->NewNode( |
+ simplified()->LoadField(AccessBuilder::ForMap()), value, effect, control); |
+ Node* value_instance_type = effect = graph()->NewNode( |
+ simplified()->LoadField(AccessBuilder::ForMapInstanceType()), value_map, |
+ effect, control); |
+ |
+ // Check if the {value} is a JSArray. |
+ check = graph()->NewNode(simplified()->NumberEqual(), value_instance_type, |
+ jsgraph()->Constant(JS_ARRAY_TYPE)); |
+ control = graph()->NewNode(common()->Branch(), check, control); |
+ |
+ // The {value} is a JSArray. |
+ controls[count] = graph()->NewNode(common()->IfTrue(), control); |
+ effects[count] = effect; |
+ values[count] = jsgraph()->TrueConstant(); |
+ count++; |
+ |
+ control = graph()->NewNode(common()->IfFalse(), control); |
+ |
+ // Check if the {value} is a JSProxy. |
+ check = graph()->NewNode(simplified()->NumberEqual(), value_instance_type, |
+ jsgraph()->Constant(JS_PROXY_TYPE)); |
+ control = |
+ graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); |
+ |
+ // The {value} is neither a JSArray nor a JSProxy. |
+ controls[count] = graph()->NewNode(common()->IfFalse(), control); |
+ effects[count] = effect; |
+ values[count] = jsgraph()->FalseConstant(); |
+ count++; |
+ |
+ control = graph()->NewNode(common()->IfTrue(), control); |
+ |
+ // Let the %ArrayIsArray runtime function deal with the JSProxy {value}. |
+ value = effect = |
+ graph()->NewNode(javascript()->CallRuntime(Runtime::kArrayIsArray), value, |
+ context, frame_state, effect, control); |
+ NodeProperties::SetType(value, Type::Boolean()); |
+ control = graph()->NewNode(common()->IfSuccess(), value); |
+ |
+ // Rewire any IfException edges on {node} to {value}. |
+ for (Edge edge : node->use_edges()) { |
+ Node* const user = edge.from(); |
+ if (user->opcode() == IrOpcode::kIfException) { |
+ edge.UpdateTo(value); |
+ Revisit(user); |
+ } |
+ } |
+ |
+ // The {value} is neither a JSArray nor a JSProxy. |
+ controls[count] = control; |
+ effects[count] = effect; |
+ values[count] = value; |
+ count++; |
+ |
+ control = graph()->NewNode(common()->Merge(count), count, controls); |
+ effects[count] = control; |
+ values[count] = control; |
+ effect = graph()->NewNode(common()->EffectPhi(count), count + 1, effects); |
+ value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, count), |
+ count + 1, values); |
+ ReplaceWithValue(node, value, effect, control); |
+ return Replace(value); |
+} |
+ |
// ES6 section 22.1.3.17 Array.prototype.pop ( ) |
Reduction JSBuiltinReducer::ReduceArrayPop(Node* node) { |
Handle<Map> receiver_map; |
@@ -1969,6 +2067,8 @@ Reduction JSBuiltinReducer::Reduce(Node* node) { |
return ReduceArrayIterator(node, IterationKind::kValues); |
case kArrayIteratorNext: |
return ReduceArrayIteratorNext(node); |
+ case kArrayIsArray: |
+ return ReduceArrayIsArray(node); |
case kArrayPop: |
return ReduceArrayPop(node); |
case kArrayPush: |