[turbofan] Lower monomorphic loads during graph building.
We introduce an explicit LoweringResult data structure. Until this change, the lowering result could be recovered from the node. However, lowering monomorphic loads requires wiring different value and effect, so we need a structure that can express such lowering result. Bug: v8:6357 Change-Id: I92655800890b744d9203a778a1936a8dcd465ed3 Reviewed-on: https://chromium-review.googlesource.com/637304 Commit-Queue: Jaroslav Sevcik <jarin@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#47992}
This commit is contained in:
parent
bc69f3450b
commit
14b424c308
@ -476,7 +476,8 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(
|
||||
Zone* local_zone, Handle<SharedFunctionInfo> shared_info,
|
||||
Handle<FeedbackVector> feedback_vector, BailoutId osr_offset,
|
||||
JSGraph* jsgraph, CallFrequency invocation_frequency,
|
||||
SourcePositionTable* source_positions, int inlining_id,
|
||||
SourcePositionTable* source_positions, Handle<Context> native_context,
|
||||
CompilationDependencies* dependencies, int inlining_id,
|
||||
JSTypeHintLowering::Flags flags, bool stack_check)
|
||||
: local_zone_(local_zone),
|
||||
jsgraph_(jsgraph),
|
||||
@ -485,7 +486,8 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(
|
||||
exception_handler_table_(
|
||||
handle(HandlerTable::cast(bytecode_array()->handler_table()))),
|
||||
feedback_vector_(feedback_vector),
|
||||
type_hint_lowering_(jsgraph, feedback_vector, flags),
|
||||
type_hint_lowering_(jsgraph, feedback_vector, native_context,
|
||||
dependencies, flags, local_zone),
|
||||
frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
|
||||
FrameStateType::kInterpretedFunction,
|
||||
bytecode_array()->parameter_count(),
|
||||
|
@ -16,6 +16,9 @@
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class CompilationDependencies;
|
||||
|
||||
namespace compiler {
|
||||
|
||||
class Reduction;
|
||||
@ -29,7 +32,8 @@ class BytecodeGraphBuilder {
|
||||
Zone* local_zone, Handle<SharedFunctionInfo> shared,
|
||||
Handle<FeedbackVector> feedback_vector, BailoutId osr_offset,
|
||||
JSGraph* jsgraph, CallFrequency invocation_frequency,
|
||||
SourcePositionTable* source_positions,
|
||||
SourcePositionTable* source_positions, Handle<Context> native_context,
|
||||
CompilationDependencies* dependencies,
|
||||
int inlining_id = SourcePosition::kNotInlined,
|
||||
JSTypeHintLowering::Flags flags = JSTypeHintLowering::kNoFlags,
|
||||
bool stack_check = true);
|
||||
|
@ -350,8 +350,7 @@ bool JSInliner::DetermineCallTarget(
|
||||
// TODO(turbofan): We might want to revisit this restriction later when we
|
||||
// have a need for this, and we know how to model different native contexts
|
||||
// in the same graph in a compositional way.
|
||||
if (function->context()->native_context() !=
|
||||
info_->context()->native_context()) {
|
||||
if (function->context()->native_context() != *native_context()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -430,6 +429,10 @@ Reduction JSInliner::Reduce(Node* node) {
|
||||
return ReduceJSCall(node);
|
||||
}
|
||||
|
||||
Handle<Context> JSInliner::native_context() const {
|
||||
return handle(info_->context()->native_context());
|
||||
}
|
||||
|
||||
Reduction JSInliner::ReduceJSCall(Node* node) {
|
||||
DCHECK(IrOpcode::IsInlineeOpcode(node->opcode()));
|
||||
Handle<SharedFunctionInfo> shared_info;
|
||||
@ -541,7 +544,8 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
|
||||
}
|
||||
BytecodeGraphBuilder graph_builder(
|
||||
zone(), shared_info, feedback_vector, BailoutId::None(), jsgraph(),
|
||||
call.frequency(), source_positions_, inlining_id, flags, false);
|
||||
call.frequency(), source_positions_, native_context(),
|
||||
info_->dependencies(), inlining_id, flags, false);
|
||||
graph_builder.CreateGraph();
|
||||
|
||||
// Extract the inlinee start/end nodes.
|
||||
|
@ -47,6 +47,7 @@ class JSInliner final : public AdvancedReducer {
|
||||
SimplifiedOperatorBuilder* simplified() const;
|
||||
Graph* graph() const;
|
||||
JSGraph* jsgraph() const { return jsgraph_; }
|
||||
Handle<Context> native_context() const;
|
||||
|
||||
Zone* const local_zone_;
|
||||
CompilationInfo* info_;
|
||||
|
@ -5,10 +5,13 @@
|
||||
#include "src/compiler/js-type-hint-lowering.h"
|
||||
|
||||
#include "src/compiler/access-builder.h"
|
||||
#include "src/compiler/access-info.h"
|
||||
#include "src/compiler/js-graph.h"
|
||||
#include "src/compiler/operator-properties.h"
|
||||
#include "src/compiler/property-access-builder.h"
|
||||
#include "src/compiler/simplified-operator.h"
|
||||
#include "src/feedback-vector.h"
|
||||
#include "src/handles-inl.h"
|
||||
#include "src/type-hints.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -209,8 +212,17 @@ class JSSpeculativeBinopBuilder final {
|
||||
|
||||
JSTypeHintLowering::JSTypeHintLowering(JSGraph* jsgraph,
|
||||
Handle<FeedbackVector> feedback_vector,
|
||||
Flags flags)
|
||||
: jsgraph_(jsgraph), flags_(flags), feedback_vector_(feedback_vector) {}
|
||||
Handle<Context> native_context,
|
||||
CompilationDependencies* dependencies,
|
||||
Flags flags, Zone* local_zone)
|
||||
: jsgraph_(jsgraph),
|
||||
flags_(flags),
|
||||
feedback_vector_(feedback_vector),
|
||||
native_context_(native_context),
|
||||
dependencies_(dependencies),
|
||||
local_zone_(local_zone) {}
|
||||
|
||||
Graph* JSTypeHintLowering::graph() const { return jsgraph_->graph(); }
|
||||
|
||||
JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceBinaryOperation(
|
||||
const Operator* op, Node* left, Node* right, Node* effect, Node* control,
|
||||
@ -360,7 +372,59 @@ JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceLoadNamedOperation(
|
||||
DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess)) {
|
||||
return LoweringResult::Exit(node);
|
||||
}
|
||||
return LoweringResult::NoChange();
|
||||
|
||||
// Try to extract maps from the feedback vector. Give up if the IC
|
||||
// is megamorphic or unitialized.
|
||||
MapHandles receiver_maps;
|
||||
if (nexus.ExtractMaps(&receiver_maps) == 0) {
|
||||
return LoweringResult::NoChange();
|
||||
}
|
||||
|
||||
// Extract information about accesses from the maps.
|
||||
NamedAccess const& p = NamedAccessOf(op);
|
||||
AccessInfoFactory access_info_factory(dependencies(), native_context(),
|
||||
graph()->zone());
|
||||
|
||||
ZoneVector<PropertyAccessInfo> access_infos(local_zone());
|
||||
if (!access_info_factory.ComputePropertyAccessInfos(
|
||||
receiver_maps, p.name(), AccessMode::kLoad, &access_infos)) {
|
||||
return LoweringResult::NoChange();
|
||||
}
|
||||
|
||||
// Bail out if not monomorphic.
|
||||
if (access_infos.size() != 1) return LoweringResult::NoChange();
|
||||
|
||||
// We only lower data fields and data constants.
|
||||
PropertyAccessInfo const& access_info = access_infos[0];
|
||||
if (!access_info.IsDataField() && !access_info.IsDataConstant()) {
|
||||
return LoweringResult::NoChange();
|
||||
}
|
||||
|
||||
PropertyAccessBuilder access_builder(jsgraph(), dependencies());
|
||||
if (!access_builder.TryBuildStringCheck(access_info.receiver_maps(),
|
||||
&receiver, &effect, control) &&
|
||||
!access_builder.TryBuildNumberCheck(access_info.receiver_maps(),
|
||||
&receiver, &effect, control)) {
|
||||
receiver = access_builder.BuildCheckHeapObject(receiver, &effect, control);
|
||||
access_builder.BuildCheckMaps(receiver, &effect, control,
|
||||
access_info.receiver_maps());
|
||||
}
|
||||
|
||||
Handle<JSObject> holder;
|
||||
if (access_info.holder().ToHandle(&holder)) {
|
||||
access_builder.AssumePrototypesStable(native_context(),
|
||||
access_info.receiver_maps(), holder);
|
||||
}
|
||||
|
||||
Node* value = nullptr;
|
||||
if (access_info.IsDataConstant()) {
|
||||
value = jsgraph()->Constant(access_info.constant());
|
||||
} else {
|
||||
DCHECK(access_info.IsDataField());
|
||||
value = access_builder.BuildLoadDataField(p.name(), access_info, receiver,
|
||||
&effect, &control);
|
||||
}
|
||||
return LoweringResult::SideEffectFree(value, effect, control);
|
||||
}
|
||||
|
||||
JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceLoadKeyedOperation(
|
||||
|
@ -14,6 +14,7 @@ namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// Forward declarations.
|
||||
class CompilationDependencies;
|
||||
class FeedbackNexus;
|
||||
class FeedbackSlot;
|
||||
|
||||
@ -42,7 +43,9 @@ class JSTypeHintLowering {
|
||||
typedef base::Flags<Flag> Flags;
|
||||
|
||||
JSTypeHintLowering(JSGraph* jsgraph, Handle<FeedbackVector> feedback_vector,
|
||||
Flags flags);
|
||||
Handle<Context> native_context,
|
||||
CompilationDependencies* dependencies, Flags flags,
|
||||
Zone* local_zone);
|
||||
|
||||
// {LoweringResult} describes the result of lowering. The following outcomes
|
||||
// are possible:
|
||||
@ -156,11 +159,21 @@ class JSTypeHintLowering {
|
||||
const Handle<FeedbackVector>& feedback_vector() const {
|
||||
return feedback_vector_;
|
||||
}
|
||||
Graph* graph() const;
|
||||
Zone* local_zone() const { return local_zone_; }
|
||||
|
||||
Handle<Context> native_context() const { return native_context_; }
|
||||
CompilationDependencies* dependencies() const { return dependencies_; }
|
||||
|
||||
JSGraph* jsgraph_;
|
||||
Flags const flags_;
|
||||
Handle<FeedbackVector> feedback_vector_;
|
||||
|
||||
Handle<Context> native_context_;
|
||||
CompilationDependencies* dependencies_;
|
||||
|
||||
Zone* local_zone_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JSTypeHintLowering);
|
||||
};
|
||||
|
||||
|
@ -893,7 +893,8 @@ struct GraphBuilderPhase {
|
||||
temp_zone, data->info()->shared_info(),
|
||||
handle(data->info()->closure()->feedback_vector()),
|
||||
data->info()->osr_offset(), data->jsgraph(), CallFrequency(1.0f),
|
||||
data->source_positions(), SourcePosition::kNotInlined, flags);
|
||||
data->source_positions(), data->native_context(),
|
||||
data->info()->dependencies(), SourcePosition::kNotInlined, flags);
|
||||
graph_builder.CreateGraph();
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user