Commit 94b33165 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Skip JSCallReducer and JSNativeContextSpecialization on asm.js.

For the old asm.js pipeline, there's no point in running either the
JSCallReducer or the JSNativeContextSpecialization, as both will not
kick in for any asm.js relevant code.

So remove the kDeoptimizationEnabled flag from both of them and just
run them on regular JavaScript only.

Drive-by-fix: Slightly rearrange keyed access to String receivers in the
JSNativeContextSpecialization::ReduceKeyedAccess method to access constant
characters independent of the IC mode (as long as the constant index is
within the range of the receiver).

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

Review-Url: https://codereview.chromium.org/2743253002
Cr-Commit-Position: refs/heads/master@{#43813}
parent 5790aad4
......@@ -617,9 +617,6 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
return Changed(node);
}
// Not much we can do if deoptimization support is disabled.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
Handle<Object> feedback(nexus.GetFeedback(), isolate());
if (feedback->IsAllocationSite()) {
// Retrieve the Array function from the {node}.
......@@ -727,9 +724,6 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
return NoChange();
}
// Not much we can do if deoptimization support is disabled.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
if (!p.feedback().IsValid()) return NoChange();
CallICNexus nexus(p.feedback().vector(), p.feedback().slot());
Handle<Object> feedback(nexus.GetFeedback(), isolate());
......
......@@ -27,19 +27,11 @@ class SimplifiedOperatorBuilder;
// which might allow inlining or other optimizations to be performed afterwards.
class JSCallReducer final : public AdvancedReducer {
public:
// Flags that control the mode of operation.
enum Flag {
kNoFlags = 0u,
kDeoptimizationEnabled = 1u << 0,
};
typedef base::Flags<Flag> Flags;
JSCallReducer(Editor* editor, JSGraph* jsgraph, Flags flags,
JSCallReducer(Editor* editor, JSGraph* jsgraph,
Handle<Context> native_context,
CompilationDependencies* dependencies)
: AdvancedReducer(editor),
jsgraph_(jsgraph),
flags_(flags),
native_context_(native_context),
dependencies_(dependencies) {}
......@@ -68,7 +60,6 @@ class JSCallReducer final : public AdvancedReducer {
Handle<JSObject>* holder);
Graph* graph() const;
Flags flags() const { return flags_; }
JSGraph* jsgraph() const { return jsgraph_; }
Isolate* isolate() const;
Factory* factory() const;
......@@ -79,13 +70,10 @@ class JSCallReducer final : public AdvancedReducer {
CompilationDependencies* dependencies() const { return dependencies_; }
JSGraph* const jsgraph_;
Flags const flags_;
Handle<Context> const native_context_;
CompilationDependencies* const dependencies_;
};
DEFINE_OPERATORS_FOR_FLAGS(JSCallReducer::Flags)
} // namespace compiler
} // namespace internal
} // namespace v8
......
......@@ -138,9 +138,6 @@ Reduction JSNativeContextSpecialization::ReduceJSGetSuperConstructor(
DCHECK_EQ(IrOpcode::kJSGetSuperConstructor, node->opcode());
Node* constructor = NodeProperties::GetValueInput(node, 0);
// If deoptimization is disabled, we cannot optimize.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
// Check if the input is a known JSFunction.
HeapObjectMatcher m(constructor);
if (!m.HasValue()) return NoChange();
......@@ -176,9 +173,6 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// If deoptimization is disabled, we cannot optimize.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
// Check if the right hand side is a known {receiver}.
HeapObjectMatcher m(constructor);
if (!m.HasValue() || !m.Value()->IsJSObject()) return NoChange();
......@@ -529,9 +523,6 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadGlobal(Node* node) {
return Replace(value);
}
// Not much we can do if deoptimization support is disabled.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
// Lookup the {name} on the global object instead.
return ReduceGlobalAccess(node, nullptr, nullptr, name, AccessMode::kLoad);
}
......@@ -555,9 +546,6 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) {
return Replace(value);
}
// Not much we can do if deoptimization support is disabled.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
// Lookup the {name} on the global object instead.
return ReduceGlobalAccess(node, nullptr, value, name, AccessMode::kStore);
}
......@@ -577,9 +565,6 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// Not much we can do if deoptimization support is disabled.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
// Check if we have an access o.x or o.x=v where o is the current
// native contexts' global proxy, and turn that into a direct access
// to the current native contexts' global object instead.
......@@ -806,19 +791,16 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus(
Node* const receiver = NodeProperties::GetValueInput(node, 0);
Node* const effect = NodeProperties::GetEffectInput(node);
if (flags() & kDeoptimizationEnabled) {
// Check if we are accessing the current native contexts' global proxy.
HeapObjectMatcher m(receiver);
if (m.HasValue() && m.Value().is_identical_to(global_proxy())) {
// Optimize accesses to the current native contexts' global proxy.
return ReduceGlobalAccess(node, nullptr, value, name, access_mode);
}
// Check if we are accessing the current native contexts' global proxy.
HeapObjectMatcher m(receiver);
if (m.HasValue() && m.Value().is_identical_to(global_proxy())) {
// Optimize accesses to the current native contexts' global proxy.
return ReduceGlobalAccess(node, nullptr, value, name, access_mode);
}
// Check if the {nexus} reports type feedback for the IC.
if (nexus.IsUninitialized()) {
if ((flags() & kDeoptimizationEnabled) &&
(flags() & kBailoutOnUninitialized)) {
if (flags() & kBailoutOnUninitialized) {
return ReduceSoftDeoptimize(
node,
DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
......@@ -831,8 +813,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus(
if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) {
return NoChange();
} else if (receiver_maps.length() == 0) {
if ((flags() & kDeoptimizationEnabled) &&
(flags() & kBailoutOnUninitialized)) {
if (flags() & kBailoutOnUninitialized) {
return ReduceSoftDeoptimize(
node,
DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
......@@ -863,14 +844,12 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
// {function} in order to be notified about changes to the
// "prototype" of {function}, so it doesn't make sense to
// continue unless deoptimization is enabled.
if (flags() & kDeoptimizationEnabled) {
Handle<Map> initial_map(function->initial_map(), isolate());
dependencies()->AssumeInitialMapCantChange(initial_map);
Handle<Object> prototype(initial_map->prototype(), isolate());
Node* value = jsgraph()->Constant(prototype);
ReplaceWithValue(node, value);
return Replace(value);
}
Handle<Map> initial_map(function->initial_map(), isolate());
dependencies()->AssumeInitialMapCantChange(initial_map);
Handle<Object> prototype(initial_map->prototype(), isolate());
Node* value = jsgraph()->Constant(prototype);
ReplaceWithValue(node, value);
return Replace(value);
}
} else if (m.Value()->IsString() &&
p.name().is_identical_to(factory()->length_string())) {
......@@ -931,9 +910,6 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
Node* control = NodeProperties::GetControlInput(node);
Node* frame_state = NodeProperties::FindFrameStateBefore(node);
// Not much we can do if deoptimization support is disabled.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
// Check for keyed access to strings.
if (HasOnlyStringMaps(receiver_maps)) {
// Strings are immutable in JavaScript.
......@@ -1179,41 +1155,40 @@ Reduction JSNativeContextSpecialization::ReduceKeyedAccess(
if (mreceiver.HasValue() && mreceiver.Value()->IsString()) {
Handle<String> string = Handle<String>::cast(mreceiver.Value());
// Strings are immutable in JavaScript.
if (access_mode == AccessMode::kStore) return NoChange();
// Properly deal with constant {index}.
NumberMatcher mindex(index);
if (mindex.IsInteger() && mindex.IsInRange(0.0, string->length() - 1)) {
// Constant-fold the {index} access to {string}.
Node* value = jsgraph()->HeapConstant(
factory()->LookupSingleCharacterStringFromCode(
string->Get(static_cast<int>(mindex.Value()))));
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
// We can only assume that the {index} is a valid array index if the IC
// is in element access mode and not MEGAMORPHIC, otherwise there's no
// guard for the bounds check below.
if (nexus.ic_state() != MEGAMORPHIC && nexus.GetKeyType() == ELEMENT) {
// Strings are immutable in JavaScript.
if (access_mode == AccessMode::kStore) return NoChange();
// Properly deal with constant {index}.
NumberMatcher mindex(index);
if (mindex.IsInteger() && mindex.IsInRange(0.0, string->length() - 1)) {
// Constant-fold the {index} access to {string}.
Node* value = jsgraph()->HeapConstant(
factory()->LookupSingleCharacterStringFromCode(
string->Get(static_cast<int>(mindex.Value()))));
ReplaceWithValue(node, value, effect, control);
return Replace(value);
} else if (flags() & kDeoptimizationEnabled) {
// Ensure that {index} is less than {receiver} length.
Node* length = jsgraph()->Constant(string->length());
index = effect = graph()->NewNode(simplified()->CheckBounds(), index,
length, effect, control);
// Return the character from the {receiver} as single character string.
value = graph()->NewNode(simplified()->StringCharAt(), receiver, index,
control);
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
// Ensure that {index} is less than {receiver} length.
Node* length = jsgraph()->Constant(string->length());
index = effect = graph()->NewNode(simplified()->CheckBounds(), index,
length, effect, control);
// Return the character from the {receiver} as single character string.
value = graph()->NewNode(simplified()->StringCharAt(), receiver, index,
control);
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
}
// Check if the {nexus} reports type feedback for the IC.
if (nexus.IsUninitialized()) {
if ((flags() & kDeoptimizationEnabled) &&
(flags() & kBailoutOnUninitialized)) {
if (flags() & kBailoutOnUninitialized) {
return ReduceSoftDeoptimize(
node,
DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
......@@ -1226,8 +1201,7 @@ Reduction JSNativeContextSpecialization::ReduceKeyedAccess(
if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) {
return NoChange();
} else if (receiver_maps.length() == 0) {
if ((flags() & kDeoptimizationEnabled) &&
(flags() & kBailoutOnUninitialized)) {
if (flags() & kBailoutOnUninitialized) {
return ReduceSoftDeoptimize(
node,
DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
......@@ -1698,9 +1672,6 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral(
Node* node) {
DCHECK_EQ(IrOpcode::kJSStoreDataPropertyInLiteral, node->opcode());
// If deoptimization is disabled, we cannot optimize.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
FeedbackParameter const& p = FeedbackParameterOf(node->op());
if (!p.feedback().IsValid()) return NoChange();
......
......@@ -40,8 +40,7 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
enum Flag {
kNoFlags = 0u,
kAccessorInliningEnabled = 1u << 0,
kBailoutOnUninitialized = 1u << 1,
kDeoptimizationEnabled = 1u << 2,
kBailoutOnUninitialized = 1u << 1
};
typedef base::Flags<Flag> Flags;
......
......@@ -783,12 +783,8 @@ struct InliningPhase {
CheckpointElimination checkpoint_elimination(&graph_reducer);
CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
data->common(), data->machine());
JSCallReducer::Flags call_reducer_flags = JSCallReducer::kNoFlags;
if (data->info()->is_deoptimization_enabled()) {
call_reducer_flags |= JSCallReducer::kDeoptimizationEnabled;
}
JSCallReducer call_reducer(&graph_reducer, data->jsgraph(),
call_reducer_flags, data->native_context(),
data->native_context(),
data->info()->dependencies());
JSContextSpecialization context_specialization(
&graph_reducer, data->jsgraph(),
......@@ -805,9 +801,6 @@ struct InliningPhase {
if (data->info()->is_bailout_on_uninitialized()) {
flags |= JSNativeContextSpecialization::kBailoutOnUninitialized;
}
if (data->info()->is_deoptimization_enabled()) {
flags |= JSNativeContextSpecialization::kDeoptimizationEnabled;
}
JSNativeContextSpecialization native_context_specialization(
&graph_reducer, data->jsgraph(), flags, data->native_context(),
data->info()->dependencies(), temp_zone);
......@@ -827,10 +820,14 @@ struct InliningPhase {
if (data->info()->is_frame_specializing()) {
AddReducer(data, &graph_reducer, &frame_specialization);
}
AddReducer(data, &graph_reducer, &native_context_specialization);
if (data->info()->is_deoptimization_enabled()) {
AddReducer(data, &graph_reducer, &native_context_specialization);
}
AddReducer(data, &graph_reducer, &context_specialization);
AddReducer(data, &graph_reducer, &intrinsic_lowering);
AddReducer(data, &graph_reducer, &call_reducer);
if (data->info()->is_deoptimization_enabled()) {
AddReducer(data, &graph_reducer, &call_reducer);
}
AddReducer(data, &graph_reducer, &inlining);
graph_reducer.ReduceGraph();
}
......
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