Commit 9b14e5bb authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Decouple inlining and native context specialization.

Retrieve the native context/global object from the Node being
specialized in the JSNativeContextSpecialization and the
JSGlobalObjectSpecialization classes. For this we introduce two
new methods NodeProperties::GetSpecializationNativeContext and
NodeProperties::GetSpecializationGlobalObject, which walk up
the context chain and might in the end take the native context
from the outermost activation (if native context specialization
is enabled). This allows us to run the native context specialization
pass as part of the inlining phase without hacking some of that into
the JSInliner.

Also refactor the NodeProperties::GetSpecializationContext method
that was previously local to the JSContextSpecialization.

Also refactor two other oddities in JSNativeContextSpecialization.

R=jarin@chromium.org
BUG=v8:4470, v8:4493
LOG=n

Review URL: https://codereview.chromium.org/1451143005

Cr-Commit-Position: refs/heads/master@{#32076}
parent a9fa0498
...@@ -124,6 +124,20 @@ void CompilationDependencies::AssumeMapStable(Handle<Map> map) { ...@@ -124,6 +124,20 @@ void CompilationDependencies::AssumeMapStable(Handle<Map> map) {
} }
void CompilationDependencies::AssumePrototypeMapsStable(
Handle<Map> map, MaybeHandle<JSReceiver> prototype) {
for (PrototypeIterator i(map); !i.IsAtEnd(); i.Advance()) {
Handle<JSReceiver> const current =
PrototypeIterator::GetCurrent<JSReceiver>(i);
AssumeMapStable(handle(current->map()));
Handle<JSReceiver> last;
if (prototype.ToHandle(&last) && last.is_identical_to(current)) {
break;
}
}
}
void CompilationDependencies::AssumeTransitionStable( void CompilationDependencies::AssumeTransitionStable(
Handle<AllocationSite> site) { Handle<AllocationSite> site) {
// Do nothing if the object doesn't have any useful element transitions left. // Do nothing if the object doesn't have any useful element transitions left.
...@@ -135,5 +149,6 @@ void CompilationDependencies::AssumeTransitionStable( ...@@ -135,5 +149,6 @@ void CompilationDependencies::AssumeTransitionStable(
Insert(DependentCode::kAllocationSiteTransitionChangedGroup, site); Insert(DependentCode::kAllocationSiteTransitionChangedGroup, site);
} }
} }
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -32,6 +32,9 @@ class CompilationDependencies { ...@@ -32,6 +32,9 @@ class CompilationDependencies {
Insert(DependentCode::kFieldTypeGroup, map); Insert(DependentCode::kFieldTypeGroup, map);
} }
void AssumeMapStable(Handle<Map> map); void AssumeMapStable(Handle<Map> map);
void AssumePrototypeMapsStable(
Handle<Map> map,
MaybeHandle<JSReceiver> prototype = MaybeHandle<JSReceiver>());
void AssumeMapNotDeprecated(Handle<Map> map); void AssumeMapNotDeprecated(Handle<Map> map);
void AssumePropertyCell(Handle<PropertyCell> cell) { void AssumePropertyCell(Handle<PropertyCell> cell) {
Insert(DependentCode::kPropertyCellChangedGroup, cell); Insert(DependentCode::kPropertyCellChangedGroup, cell);
......
...@@ -297,6 +297,12 @@ class CompilationInfo { ...@@ -297,6 +297,12 @@ class CompilationInfo {
return has_global_object() ? closure()->context()->global_object() : NULL; return has_global_object() ? closure()->context()->global_object() : NULL;
} }
bool has_native_context() const { return has_global_object(); }
Context* native_context() const {
return has_native_context() ? global_object()->native_context() : nullptr;
}
// Accessors for the different compilation modes. // Accessors for the different compilation modes.
bool IsOptimizing() const { return mode_ == OPTIMIZE; } bool IsOptimizing() const { return mode_ == OPTIMIZE; }
bool IsStub() const { return mode_ == STUB; } bool IsStub() const { return mode_ == STUB; }
......
...@@ -73,6 +73,20 @@ FieldAccess AccessBuilder::ForJSFunctionSharedFunctionInfo() { ...@@ -73,6 +73,20 @@ FieldAccess AccessBuilder::ForJSFunctionSharedFunctionInfo() {
} }
// static
FieldAccess AccessBuilder::ForJSArrayLength(ElementsKind elements_kind) {
TypeCache const& type_cache = TypeCache::Get();
FieldAccess access = {kTaggedBase, JSArray::kLengthOffset, Handle<Name>(),
type_cache.kJSArrayLengthType, kMachAnyTagged};
if (IsFastDoubleElementsKind(elements_kind)) {
access.type = type_cache.kFixedDoubleArrayLengthType;
} else if (IsFastElementsKind(elements_kind)) {
access.type = type_cache.kFixedArrayLengthType;
}
return access;
}
// static // static
FieldAccess AccessBuilder::ForJSArrayBufferBackingStore() { FieldAccess AccessBuilder::ForJSArrayBufferBackingStore() {
FieldAccess access = {kTaggedBase, JSArrayBuffer::kBackingStoreOffset, FieldAccess access = {kTaggedBase, JSArrayBuffer::kBackingStoreOffset,
......
...@@ -40,6 +40,9 @@ class AccessBuilder final : public AllStatic { ...@@ -40,6 +40,9 @@ class AccessBuilder final : public AllStatic {
// Provides access to JSFunction::shared() field. // Provides access to JSFunction::shared() field.
static FieldAccess ForJSFunctionSharedFunctionInfo(); static FieldAccess ForJSFunctionSharedFunctionInfo();
// Provides access to JSArray::length() field.
static FieldAccess ForJSArrayLength(ElementsKind elements_kind);
// Provides access to JSArrayBuffer::backing_store() field. // Provides access to JSArrayBuffer::backing_store() field.
static FieldAccess ForJSArrayBufferBackingStore(); static FieldAccess ForJSArrayBufferBackingStore();
......
...@@ -135,7 +135,9 @@ AccessInfoFactory::AccessInfoFactory(CompilationDependencies* dependencies, ...@@ -135,7 +135,9 @@ AccessInfoFactory::AccessInfoFactory(CompilationDependencies* dependencies,
native_context_(native_context), native_context_(native_context),
isolate_(native_context->GetIsolate()), isolate_(native_context->GetIsolate()),
type_cache_(TypeCache::Get()), type_cache_(TypeCache::Get()),
zone_(zone) {} zone_(zone) {
DCHECK(native_context->IsNativeContext());
}
bool AccessInfoFactory::ComputeElementAccessInfo( bool AccessInfoFactory::ComputeElementAccessInfo(
......
...@@ -34,25 +34,7 @@ MaybeHandle<Context> JSContextSpecialization::GetSpecializationContext( ...@@ -34,25 +34,7 @@ MaybeHandle<Context> JSContextSpecialization::GetSpecializationContext(
DCHECK(node->opcode() == IrOpcode::kJSLoadContext || DCHECK(node->opcode() == IrOpcode::kJSLoadContext ||
node->opcode() == IrOpcode::kJSStoreContext); node->opcode() == IrOpcode::kJSStoreContext);
Node* const object = NodeProperties::GetValueInput(node, 0); Node* const object = NodeProperties::GetValueInput(node, 0);
switch (object->opcode()) { return NodeProperties::GetSpecializationContext(object, context());
case IrOpcode::kHeapConstant:
return Handle<Context>::cast(OpParameter<Handle<HeapObject>>(object));
case IrOpcode::kParameter: {
Node* const start = NodeProperties::GetValueInput(object, 0);
DCHECK_EQ(IrOpcode::kStart, start->opcode());
int const index = ParameterIndexOf(object->op());
// The context is always the last parameter to a JavaScript function, and
// {Parameter} indices start at -1, so value outputs of {Start} look like
// this: closure, receiver, param0, ..., paramN, context.
if (index == start->op()->ValueOutputCount() - 2) {
return context();
}
break;
}
default:
break;
}
return MaybeHandle<Context>();
} }
......
...@@ -28,13 +28,11 @@ struct JSGlobalObjectSpecialization::ScriptContextTableLookupResult { ...@@ -28,13 +28,11 @@ struct JSGlobalObjectSpecialization::ScriptContextTableLookupResult {
JSGlobalObjectSpecialization::JSGlobalObjectSpecialization( JSGlobalObjectSpecialization::JSGlobalObjectSpecialization(
Editor* editor, JSGraph* jsgraph, Flags flags, Editor* editor, JSGraph* jsgraph, Flags flags,
Handle<JSGlobalObject> global_object, CompilationDependencies* dependencies) MaybeHandle<Context> native_context, CompilationDependencies* dependencies)
: AdvancedReducer(editor), : AdvancedReducer(editor),
jsgraph_(jsgraph), jsgraph_(jsgraph),
flags_(flags), flags_(flags),
global_object_(global_object), native_context_(native_context),
script_context_table_(
global_object->native_context()->script_context_table(), isolate()),
dependencies_(dependencies), dependencies_(dependencies),
type_cache_(TypeCache::Get()) {} type_cache_(TypeCache::Get()) {}
...@@ -58,9 +56,13 @@ Reduction JSGlobalObjectSpecialization::ReduceJSLoadGlobal(Node* node) { ...@@ -58,9 +56,13 @@ Reduction JSGlobalObjectSpecialization::ReduceJSLoadGlobal(Node* node) {
Node* effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node); Node* control = NodeProperties::GetControlInput(node);
// Retrieve the global object from the given {node}.
Handle<JSGlobalObject> global_object;
if (!GetGlobalObject(node).ToHandle(&global_object)) return NoChange();
// Try to lookup the name on the script context table first (lexical scoping). // Try to lookup the name on the script context table first (lexical scoping).
ScriptContextTableLookupResult result; ScriptContextTableLookupResult result;
if (LookupInScriptContextTable(name, &result)) { if (LookupInScriptContextTable(global_object, name, &result)) {
if (result.context->is_the_hole(result.index)) return NoChange(); if (result.context->is_the_hole(result.index)) return NoChange();
Node* context = jsgraph()->HeapConstant(result.context); Node* context = jsgraph()->HeapConstant(result.context);
Node* value = effect = graph()->NewNode( Node* value = effect = graph()->NewNode(
...@@ -72,7 +74,7 @@ Reduction JSGlobalObjectSpecialization::ReduceJSLoadGlobal(Node* node) { ...@@ -72,7 +74,7 @@ Reduction JSGlobalObjectSpecialization::ReduceJSLoadGlobal(Node* node) {
// Lookup on the global object instead. We only deal with own data // Lookup on the global object instead. We only deal with own data
// properties of the global object here (represented as PropertyCell). // properties of the global object here (represented as PropertyCell).
LookupIterator it(global_object(), name, LookupIterator::OWN); LookupIterator it(global_object, name, LookupIterator::OWN);
if (it.state() != LookupIterator::DATA) return NoChange(); if (it.state() != LookupIterator::DATA) return NoChange();
Handle<PropertyCell> property_cell = it.GetPropertyCell(); Handle<PropertyCell> property_cell = it.GetPropertyCell();
PropertyDetails property_details = property_cell->property_details(); PropertyDetails property_details = property_cell->property_details();
...@@ -145,9 +147,13 @@ Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) { ...@@ -145,9 +147,13 @@ Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) {
Node* effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node); Node* control = NodeProperties::GetControlInput(node);
// Retrieve the global object from the given {node}.
Handle<JSGlobalObject> global_object;
if (!GetGlobalObject(node).ToHandle(&global_object)) return NoChange();
// Try to lookup the name on the script context table first (lexical scoping). // Try to lookup the name on the script context table first (lexical scoping).
ScriptContextTableLookupResult result; ScriptContextTableLookupResult result;
if (LookupInScriptContextTable(name, &result)) { if (LookupInScriptContextTable(global_object, name, &result)) {
if (result.context->is_the_hole(result.index)) return NoChange(); if (result.context->is_the_hole(result.index)) return NoChange();
if (result.immutable) return NoChange(); if (result.immutable) return NoChange();
Node* context = jsgraph()->HeapConstant(result.context); Node* context = jsgraph()->HeapConstant(result.context);
...@@ -159,7 +165,7 @@ Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) { ...@@ -159,7 +165,7 @@ Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) {
// Lookup on the global object instead. We only deal with own data // Lookup on the global object instead. We only deal with own data
// properties of the global object here (represented as PropertyCell). // properties of the global object here (represented as PropertyCell).
LookupIterator it(global_object(), name, LookupIterator::OWN); LookupIterator it(global_object, name, LookupIterator::OWN);
if (it.state() != LookupIterator::DATA) return NoChange(); if (it.state() != LookupIterator::DATA) return NoChange();
Handle<PropertyCell> property_cell = it.GetPropertyCell(); Handle<PropertyCell> property_cell = it.GetPropertyCell();
PropertyDetails property_details = property_cell->property_details(); PropertyDetails property_details = property_cell->property_details();
...@@ -254,16 +260,27 @@ Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) { ...@@ -254,16 +260,27 @@ Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) {
} }
MaybeHandle<JSGlobalObject> JSGlobalObjectSpecialization::GetGlobalObject(
Node* node) {
Node* const context = NodeProperties::GetContextInput(node);
return NodeProperties::GetSpecializationGlobalObject(context,
native_context());
}
bool JSGlobalObjectSpecialization::LookupInScriptContextTable( bool JSGlobalObjectSpecialization::LookupInScriptContextTable(
Handle<Name> name, ScriptContextTableLookupResult* result) { Handle<JSGlobalObject> global_object, Handle<Name> name,
ScriptContextTableLookupResult* result) {
if (!name->IsString()) return false; if (!name->IsString()) return false;
Handle<ScriptContextTable> script_context_table(
global_object->native_context()->script_context_table(), isolate());
ScriptContextTable::LookupResult lookup_result; ScriptContextTable::LookupResult lookup_result;
if (!ScriptContextTable::Lookup(script_context_table(), if (!ScriptContextTable::Lookup(script_context_table,
Handle<String>::cast(name), &lookup_result)) { Handle<String>::cast(name), &lookup_result)) {
return false; return false;
} }
Handle<Context> script_context = ScriptContextTable::GetContext( Handle<Context> script_context = ScriptContextTable::GetContext(
script_context_table(), lookup_result.context_index); script_context_table, lookup_result.context_index);
result->context = script_context; result->context = script_context;
result->immutable = IsImmutableVariableMode(lookup_result.mode); result->immutable = IsImmutableVariableMode(lookup_result.mode);
result->index = lookup_result.slot_index; result->index = lookup_result.slot_index;
......
...@@ -13,7 +13,6 @@ namespace internal { ...@@ -13,7 +13,6 @@ namespace internal {
// Forward declarations. // Forward declarations.
class CompilationDependencies; class CompilationDependencies;
class ScriptContextTable;
class TypeCache; class TypeCache;
...@@ -39,7 +38,7 @@ class JSGlobalObjectSpecialization final : public AdvancedReducer { ...@@ -39,7 +38,7 @@ class JSGlobalObjectSpecialization final : public AdvancedReducer {
typedef base::Flags<Flag> Flags; typedef base::Flags<Flag> Flags;
JSGlobalObjectSpecialization(Editor* editor, JSGraph* jsgraph, Flags flags, JSGlobalObjectSpecialization(Editor* editor, JSGraph* jsgraph, Flags flags,
Handle<JSGlobalObject> global_object, MaybeHandle<Context> native_context,
CompilationDependencies* dependencies); CompilationDependencies* dependencies);
Reduction Reduce(Node* node) final; Reduction Reduce(Node* node) final;
...@@ -48,8 +47,12 @@ class JSGlobalObjectSpecialization final : public AdvancedReducer { ...@@ -48,8 +47,12 @@ class JSGlobalObjectSpecialization final : public AdvancedReducer {
Reduction ReduceJSLoadGlobal(Node* node); Reduction ReduceJSLoadGlobal(Node* node);
Reduction ReduceJSStoreGlobal(Node* node); Reduction ReduceJSStoreGlobal(Node* node);
// Retrieve the global object from the given {node} if known.
MaybeHandle<JSGlobalObject> GetGlobalObject(Node* node);
struct ScriptContextTableLookupResult; struct ScriptContextTableLookupResult;
bool LookupInScriptContextTable(Handle<Name> name, bool LookupInScriptContextTable(Handle<JSGlobalObject> global_object,
Handle<Name> name,
ScriptContextTableLookupResult* result); ScriptContextTableLookupResult* result);
Graph* graph() const; Graph* graph() const;
...@@ -59,16 +62,12 @@ class JSGlobalObjectSpecialization final : public AdvancedReducer { ...@@ -59,16 +62,12 @@ class JSGlobalObjectSpecialization final : public AdvancedReducer {
JSOperatorBuilder* javascript() const; JSOperatorBuilder* javascript() const;
SimplifiedOperatorBuilder* simplified() const; SimplifiedOperatorBuilder* simplified() const;
Flags flags() const { return flags_; } Flags flags() const { return flags_; }
Handle<JSGlobalObject> global_object() const { return global_object_; } MaybeHandle<Context> native_context() const { return native_context_; }
Handle<ScriptContextTable> script_context_table() const {
return script_context_table_;
}
CompilationDependencies* dependencies() const { return dependencies_; } CompilationDependencies* dependencies() const { return dependencies_; }
JSGraph* const jsgraph_; JSGraph* const jsgraph_;
Flags const flags_; Flags const flags_;
Handle<JSGlobalObject> global_object_; MaybeHandle<Context> native_context_;
Handle<ScriptContextTable> script_context_table_;
CompilationDependencies* const dependencies_; CompilationDependencies* const dependencies_;
TypeCache const& type_cache_; TypeCache const& type_cache_;
......
...@@ -10,11 +10,7 @@ ...@@ -10,11 +10,7 @@
#include "src/compiler/all-nodes.h" #include "src/compiler/all-nodes.h"
#include "src/compiler/ast-graph-builder.h" #include "src/compiler/ast-graph-builder.h"
#include "src/compiler/common-operator.h" #include "src/compiler/common-operator.h"
#include "src/compiler/common-operator-reducer.h"
#include "src/compiler/dead-code-elimination.h"
#include "src/compiler/graph-reducer.h" #include "src/compiler/graph-reducer.h"
#include "src/compiler/js-global-object-specialization.h"
#include "src/compiler/js-native-context-specialization.h"
#include "src/compiler/js-operator.h" #include "src/compiler/js-operator.h"
#include "src/compiler/node-matchers.h" #include "src/compiler/node-matchers.h"
#include "src/compiler/node-properties.h" #include "src/compiler/node-properties.h"
...@@ -356,9 +352,6 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) { ...@@ -356,9 +352,6 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
if (info_->is_deoptimization_enabled()) { if (info_->is_deoptimization_enabled()) {
info.MarkAsDeoptimizationEnabled(); info.MarkAsDeoptimizationEnabled();
} }
if (info_->is_native_context_specializing()) {
info.MarkAsNativeContextSpecializing();
}
if (!Compiler::ParseAndAnalyze(info.parse_info())) { if (!Compiler::ParseAndAnalyze(info.parse_info())) {
TRACE("Not inlining %s into %s because parsing failed\n", TRACE("Not inlining %s into %s because parsing failed\n",
...@@ -410,34 +403,6 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) { ...@@ -410,34 +403,6 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
AstGraphBuilder graph_builder(local_zone_, &info, &jsgraph); AstGraphBuilder graph_builder(local_zone_, &info, &jsgraph);
graph_builder.CreateGraph(false); graph_builder.CreateGraph(false);
// TODO(mstarzinger): Unify this with the Pipeline once JSInliner refactoring
// starts.
if (info.is_native_context_specializing()) {
GraphReducer graph_reducer(local_zone_, &graph, jsgraph.Dead());
DeadCodeElimination dead_code_elimination(&graph_reducer, &graph,
jsgraph.common());
CommonOperatorReducer common_reducer(&graph_reducer, &graph,
jsgraph.common(), jsgraph.machine());
JSGlobalObjectSpecialization global_object_specialization(
&graph_reducer, &jsgraph,
info.is_deoptimization_enabled()
? JSGlobalObjectSpecialization::kDeoptimizationEnabled
: JSGlobalObjectSpecialization::kNoFlags,
handle(info.global_object(), info.isolate()), info_->dependencies());
JSNativeContextSpecialization native_context_specialization(
&graph_reducer, &jsgraph,
info.is_deoptimization_enabled()
? JSNativeContextSpecialization::kDeoptimizationEnabled
: JSNativeContextSpecialization::kNoFlags,
handle(info.global_object()->native_context(), info.isolate()),
info_->dependencies(), local_zone_);
graph_reducer.AddReducer(&dead_code_elimination);
graph_reducer.AddReducer(&common_reducer);
graph_reducer.AddReducer(&global_object_specialization);
graph_reducer.AddReducer(&native_context_specialization);
graph_reducer.ReduceGraph();
}
CopyVisitor visitor(&graph, jsgraph_->graph(), &zone); CopyVisitor visitor(&graph, jsgraph_->graph(), &zone);
visitor.CopyGraph(); visitor.CopyGraph();
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "src/code-factory.h" #include "src/code-factory.h"
#include "src/compilation-dependencies.h" #include "src/compilation-dependencies.h"
#include "src/compiler/access-builder.h" #include "src/compiler/access-builder.h"
#include "src/compiler/access-info.h"
#include "src/compiler/js-graph.h" #include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h" #include "src/compiler/js-operator.h"
#include "src/compiler/linkage.h" #include "src/compiler/linkage.h"
...@@ -24,7 +25,7 @@ namespace compiler { ...@@ -24,7 +25,7 @@ namespace compiler {
JSNativeContextSpecialization::JSNativeContextSpecialization( JSNativeContextSpecialization::JSNativeContextSpecialization(
Editor* editor, JSGraph* jsgraph, Flags flags, Editor* editor, JSGraph* jsgraph, Flags flags,
Handle<Context> native_context, CompilationDependencies* dependencies, MaybeHandle<Context> native_context, CompilationDependencies* dependencies,
Zone* zone) Zone* zone)
: AdvancedReducer(editor), : AdvancedReducer(editor),
jsgraph_(jsgraph), jsgraph_(jsgraph),
...@@ -32,8 +33,7 @@ JSNativeContextSpecialization::JSNativeContextSpecialization( ...@@ -32,8 +33,7 @@ JSNativeContextSpecialization::JSNativeContextSpecialization(
native_context_(native_context), native_context_(native_context),
dependencies_(dependencies), dependencies_(dependencies),
zone_(zone), zone_(zone),
type_cache_(TypeCache::Get()), type_cache_(TypeCache::Get()) {}
access_info_factory_(dependencies, native_context, graph()->zone()) {}
Reduction JSNativeContextSpecialization::Reduce(Node* node) { Reduction JSNativeContextSpecialization::Reduce(Node* node) {
...@@ -69,9 +69,15 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess( ...@@ -69,9 +69,15 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
// Not much we can do if deoptimization support is disabled. // Not much we can do if deoptimization support is disabled.
if (!(flags() & kDeoptimizationEnabled)) return NoChange(); if (!(flags() & kDeoptimizationEnabled)) return NoChange();
// Retrieve the native context from the given {node}.
Handle<Context> native_context;
if (!GetNativeContext(node).ToHandle(&native_context)) return NoChange();
// Compute property access infos for the receiver maps. // Compute property access infos for the receiver maps.
AccessInfoFactory access_info_factory(dependencies(), native_context,
graph()->zone());
ZoneVector<PropertyAccessInfo> access_infos(zone()); ZoneVector<PropertyAccessInfo> access_infos(zone());
if (!access_info_factory().ComputePropertyAccessInfos( if (!access_info_factory.ComputePropertyAccessInfos(
receiver_maps, name, access_mode, &access_infos)) { receiver_maps, name, access_mode, &access_infos)) {
return NoChange(); return NoChange();
} }
...@@ -183,7 +189,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess( ...@@ -183,7 +189,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
// Determine actual holder and perform prototype chain checks. // Determine actual holder and perform prototype chain checks.
Handle<JSObject> holder; Handle<JSObject> holder;
if (access_info.holder().ToHandle(&holder)) { if (access_info.holder().ToHandle(&holder)) {
AssumePrototypesStable(receiver_type, holder); AssumePrototypesStable(receiver_type, native_context, holder);
} }
// Generate the actual property access. // Generate the actual property access.
...@@ -487,10 +493,16 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( ...@@ -487,10 +493,16 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
// TODO(bmeurer): Add support for non-standard stores. // TODO(bmeurer): Add support for non-standard stores.
if (store_mode != STANDARD_STORE) return NoChange(); if (store_mode != STANDARD_STORE) return NoChange();
// Retrieve the native context from the given {node}.
Handle<Context> native_context;
if (!GetNativeContext(node).ToHandle(&native_context)) return NoChange();
// Compute element access infos for the receiver maps. // Compute element access infos for the receiver maps.
AccessInfoFactory access_info_factory(dependencies(), native_context,
graph()->zone());
ZoneVector<ElementAccessInfo> access_infos(zone()); ZoneVector<ElementAccessInfo> access_infos(zone());
if (!access_info_factory().ComputeElementAccessInfos( if (!access_info_factory.ComputeElementAccessInfos(receiver_maps, access_mode,
receiver_maps, access_mode, &access_infos)) { &access_infos)) {
return NoChange(); return NoChange();
} }
...@@ -613,7 +625,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( ...@@ -613,7 +625,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
// not compatible with (monomorphic) keyed stores. // not compatible with (monomorphic) keyed stores.
Handle<JSObject> holder; Handle<JSObject> holder;
if (access_info.holder().ToHandle(&holder)) { if (access_info.holder().ToHandle(&holder)) {
AssumePrototypesStable(receiver_type, holder); AssumePrototypesStable(receiver_type, native_context, holder);
} }
// Check that the {index} is actually a Number. // Check that the {index} is actually a Number.
...@@ -667,24 +679,15 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( ...@@ -667,24 +679,15 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
} }
// Load the length of the {receiver}. // Load the length of the {receiver}.
Node* this_length; Node* this_length = this_effect =
if (receiver_is_jsarray) { receiver_is_jsarray
FieldAccess length_access = { ? graph()->NewNode(
kTaggedBase, JSArray::kLengthOffset, factory()->name_string(), simplified()->LoadField(
type_cache_.kJSArrayLengthType, kMachAnyTagged}; AccessBuilder::ForJSArrayLength(elements_kind)),
if (IsFastDoubleElementsKind(elements_kind)) { this_receiver, this_effect, this_control)
length_access.type = type_cache_.kFixedDoubleArrayLengthType; : graph()->NewNode(
} else if (IsFastElementsKind(elements_kind)) { simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
length_access.type = type_cache_.kFixedArrayLengthType; this_elements, this_effect, this_control);
}
this_length = this_effect =
graph()->NewNode(simplified()->LoadField(length_access),
this_receiver, this_effect, this_control);
} else {
this_length = this_effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForFixedArrayLength()),
this_elements, this_effect, this_control);
}
// Check that the {index} is in the valid range for the {receiver}. // Check that the {index} is in the valid range for the {receiver}.
Node* check = graph()->NewNode(simplified()->NumberLessThan(), this_index, Node* check = graph()->NewNode(simplified()->NumberLessThan(), this_index,
...@@ -742,7 +745,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( ...@@ -742,7 +745,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
if (receiver_type->NowIs(initial_holey_array_type) && if (receiver_type->NowIs(initial_holey_array_type) &&
isolate()->IsFastArrayConstructorPrototypeChainIntact()) { isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
// Add a code dependency on the array protector cell. // Add a code dependency on the array protector cell.
AssumePrototypesStable(receiver_type, AssumePrototypesStable(receiver_type, native_context,
isolate()->initial_object_prototype()); isolate()->initial_object_prototype());
dependencies()->AssumePropertyCell(factory()->array_protector()); dependencies()->AssumePropertyCell(factory()->array_protector());
// Turn the hole into undefined. // Turn the hole into undefined.
...@@ -773,7 +776,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( ...@@ -773,7 +776,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
if (receiver_type->NowIs(initial_holey_array_type) && if (receiver_type->NowIs(initial_holey_array_type) &&
isolate()->IsFastArrayConstructorPrototypeChainIntact()) { isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
// Add a code dependency on the array protector cell. // Add a code dependency on the array protector cell.
AssumePrototypesStable(receiver_type, AssumePrototypesStable(receiver_type, native_context,
isolate()->initial_object_prototype()); isolate()->initial_object_prototype());
dependencies()->AssumePropertyCell(factory()->array_protector()); dependencies()->AssumePropertyCell(factory()->array_protector());
// Turn the hole into undefined. // Turn the hole into undefined.
...@@ -945,27 +948,19 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) { ...@@ -945,27 +948,19 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) {
void JSNativeContextSpecialization::AssumePrototypesStable( void JSNativeContextSpecialization::AssumePrototypesStable(
Type* receiver_type, Handle<JSObject> holder) { Type* receiver_type, Handle<Context> native_context,
Handle<JSObject> holder) {
// Determine actual holder and perform prototype chain checks. // Determine actual holder and perform prototype chain checks.
for (auto i = receiver_type->Classes(); !i.Done(); i.Advance()) { for (auto i = receiver_type->Classes(); !i.Done(); i.Advance()) {
Handle<Map> map = i.Current(); Handle<Map> map = i.Current();
// Perform the implicit ToObject for primitives here. // Perform the implicit ToObject for primitives here.
// Implemented according to ES6 section 7.3.2 GetV (V, P). // Implemented according to ES6 section 7.3.2 GetV (V, P).
Handle<JSFunction> constructor; Handle<JSFunction> constructor;
if (Map::GetConstructorFunction(map, native_context()) if (Map::GetConstructorFunction(map, native_context)
.ToHandle(&constructor)) { .ToHandle(&constructor)) {
map = handle(constructor->initial_map(), isolate()); map = handle(constructor->initial_map(), isolate());
} }
for (PrototypeIterator j(map); !j.IsAtEnd(); j.Advance()) { dependencies()->AssumePrototypeMapsStable(map, holder);
// Check that the {prototype} still has the same map. All prototype
// maps are guaranteed to be stable, so it's sufficient to add a
// stability dependency here.
Handle<JSReceiver> const prototype =
PrototypeIterator::GetCurrent<JSReceiver>(j);
dependencies()->AssumeMapStable(handle(prototype->map(), isolate()));
// Stop once we get to the holder.
if (prototype.is_identical_to(holder)) break;
}
} }
} }
...@@ -982,6 +977,14 @@ void JSNativeContextSpecialization::MarkAsDeferred(Node* if_projection) { ...@@ -982,6 +977,14 @@ void JSNativeContextSpecialization::MarkAsDeferred(Node* if_projection) {
} }
MaybeHandle<Context> JSNativeContextSpecialization::GetNativeContext(
Node* node) {
Node* const context = NodeProperties::GetContextInput(node);
return NodeProperties::GetSpecializationNativeContext(context,
native_context());
}
Graph* JSNativeContextSpecialization::graph() const { Graph* JSNativeContextSpecialization::graph() const {
return jsgraph()->graph(); return jsgraph()->graph();
} }
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#define V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_ #define V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_
#include "src/base/flags.h" #include "src/base/flags.h"
#include "src/compiler/access-info.h"
#include "src/compiler/graph-reducer.h" #include "src/compiler/graph-reducer.h"
namespace v8 { namespace v8 {
...@@ -22,6 +21,7 @@ class TypeCache; ...@@ -22,6 +21,7 @@ class TypeCache;
namespace compiler { namespace compiler {
// Forward declarations. // Forward declarations.
enum class AccessMode;
class CommonOperatorBuilder; class CommonOperatorBuilder;
class JSGraph; class JSGraph;
class JSOperatorBuilder; class JSOperatorBuilder;
...@@ -43,7 +43,7 @@ class JSNativeContextSpecialization final : public AdvancedReducer { ...@@ -43,7 +43,7 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
typedef base::Flags<Flag> Flags; typedef base::Flags<Flag> Flags;
JSNativeContextSpecialization(Editor* editor, JSGraph* jsgraph, Flags flags, JSNativeContextSpecialization(Editor* editor, JSGraph* jsgraph, Flags flags,
Handle<Context> native_context, MaybeHandle<Context> native_context,
CompilationDependencies* dependencies, CompilationDependencies* dependencies,
Zone* zone); Zone* zone);
...@@ -73,12 +73,17 @@ class JSNativeContextSpecialization final : public AdvancedReducer { ...@@ -73,12 +73,17 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
// Adds stability dependencies on all prototypes of every class in // Adds stability dependencies on all prototypes of every class in
// {receiver_type} up to (and including) the {holder}. // {receiver_type} up to (and including) the {holder}.
void AssumePrototypesStable(Type* receiver_type, Handle<JSObject> holder); void AssumePrototypesStable(Type* receiver_type,
Handle<Context> native_context,
Handle<JSObject> holder);
// Assuming that {if_projection} is either IfTrue or IfFalse, adds a hint on // Assuming that {if_projection} is either IfTrue or IfFalse, adds a hint on
// the dominating Branch that {if_projection} is the unlikely (deferred) case. // the dominating Branch that {if_projection} is the unlikely (deferred) case.
void MarkAsDeferred(Node* if_projection); void MarkAsDeferred(Node* if_projection);
// Retrieve the native context from the given {node} if known.
MaybeHandle<Context> GetNativeContext(Node* node);
Graph* graph() const; Graph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; } JSGraph* jsgraph() const { return jsgraph_; }
Isolate* isolate() const; Isolate* isolate() const;
...@@ -88,18 +93,16 @@ class JSNativeContextSpecialization final : public AdvancedReducer { ...@@ -88,18 +93,16 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
SimplifiedOperatorBuilder* simplified() const; SimplifiedOperatorBuilder* simplified() const;
MachineOperatorBuilder* machine() const; MachineOperatorBuilder* machine() const;
Flags flags() const { return flags_; } Flags flags() const { return flags_; }
Handle<Context> native_context() const { return native_context_; } MaybeHandle<Context> native_context() const { return native_context_; }
CompilationDependencies* dependencies() const { return dependencies_; } CompilationDependencies* dependencies() const { return dependencies_; }
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
AccessInfoFactory& access_info_factory() { return access_info_factory_; }
JSGraph* const jsgraph_; JSGraph* const jsgraph_;
Flags const flags_; Flags const flags_;
Handle<Context> native_context_; MaybeHandle<Context> native_context_;
CompilationDependencies* const dependencies_; CompilationDependencies* const dependencies_;
Zone* const zone_; Zone* const zone_;
TypeCache const& type_cache_; TypeCache const& type_cache_;
AccessInfoFactory access_info_factory_;
DISALLOW_COPY_AND_ASSIGN(JSNativeContextSpecialization); DISALLOW_COPY_AND_ASSIGN(JSNativeContextSpecialization);
}; };
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "src/compiler/common-operator.h" #include "src/compiler/common-operator.h"
#include "src/compiler/graph.h" #include "src/compiler/graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/node-properties.h" #include "src/compiler/node-properties.h"
#include "src/compiler/operator-properties.h" #include "src/compiler/operator-properties.h"
#include "src/compiler/verifier.h" #include "src/compiler/verifier.h"
...@@ -292,6 +293,90 @@ void NodeProperties::CollectControlProjections(Node* node, Node** projections, ...@@ -292,6 +293,90 @@ void NodeProperties::CollectControlProjections(Node* node, Node** projections,
} }
// static
MaybeHandle<Context> NodeProperties::GetSpecializationContext(
Node* node, MaybeHandle<Context> context) {
switch (node->opcode()) {
case IrOpcode::kHeapConstant:
return Handle<Context>::cast(OpParameter<Handle<HeapObject>>(node));
case IrOpcode::kParameter: {
Node* const start = NodeProperties::GetValueInput(node, 0);
DCHECK_EQ(IrOpcode::kStart, start->opcode());
int const index = ParameterIndexOf(node->op());
// The context is always the last parameter to a JavaScript function, and
// {Parameter} indices start at -1, so value outputs of {Start} look like
// this: closure, receiver, param0, ..., paramN, context.
if (index == start->op()->ValueOutputCount() - 2) {
return context;
}
break;
}
default:
break;
}
return MaybeHandle<Context>();
}
// static
MaybeHandle<Context> NodeProperties::GetSpecializationNativeContext(
Node* node, MaybeHandle<Context> native_context) {
while (true) {
switch (node->opcode()) {
case IrOpcode::kJSCreateBlockContext:
case IrOpcode::kJSCreateCatchContext:
case IrOpcode::kJSCreateFunctionContext:
case IrOpcode::kJSCreateModuleContext:
case IrOpcode::kJSCreateScriptContext:
case IrOpcode::kJSCreateWithContext: {
// Skip over the intermediate contexts, we're only interested in the
// very last context in the context chain anyway.
node = NodeProperties::GetContextInput(node);
break;
}
case IrOpcode::kHeapConstant: {
// Extract the native context from the actual {context}.
Handle<Context> context =
Handle<Context>::cast(OpParameter<Handle<HeapObject>>(node));
return handle(context->native_context());
}
case IrOpcode::kOsrValue: {
int const index = OpParameter<int>(node);
if (index == Linkage::kOsrContextSpillSlotIndex) {
return native_context;
}
return MaybeHandle<Context>();
}
case IrOpcode::kParameter: {
Node* const start = NodeProperties::GetValueInput(node, 0);
DCHECK_EQ(IrOpcode::kStart, start->opcode());
int const index = ParameterIndexOf(node->op());
// The context is always the last parameter to a JavaScript function,
// and {Parameter} indices start at -1, so value outputs of {Start}
// look like this: closure, receiver, param0, ..., paramN, context.
if (index == start->op()->ValueOutputCount() - 2) {
return native_context;
}
return MaybeHandle<Context>();
}
default:
return MaybeHandle<Context>();
}
}
}
// static
MaybeHandle<JSGlobalObject> NodeProperties::GetSpecializationGlobalObject(
Node* node, MaybeHandle<Context> native_context) {
Handle<Context> context;
if (GetSpecializationNativeContext(node, native_context).ToHandle(&context)) {
return handle(context->global_object());
}
return MaybeHandle<JSGlobalObject>();
}
// static // static
Type* NodeProperties::GetTypeOrAny(Node* node) { Type* NodeProperties::GetTypeOrAny(Node* node) {
return IsTyped(node) ? node->type() : Type::Any(); return IsTyped(node) ? node->type() : Type::Any();
......
...@@ -115,6 +115,27 @@ class NodeProperties final { ...@@ -115,6 +115,27 @@ class NodeProperties final {
// - Switch: [ IfValue, ..., IfDefault ] // - Switch: [ IfValue, ..., IfDefault ]
static void CollectControlProjections(Node* node, Node** proj, size_t count); static void CollectControlProjections(Node* node, Node** proj, size_t count);
// ---------------------------------------------------------------------------
// Context.
// Try to retrieve the specialization context from the given {node},
// optionally utilizing the knowledge about the (outermost) function
// {context}.
static MaybeHandle<Context> GetSpecializationContext(
Node* node, MaybeHandle<Context> context = MaybeHandle<Context>());
// Try to retrieve the specialization native context from the given
// {node}, optionally utilizing the knowledge about the (outermost)
// {native_context}.
static MaybeHandle<Context> GetSpecializationNativeContext(
Node* node, MaybeHandle<Context> native_context = MaybeHandle<Context>());
// Try to retrieve the specialization global object from the given
// {node}, optionally utilizing the knowledge about the (outermost)
// {native_context}.
static MaybeHandle<JSGlobalObject> GetSpecializationGlobalObject(
Node* node, MaybeHandle<Context> native_context = MaybeHandle<Context>());
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Type. // Type.
......
...@@ -496,39 +496,6 @@ struct GraphBuilderPhase { ...@@ -496,39 +496,6 @@ struct GraphBuilderPhase {
}; };
struct NativeContextSpecializationPhase {
static const char* phase_name() { return "native context specialization"; }
void Run(PipelineData* data, Zone* temp_zone) {
JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
data->common());
CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
data->common(), data->machine());
JSGlobalObjectSpecialization global_object_specialization(
&graph_reducer, data->jsgraph(),
data->info()->is_deoptimization_enabled()
? JSGlobalObjectSpecialization::kDeoptimizationEnabled
: JSGlobalObjectSpecialization::kNoFlags,
handle(data->info()->global_object(), data->isolate()),
data->info()->dependencies());
JSNativeContextSpecialization native_context_specialization(
&graph_reducer, data->jsgraph(),
data->info()->is_deoptimization_enabled()
? JSNativeContextSpecialization::kDeoptimizationEnabled
: JSNativeContextSpecialization::kNoFlags,
handle(data->info()->global_object()->native_context(),
data->isolate()),
data->info()->dependencies(), temp_zone);
AddReducer(data, &graph_reducer, &dead_code_elimination);
AddReducer(data, &graph_reducer, &common_reducer);
AddReducer(data, &graph_reducer, &global_object_specialization);
AddReducer(data, &graph_reducer, &native_context_specialization);
graph_reducer.ReduceGraph();
}
};
struct InliningPhase { struct InliningPhase {
static const char* phase_name() { return "inlining"; } static const char* phase_name() { return "inlining"; }
...@@ -549,6 +516,24 @@ struct InliningPhase { ...@@ -549,6 +516,24 @@ struct InliningPhase {
: MaybeHandle<Context>()); : MaybeHandle<Context>());
JSFrameSpecialization frame_specialization(data->info()->osr_frame(), JSFrameSpecialization frame_specialization(data->info()->osr_frame(),
data->jsgraph()); data->jsgraph());
JSGlobalObjectSpecialization global_object_specialization(
&graph_reducer, data->jsgraph(),
data->info()->is_deoptimization_enabled()
? JSGlobalObjectSpecialization::kDeoptimizationEnabled
: JSGlobalObjectSpecialization::kNoFlags,
data->info()->is_native_context_specializing()
? handle(data->info()->native_context(), data->isolate())
: MaybeHandle<Context>(),
data->info()->dependencies());
JSNativeContextSpecialization native_context_specialization(
&graph_reducer, data->jsgraph(),
data->info()->is_deoptimization_enabled()
? JSNativeContextSpecialization::kDeoptimizationEnabled
: JSNativeContextSpecialization::kNoFlags,
data->info()->is_native_context_specializing()
? handle(data->info()->native_context(), data->isolate())
: MaybeHandle<Context>(),
data->info()->dependencies(), temp_zone);
JSInliningHeuristic inlining(&graph_reducer, JSInliningHeuristic inlining(&graph_reducer,
data->info()->is_inlining_enabled() data->info()->is_inlining_enabled()
? JSInliningHeuristic::kGeneralInlining ? JSInliningHeuristic::kGeneralInlining
...@@ -559,6 +544,8 @@ struct InliningPhase { ...@@ -559,6 +544,8 @@ struct InliningPhase {
if (data->info()->is_frame_specializing()) { if (data->info()->is_frame_specializing()) {
AddReducer(data, &graph_reducer, &frame_specialization); AddReducer(data, &graph_reducer, &frame_specialization);
} }
AddReducer(data, &graph_reducer, &global_object_specialization);
AddReducer(data, &graph_reducer, &native_context_specialization);
AddReducer(data, &graph_reducer, &context_specialization); AddReducer(data, &graph_reducer, &context_specialization);
AddReducer(data, &graph_reducer, &call_reducer); AddReducer(data, &graph_reducer, &call_reducer);
AddReducer(data, &graph_reducer, &inlining); AddReducer(data, &graph_reducer, &inlining);
...@@ -1100,12 +1087,6 @@ Handle<Code> Pipeline::GenerateCode() { ...@@ -1100,12 +1087,6 @@ Handle<Code> Pipeline::GenerateCode() {
RunPrintAndVerify("OSR deconstruction", true); RunPrintAndVerify("OSR deconstruction", true);
} }
// Perform native context specialization (if enabled).
if (info()->is_native_context_specializing()) {
Run<NativeContextSpecializationPhase>();
RunPrintAndVerify("Native context specialized", true);
}
// Perform function context specialization and inlining (if enabled). // Perform function context specialization and inlining (if enabled).
Run<InliningPhase>(); Run<InliningPhase>();
RunPrintAndVerify("Inlined", true); RunPrintAndVerify("Inlined", true);
......
...@@ -171,8 +171,6 @@ V8_INLINE Handle<T> handle(T* object) { ...@@ -171,8 +171,6 @@ V8_INLINE Handle<T> handle(T* object) {
// into a Handle requires checking that it does not point to NULL. This // into a Handle requires checking that it does not point to NULL. This
// ensures NULL checks before use. // ensures NULL checks before use.
// //
// Do not use MaybeHandle as argument type.
//
// Also note that Handles do not provide default equality comparison or hashing // Also note that Handles do not provide default equality comparison or hashing
// operators on purpose. Such operators would be misleading, because intended // operators on purpose. Such operators would be misleading, because intended
// semantics is ambiguous between Handle location and object identity. // semantics is ambiguous between Handle location and object identity.
......
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