Revert of [turbofan] Add initial support for global specialization. (patchset #4 id:60001 of https://codereview.chromium.org/1387393002/ )

Reason for revert:
Breaks GC stress: http://build.chromium.org/p/client.v8/builders/V8%20Linux64%20GC%20Stress%20-%20custom%20snapshot/builds/1984/steps/Bisect%20c5528ac1.Retry/logs/regress-crbug-450960

Original issue's description:
> [turbofan] Add initial support for global specialization.
>
> Introduce a new JSGlobalSpecialization advanced reducer that runs
> during the initial inlining and context specialization, and specializes
> the graph to the globals of the native context.  Currently we assume
> that we do not inline cross native context, but long-term we will grab
> the global object from the JSLoadGlobal/JSStoreGlobal feedback (with the
> new global load/store ICs that are currently in the workings), and then
> this whole specialization will be fully compositional even across
> cross-context inlining.
>
> Note that we cannot really handle most of the stores to global object
> property cells because TurboFan doesn't have a mechanism to enforce
> certain representations.  Also note that we cannot yet fully benefit
> from the type feedback collected on the global object property cells,
> because the type system cannot deal with maps in a reasonable way.
>
> CQ_INCLUDE_TRYBOTS=tryserver.v8:v8_linux_nosnap_rel
> R=jarin@chromium.org
> BUG=v8:4470
> LOG=n
>
> Committed: https://crrev.com/6fbf7903f94924ea066af481719898bd9667b6eb
> Cr-Commit-Position: refs/heads/master@{#31139}

TBR=jarin@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:4470

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

Cr-Commit-Position: refs/heads/master@{#31144}
This commit is contained in:
bmeurer 2015-10-07 04:42:12 -07:00 committed by Commit bot
parent 1d7c9c8139
commit 84065c5f1e
15 changed files with 15 additions and 388 deletions

View File

@ -755,8 +755,6 @@ source_set("v8_base") {
"src/compiler/js-frame-specialization.h",
"src/compiler/js-generic-lowering.cc",
"src/compiler/js-generic-lowering.h",
"src/compiler/js-global-specialization.cc",
"src/compiler/js-global-specialization.h",
"src/compiler/js-graph.cc",
"src/compiler/js-graph.h",
"src/compiler/js-inlining.cc",

View File

@ -447,9 +447,6 @@ OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() {
FLAG_turbo_asm_deoptimization) {
info()->MarkAsDeoptimizationEnabled();
}
if (info()->has_global_object() && FLAG_native_context_specialization) {
info()->MarkAsNativeContextSpecializing();
}
Timer t(this, &time_taken_to_create_graph_);
compiler::Pipeline pipeline(info());
@ -781,8 +778,7 @@ static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
Handle<Code> code = info->code();
if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
// Function context specialization folds-in the function context,
// so no sharing can occur.
// Context specialization folds-in the context, so no sharing can occur.
if (info->is_function_context_specializing()) return;
// Frame specialization implies function context specialization.
DCHECK(!info->is_frame_specializing());
@ -800,12 +796,11 @@ static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
literals, info->osr_ast_id());
}
// Do not cache (native) context-independent code compiled for OSR.
// Do not cache context-independent code compiled for OSR.
if (code->is_turbofanned() && info->is_osr()) return;
// Cache optimized (native) context-independent code.
if (FLAG_turbo_cache_shared_code && code->is_turbofanned() &&
!info->is_native_context_specializing()) {
// Cache optimized context-independent code.
if (FLAG_turbo_cache_shared_code && code->is_turbofanned()) {
DCHECK(!info->is_function_context_specializing());
DCHECK(info->osr_ast_id().IsNone());
Handle<SharedFunctionInfo> shared(function->shared());

View File

@ -117,15 +117,14 @@ class CompilationInfo {
kSerializing = 1 << 7,
kFunctionContextSpecializing = 1 << 8,
kFrameSpecializing = 1 << 9,
kNativeContextSpecializing = 1 << 10,
kInliningEnabled = 1 << 11,
kTypingEnabled = 1 << 12,
kDisableFutureOptimization = 1 << 13,
kSplittingEnabled = 1 << 14,
kTypeFeedbackEnabled = 1 << 15,
kDeoptimizationEnabled = 1 << 16,
kSourcePositionsEnabled = 1 << 17,
kFirstCompile = 1 << 18,
kInliningEnabled = 1 << 10,
kTypingEnabled = 1 << 11,
kDisableFutureOptimization = 1 << 12,
kSplittingEnabled = 1 << 13,
kTypeFeedbackEnabled = 1 << 14,
kDeoptimizationEnabled = 1 << 15,
kSourcePositionsEnabled = 1 << 16,
kFirstCompile = 1 << 17,
};
explicit CompilationInfo(ParseInfo* parse_info);
@ -231,14 +230,6 @@ class CompilationInfo {
bool is_frame_specializing() const { return GetFlag(kFrameSpecializing); }
void MarkAsNativeContextSpecializing() {
SetFlag(kNativeContextSpecializing);
}
bool is_native_context_specializing() const {
return GetFlag(kNativeContextSpecializing);
}
void MarkAsTypeFeedbackEnabled() { SetFlag(kTypeFeedbackEnabled); }
bool is_type_feedback_enabled() const {

View File

@ -151,14 +151,8 @@ FieldAccess AccessBuilder::ForContextSlot(size_t index) {
// static
FieldAccess AccessBuilder::ForPropertyCellValue() {
return ForPropertyCellValue(Type::Tagged());
}
// static
FieldAccess AccessBuilder::ForPropertyCellValue(Type* type) {
FieldAccess access = {kTaggedBase, PropertyCell::kValueOffset, Handle<Name>(),
type, kMachAnyTagged};
Type::Any(), kMachAnyTagged};
return access;
}

View File

@ -69,7 +69,6 @@ class AccessBuilder final : public AllStatic {
// Provides access to PropertyCell::value() field.
static FieldAccess ForPropertyCellValue();
static FieldAccess ForPropertyCellValue(Type* type);
// Provides access to SharedFunctionInfo::feedback_vector() field.
static FieldAccess ForSharedFunctionInfoTypeFeedbackVector();

View File

@ -193,7 +193,7 @@ Handle<Code> CodeGenerator::GenerateCode() {
PopulateDeoptimizationData(result);
// Ensure there is space for lazy deoptimization in the relocation info.
if (info->ShouldEnsureSpaceForLazyDeopt()) {
if (!info->ShouldEnsureSpaceForLazyDeopt()) {
Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(result);
}

View File

@ -95,9 +95,6 @@ Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) {
// Success. The context load can be replaced with the constant.
// TODO(titzer): record the specialization for sharing code across multiple
// contexts that have the same value in the corresponding context slot.
if (value->IsConsString()) {
value = String::Flatten(Handle<String>::cast(value), TENURED);
}
Node* constant = jsgraph_->Constant(value);
ReplaceWithValue(node, constant);
return Replace(constant);

View File

@ -1,240 +0,0 @@
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/js-global-specialization.h"
#include "src/compilation-dependencies.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
#include "src/contexts.h"
#include "src/lookup.h"
#include "src/objects-inl.h"
namespace v8 {
namespace internal {
namespace compiler {
JSGlobalSpecialization::JSGlobalSpecialization(
Editor* editor, JSGraph* jsgraph, Flags flags,
Handle<GlobalObject> global_object, CompilationDependencies* dependencies)
: AdvancedReducer(editor),
jsgraph_(jsgraph),
flags_(flags),
global_object_(global_object),
dependencies_(dependencies),
simplified_(graph()->zone()) {}
Reduction JSGlobalSpecialization::Reduce(Node* node) {
switch (node->opcode()) {
case IrOpcode::kJSLoadGlobal:
return ReduceJSLoadGlobal(node);
case IrOpcode::kJSStoreGlobal:
return ReduceJSStoreGlobal(node);
default:
break;
}
return NoChange();
}
Reduction JSGlobalSpecialization::ReduceJSLoadGlobal(Node* node) {
DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode());
Handle<Name> name = LoadGlobalParametersOf(node->op()).name();
Node* effect = NodeProperties::GetEffectInput(node);
// Try to lookup the name on the script context table first (lexical scoping).
if (name->IsString()) {
Handle<ScriptContextTable> script_context_table(
global_object()->native_context()->script_context_table());
ScriptContextTable::LookupResult result;
if (ScriptContextTable::Lookup(script_context_table,
Handle<String>::cast(name), &result)) {
Handle<Context> script_context = ScriptContextTable::GetContext(
script_context_table, result.context_index);
if (script_context->is_the_hole(result.slot_index)) {
// TODO(bmeurer): Is this relevant in practice?
return NoChange();
}
Node* context = jsgraph()->Constant(script_context);
Node* value = effect = graph()->NewNode(
javascript()->LoadContext(0, result.slot_index,
IsImmutableVariableMode(result.mode)),
context, context, effect);
return Replace(node, value, effect);
}
}
// Lookup on the global object instead.
LookupIterator it(global_object(), name, LookupIterator::OWN);
if (it.state() == LookupIterator::DATA) {
return ReduceLoadFromPropertyCell(node, it.GetPropertyCell());
}
return NoChange();
}
Reduction JSGlobalSpecialization::ReduceJSStoreGlobal(Node* node) {
DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode());
Handle<Name> name = StoreGlobalParametersOf(node->op()).name();
Node* value = NodeProperties::GetValueInput(node, 2);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// Try to lookup the name on the script context table first (lexical scoping).
if (name->IsString()) {
Handle<ScriptContextTable> script_context_table(
global_object()->native_context()->script_context_table());
ScriptContextTable::LookupResult result;
if (ScriptContextTable::Lookup(script_context_table,
Handle<String>::cast(name), &result)) {
if (IsImmutableVariableMode(result.mode)) return NoChange();
Handle<Context> script_context = ScriptContextTable::GetContext(
script_context_table, result.context_index);
if (script_context->is_the_hole(result.slot_index)) {
// TODO(bmeurer): Is this relevant in practice?
return NoChange();
}
Node* context = jsgraph()->Constant(script_context);
effect =
graph()->NewNode(javascript()->StoreContext(0, result.slot_index),
context, value, context, effect, control);
return Replace(node, value, effect, control);
}
}
// Lookup on the global object instead.
LookupIterator it(global_object(), name, LookupIterator::OWN);
if (it.state() == LookupIterator::DATA) {
return ReduceStoreToPropertyCell(node, it.GetPropertyCell());
}
return NoChange();
}
Reduction JSGlobalSpecialization::ReduceLoadFromPropertyCell(
Node* node, Handle<PropertyCell> property_cell) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// We only specialize global data property access.
PropertyDetails property_details = property_cell->property_details();
DCHECK_EQ(kData, property_details.kind());
Handle<Object> property_cell_value(property_cell->value(), isolate());
DCHECK(!property_cell_value->IsTheHole());
// Load from non-configurable, read-only data property on the global
// object can be constant-folded, even without deoptimization support.
if (!property_details.IsConfigurable() && property_details.IsReadOnly()) {
return Replace(node, property_cell_value);
}
// Load from constant/undefined global property can be constant-folded
// with deoptimization support, by adding a code dependency on the cell.
if ((property_details.cell_type() == PropertyCellType::kConstant ||
property_details.cell_type() == PropertyCellType::kUndefined) &&
(flags() & kDeoptimizationEnabled)) {
dependencies()->AssumePropertyCell(property_cell);
return Replace(node, property_cell_value);
}
// Not much we can do if we run the generic pipeline here.
if (!(flags() & kTypingEnabled)) return NoChange();
// Load from constant type global property can benefit from representation
// (and map) feedback with deoptimization support (requires code dependency).
if (property_details.cell_type() == PropertyCellType::kConstantType &&
(flags() & kDeoptimizationEnabled)) {
dependencies()->AssumePropertyCell(property_cell);
Type* property_cell_value_type = Type::Any();
switch (property_cell->GetConstantType()) {
case PropertyCellConstantType::kSmi:
property_cell_value_type = Type::Intersect(
Type::SignedSmall(), Type::TaggedSigned(), graph()->zone());
break;
case PropertyCellConstantType::kStableMap: {
// TODO(bmeurer): Determine type based on the map's instance type.
property_cell_value_type = Type::TaggedPointer();
break;
}
}
Node* value = effect = graph()->NewNode(
simplified()->LoadField(
AccessBuilder::ForPropertyCellValue(property_cell_value_type)),
jsgraph()->Constant(property_cell), effect, control);
return Replace(node, value, effect);
}
// Load from non-configurable, data property on the global can be lowered to
// a field load, even without deoptimization, because the property cannot be
// deleted or reconfigured to an accessor/interceptor property.
if (property_details.IsConfigurable()) {
// With deoptimization support, we can lower loads even from configurable
// data properties on the global object, by adding a code dependency on
// the cell.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
dependencies()->AssumePropertyCell(property_cell);
}
Node* value = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForPropertyCellValue()),
jsgraph()->Constant(property_cell), effect, control);
return Replace(node, value, effect);
}
Reduction JSGlobalSpecialization::ReduceStoreToPropertyCell(
Node* node, Handle<PropertyCell> property_cell) {
Node* value = NodeProperties::GetValueInput(node, 2);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
// We only specialize global data property access.
PropertyDetails property_details = property_cell->property_details();
DCHECK_EQ(kData, property_details.kind());
Handle<Object> property_cell_value(property_cell->value(), isolate());
DCHECK(!property_cell_value->IsTheHole());
// Don't even bother trying to lower stores to read-only data properties.
if (property_details.IsReadOnly()) return NoChange();
// Not much we can do if we run the generic pipeline here.
if (!(flags() & kTypingEnabled)) return NoChange();
// TODO(bmeurer): For now we deal only with cells in mutable state.
if (property_details.cell_type() != PropertyCellType::kMutable) {
return NoChange();
}
// Store to non-configurable, data property on the global can be lowered to
// a field store, even without deoptimization, because the property cannot be
// deleted or reconfigured to an accessor/interceptor property.
if (property_details.IsConfigurable()) {
// With deoptimization support, we can lower stores even to configurable
// data properties on the global object, by adding a code dependency on
// the cell.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
dependencies()->AssumePropertyCell(property_cell);
}
effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForPropertyCellValue()),
jsgraph()->Constant(property_cell), value, effect, control);
return Replace(node, value, effect, control);
}
Reduction JSGlobalSpecialization::Replace(Node* node, Handle<Object> value) {
if (value->IsConsString()) {
value = String::Flatten(Handle<String>::cast(value), TENURED);
}
return Replace(node, jsgraph()->Constant(value));
}
Graph* JSGlobalSpecialization::graph() const { return jsgraph()->graph(); }
Isolate* JSGlobalSpecialization::isolate() const {
return jsgraph()->isolate();
}
JSOperatorBuilder* JSGlobalSpecialization::javascript() const {
return jsgraph()->javascript();
}
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -1,82 +0,0 @@
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_COMPILER_JS_GLOBAL_SPECIALIZATION_H_
#define V8_COMPILER_JS_GLOBAL_SPECIALIZATION_H_
#include "src/base/flags.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/simplified-operator.h"
namespace v8 {
namespace internal {
// Forward declarations.
class CompilationDependencies;
namespace compiler {
// Forward declarations.
class JSGraph;
class JSOperatorBuilder;
// Specializes a given JSGraph to a given GlobalObject, potentially constant
// folding some {LoadGlobal} nodes or strength reducing some {StoreGlobal}
// nodes.
class JSGlobalSpecialization final : public AdvancedReducer {
public:
// Flags that control the mode of operation.
enum Flag {
kNoFlags = 0u,
kDeoptimizationEnabled = 1u << 0,
kTypingEnabled = 1u << 1
};
typedef base::Flags<Flag> Flags;
JSGlobalSpecialization(Editor* editor, JSGraph* jsgraph, Flags flags,
Handle<GlobalObject> global_object,
CompilationDependencies* dependencies);
Reduction Reduce(Node* node) final;
private:
Reduction ReduceJSLoadGlobal(Node* node);
Reduction ReduceJSStoreGlobal(Node* node);
Reduction ReduceLoadFromPropertyCell(Node* node,
Handle<PropertyCell> property_cell);
Reduction ReduceStoreToPropertyCell(Node* node,
Handle<PropertyCell> property_cell);
Reduction Replace(Node* node, Node* value, Node* effect = nullptr,
Node* control = nullptr) {
ReplaceWithValue(node, value, effect, control);
return Changed(value);
}
Reduction Replace(Node* node, Handle<Object> value);
Graph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; }
Isolate* isolate() const;
JSOperatorBuilder* javascript() const;
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
Flags flags() const { return flags_; }
Handle<GlobalObject> global_object() const { return global_object_; }
CompilationDependencies* dependencies() const { return dependencies_; }
JSGraph* const jsgraph_;
Flags const flags_;
Handle<GlobalObject> global_object_;
CompilationDependencies* const dependencies_;
SimplifiedOperatorBuilder simplified_;
DISALLOW_COPY_AND_ASSIGN(JSGlobalSpecialization);
};
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_JS_GLOBAL_SPECIALIZATION_H_

View File

@ -1401,7 +1401,7 @@ Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) {
function, effect, control);
NodeProperties::ReplaceContextInput(node, context);
CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
if (p.AllowTailCalls()) {
if (is_strict(p.language_mode())) {
flags |= CallDescriptor::kSupportsTailCalls;
}
NodeProperties::ChangeOp(node,

View File

@ -30,7 +30,6 @@
#include "src/compiler/js-context-specialization.h"
#include "src/compiler/js-frame-specialization.h"
#include "src/compiler/js-generic-lowering.h"
#include "src/compiler/js-global-specialization.h"
#include "src/compiler/js-inlining.h"
#include "src/compiler/js-intrinsic-lowering.h"
#include "src/compiler/js-type-feedback.h"
@ -512,20 +511,6 @@ struct InliningPhase {
: MaybeHandle<Context>());
JSFrameSpecialization frame_specialization(data->info()->osr_frame(),
data->jsgraph());
JSGlobalSpecialization::Flags global_flags =
JSGlobalSpecialization::kNoFlags;
if (data->info()->is_deoptimization_enabled()) {
global_flags |= JSGlobalSpecialization::kDeoptimizationEnabled;
}
if (data->info()->is_typing_enabled()) {
global_flags |= JSGlobalSpecialization::kTypingEnabled;
}
JSGlobalSpecialization global_specialization(
&graph_reducer, data->jsgraph(), global_flags,
data->info()->has_global_object()
? handle(data->info()->global_object())
: Handle<GlobalObject>(),
data->info()->dependencies());
JSInliner inliner(&graph_reducer, data->info()->is_inlining_enabled()
? JSInliner::kGeneralInlining
: JSInliner::kRestrictedInlining,
@ -535,9 +520,6 @@ struct InliningPhase {
if (data->info()->is_frame_specializing()) {
AddReducer(data, &graph_reducer, &frame_specialization);
}
if (data->info()->is_native_context_specializing()) {
AddReducer(data, &graph_reducer, &global_specialization);
}
AddReducer(data, &graph_reducer, &context_specialization);
AddReducer(data, &graph_reducer, &inliner);
graph_reducer.ReduceGraph();

View File

@ -432,8 +432,6 @@ DEFINE_BOOL(turbo_source_positions, false,
DEFINE_IMPLICATION(trace_turbo, turbo_source_positions)
DEFINE_BOOL(function_context_specialization, false,
"enable function context specialization in TurboFan")
DEFINE_BOOL(native_context_specialization, true,
"enable native context specialization in TurboFan")
DEFINE_BOOL(turbo_inlining, false, "enable inlining in TurboFan")
DEFINE_BOOL(trace_turbo_inlining, false, "trace TurboFan inlining")
DEFINE_BOOL(loop_assignment_analysis, true, "perform loop assignment analysis")

View File

@ -400,7 +400,6 @@ TEST(OptimizedCodeSharing2) {
if (FLAG_stress_compaction) return;
FLAG_allow_natives_syntax = true;
FLAG_cache_optimized_code = true;
FLAG_native_context_specialization = false;
FLAG_turbo_cache_shared_code = true;
const char* flag = "--turbo-filter=*";
FlagList::SetFlagsFromString(flag, StrLength(flag));
@ -456,7 +455,6 @@ TEST(OptimizedCodeSharing3) {
if (FLAG_stress_compaction) return;
FLAG_allow_natives_syntax = true;
FLAG_cache_optimized_code = true;
FLAG_native_context_specialization = false;
FLAG_turbo_cache_shared_code = true;
const char* flag = "--turbo-filter=*";
FlagList::SetFlagsFromString(flag, StrLength(flag));

View File

@ -3,7 +3,6 @@
// found in the LICENSE file.
// Flags: --allow-natives-syntax --nostress-opt --turbo
// Flags: --nonative-context-specialization
var p0 = new Object();
var p1 = new Object();

View File

@ -520,8 +520,6 @@
'../../src/compiler/js-frame-specialization.h',
'../../src/compiler/js-generic-lowering.cc',
'../../src/compiler/js-generic-lowering.h',
'../../src/compiler/js-global-specialization.cc',
'../../src/compiler/js-global-specialization.h',
'../../src/compiler/js-graph.cc',
'../../src/compiler/js-graph.h',
'../../src/compiler/js-inlining.cc',