Commit c45da1b4 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Inline Array.isArray in JSBuiltinReducer.

Inline the Array.isArray builtin during typed lowering, which generates
ideal code for the common case (non-JSProxy arg), and use the existing
%ArrayIsArray runtime function for the JSProxy case just like in baseline.

BUG=v8:5267
R=jarin@chromium.org

Review-Url: https://codereview.chromium.org/2719023002
Cr-Commit-Position: refs/heads/master@{#43453}
parent 0e21a147
...@@ -725,6 +725,104 @@ Reduction JSBuiltinReducer::ReduceArrayIteratorNext(Node* node) { ...@@ -725,6 +725,104 @@ Reduction JSBuiltinReducer::ReduceArrayIteratorNext(Node* node) {
return NoChange(); 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 ( ) // ES6 section 22.1.3.17 Array.prototype.pop ( )
Reduction JSBuiltinReducer::ReduceArrayPop(Node* node) { Reduction JSBuiltinReducer::ReduceArrayPop(Node* node) {
Handle<Map> receiver_map; Handle<Map> receiver_map;
...@@ -1969,6 +2067,8 @@ Reduction JSBuiltinReducer::Reduce(Node* node) { ...@@ -1969,6 +2067,8 @@ Reduction JSBuiltinReducer::Reduce(Node* node) {
return ReduceArrayIterator(node, IterationKind::kValues); return ReduceArrayIterator(node, IterationKind::kValues);
case kArrayIteratorNext: case kArrayIteratorNext:
return ReduceArrayIteratorNext(node); return ReduceArrayIteratorNext(node);
case kArrayIsArray:
return ReduceArrayIsArray(node);
case kArrayPop: case kArrayPop:
return ReduceArrayPop(node); return ReduceArrayPop(node);
case kArrayPush: case kArrayPush:
......
...@@ -55,6 +55,7 @@ class V8_EXPORT_PRIVATE JSBuiltinReducer final ...@@ -55,6 +55,7 @@ class V8_EXPORT_PRIVATE JSBuiltinReducer final
IterationKind kind); IterationKind kind);
Reduction ReduceTypedArrayIteratorNext(Handle<Map> iterator_map, Node* node, Reduction ReduceTypedArrayIteratorNext(Handle<Map> iterator_map, Node* node,
IterationKind kind); IterationKind kind);
Reduction ReduceArrayIsArray(Node* node);
Reduction ReduceArrayPop(Node* node); Reduction ReduceArrayPop(Node* node);
Reduction ReduceArrayPush(Node* node); Reduction ReduceArrayPush(Node* node);
Reduction ReduceDateNow(Node* node); Reduction ReduceDateNow(Node* node);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment