Revert of Refactor compilation dependency handling. (patchset #4 id:60001 of https://codereview.chromium.org/1095433002/)
Reason for revert: [Sheriff] Causes crashes in laout tests: http://build.chromium.org/p/client.v8/builders/V8-Blink%20Linux%2064%20%28dbg%29/builds/2543 Extra bisect run: http://build.chromium.org/p/client.v8/builders/V8-Blink%20Linux%2064%20%28dbg%29/builds/2548 Original issue's description: > Refactor compilation dependency handling. > > Extract a new data structure CompilationDependencies and move (most) logic there. > > R=mstarzinger@chromium.org,verwaest@chromium.org > BUG= > > Committed: https://crrev.com/b882479f1c84a48961b8aec81fa1bb1225034784 > Cr-Commit-Position: refs/heads/master@{#27892} TBR=mstarzinger@chromium.org,verwaest@chromium.org,titzer@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG= Review URL: https://codereview.chromium.org/1093783002 Cr-Commit-Position: refs/heads/master@{#27904}
This commit is contained in:
parent
2af87b3e7a
commit
e3c2ba776a
2
BUILD.gn
2
BUILD.gn
@ -538,8 +538,6 @@ source_set("v8_base") {
|
||||
"src/codegen.h",
|
||||
"src/compilation-cache.cc",
|
||||
"src/compilation-cache.h",
|
||||
"src/compilation-dependencies.cc",
|
||||
"src/compilation-dependencies.h",
|
||||
"src/compilation-statistics.cc",
|
||||
"src/compilation-statistics.h",
|
||||
"src/compiler/access-builder.cc",
|
||||
|
@ -1,121 +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/factory.h"
|
||||
#include "src/handles-inl.h"
|
||||
#include "src/isolate.h"
|
||||
#include "src/objects-inl.h"
|
||||
#include "src/zone.h"
|
||||
|
||||
#include "src/compilation-dependencies.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
DependentCode* CompilationDependencies::Get(Handle<Object> object) {
|
||||
if (object->IsMap()) {
|
||||
return Handle<Map>::cast(object)->dependent_code();
|
||||
} else if (object->IsPropertyCell()) {
|
||||
return Handle<PropertyCell>::cast(object)->dependent_code();
|
||||
} else if (object->IsAllocationSite()) {
|
||||
return Handle<AllocationSite>::cast(object)->dependent_code();
|
||||
}
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void CompilationDependencies::Set(Handle<Object> object,
|
||||
Handle<DependentCode> dep) {
|
||||
if (object->IsMap()) {
|
||||
Handle<Map>::cast(object)->set_dependent_code(*dep);
|
||||
} else if (object->IsPropertyCell()) {
|
||||
Handle<PropertyCell>::cast(object)->set_dependent_code(*dep);
|
||||
} else if (object->IsAllocationSite()) {
|
||||
Handle<AllocationSite>::cast(object)->set_dependent_code(*dep);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CompilationDependencies::Insert(DependentCode::DependencyGroup group,
|
||||
Handle<HeapObject> object) {
|
||||
if (groups_[group] == nullptr) {
|
||||
groups_[group] = new (zone_) ZoneList<Handle<HeapObject>>(2, zone_);
|
||||
}
|
||||
groups_[group]->Add(object, zone_);
|
||||
|
||||
if (object_wrapper_.is_null()) {
|
||||
// Allocate the wrapper if necessary.
|
||||
object_wrapper_ =
|
||||
isolate_->factory()->NewForeign(reinterpret_cast<Address>(this));
|
||||
}
|
||||
|
||||
// Get the old dependent code list.
|
||||
Handle<DependentCode> old_dependent_code =
|
||||
Handle<DependentCode>(Get(object), isolate_);
|
||||
Handle<DependentCode> new_dependent_code =
|
||||
DependentCode::InsertCompilationDependencies(old_dependent_code, group,
|
||||
object_wrapper_);
|
||||
|
||||
// Set the new dependent code list if the head of the list changed.
|
||||
if (!new_dependent_code.is_identical_to(old_dependent_code)) {
|
||||
Set(object, new_dependent_code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CompilationDependencies::Commit(Handle<Code> code) {
|
||||
if (IsEmpty()) return;
|
||||
|
||||
DCHECK(!object_wrapper_.is_null());
|
||||
Handle<WeakCell> cell = Code::WeakCellFor(code);
|
||||
AllowDeferredHandleDereference get_wrapper;
|
||||
for (int i = 0; i < DependentCode::kGroupCount; i++) {
|
||||
ZoneList<Handle<HeapObject>>* group_objects = groups_[i];
|
||||
if (group_objects == nullptr) continue;
|
||||
DependentCode::DependencyGroup group =
|
||||
static_cast<DependentCode::DependencyGroup>(i);
|
||||
for (int j = 0; j < group_objects->length(); j++) {
|
||||
DependentCode* dependent_code = Get(group_objects->at(j));
|
||||
dependent_code->UpdateToFinishedCode(group, *object_wrapper_, *cell);
|
||||
}
|
||||
groups_[i] = nullptr; // Zone-allocated, no need to delete.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CompilationDependencies::Rollback() {
|
||||
if (IsEmpty()) return;
|
||||
|
||||
AllowDeferredHandleDereference get_wrapper;
|
||||
// Unregister from all dependent maps if not yet committed.
|
||||
for (int i = 0; i < DependentCode::kGroupCount; i++) {
|
||||
ZoneList<Handle<HeapObject>>* group_objects = groups_[i];
|
||||
if (group_objects == nullptr) continue;
|
||||
DependentCode::DependencyGroup group =
|
||||
static_cast<DependentCode::DependencyGroup>(i);
|
||||
for (int j = 0; j < group_objects->length(); j++) {
|
||||
DependentCode* dependent_code = Get(group_objects->at(j));
|
||||
dependent_code->RemoveCompilationDependencies(group, *object_wrapper_);
|
||||
}
|
||||
groups_[i] = nullptr; // Zone-allocated, no need to delete.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CompilationDependencies::AssumeTransitionStable(
|
||||
Handle<AllocationSite> site) {
|
||||
// Do nothing if the object doesn't have any useful element transitions left.
|
||||
ElementsKind kind =
|
||||
site->SitePointsToLiteral()
|
||||
? JSObject::cast(site->transition_info())->GetElementsKind()
|
||||
: site->GetElementsKind();
|
||||
if (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) {
|
||||
Insert(DependentCode::kAllocationSiteTransitionChangedGroup, site);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace v8::internal
|
@ -1,67 +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_DEPENDENCIES_H_
|
||||
#define V8_DEPENDENCIES_H_
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// Collects dependencies for this compilation, e.g. assumptions about
|
||||
// stable maps, constant globals, etc.
|
||||
class CompilationDependencies {
|
||||
public:
|
||||
CompilationDependencies(Isolate* isolate, Zone* zone)
|
||||
: isolate_(isolate),
|
||||
zone_(zone),
|
||||
object_wrapper_(Handle<Foreign>::null()),
|
||||
aborted_(false) {
|
||||
std::fill_n(groups_, DependentCode::kGroupCount, nullptr);
|
||||
}
|
||||
|
||||
void Insert(DependentCode::DependencyGroup group, Handle<HeapObject> handle);
|
||||
|
||||
void AssumeInitialMapCantChange(Handle<Map> map) {
|
||||
Insert(DependentCode::kInitialMapChangedGroup, map);
|
||||
}
|
||||
void AssumeElementsCantBeAdded(Handle<Map> map) {
|
||||
Insert(DependentCode::kElementsCantBeAddedGroup, map);
|
||||
}
|
||||
void AssumeFieldType(Handle<Map> map) {
|
||||
Insert(DependentCode::kFieldTypeGroup, map);
|
||||
}
|
||||
void AssumePropertyCell(Handle<PropertyCell> cell) {
|
||||
Insert(DependentCode::kPropertyCellChangedGroup, cell);
|
||||
}
|
||||
void AssumeTenuringDecision(Handle<AllocationSite> site) {
|
||||
Insert(DependentCode::kAllocationSiteTenuringChangedGroup, site);
|
||||
}
|
||||
void AssumeTransitionStable(Handle<AllocationSite> site);
|
||||
|
||||
void Commit(Handle<Code> code);
|
||||
void Rollback();
|
||||
void Abort() { aborted_ = true; }
|
||||
bool HasAborted() const { return aborted_; }
|
||||
|
||||
bool IsEmpty() const {
|
||||
for (int i = 0; i < DependentCode::kGroupCount; i++) {
|
||||
if (groups_[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
Isolate* isolate_;
|
||||
Zone* zone_;
|
||||
Handle<Foreign> object_wrapper_;
|
||||
bool aborted_;
|
||||
ZoneList<Handle<HeapObject> >* groups_[DependentCode::kGroupCount];
|
||||
|
||||
DependentCode* Get(Handle<Object> object);
|
||||
void Set(Handle<Object> object, Handle<DependentCode> dep);
|
||||
};
|
||||
}
|
||||
} // namespace v8::internal
|
||||
|
||||
#endif // V8_DEPENDENCIES_H_
|
@ -87,7 +87,7 @@ class CompilationInfoWithZone : public CompilationInfo {
|
||||
// called when cast as a CompilationInfo.
|
||||
virtual ~CompilationInfoWithZone() {
|
||||
DisableFutureOptimization();
|
||||
dependencies()->Rollback();
|
||||
RollbackDependencies();
|
||||
delete parse_info_;
|
||||
parse_info_ = nullptr;
|
||||
}
|
||||
@ -143,7 +143,6 @@ CompilationInfo::CompilationInfo(ParseInfo* parse_info, CodeStub* code_stub,
|
||||
osr_ast_id_(BailoutId::None()),
|
||||
zone_(zone),
|
||||
deferred_handles_(nullptr),
|
||||
dependencies_(isolate, zone),
|
||||
bailout_reason_(kNoReason),
|
||||
prologue_offset_(Code::kPrologueOffsetNotSet),
|
||||
no_frame_ranges_(isolate->cpu_profiler()->is_profiling()
|
||||
@ -154,7 +153,10 @@ CompilationInfo::CompilationInfo(ParseInfo* parse_info, CodeStub* code_stub,
|
||||
opt_count_(has_shared_info() ? shared_info()->opt_count() : 0),
|
||||
parameter_count_(0),
|
||||
optimization_id_(-1),
|
||||
osr_expr_stack_height_(0) {}
|
||||
aborted_due_to_dependency_change_(false),
|
||||
osr_expr_stack_height_(0) {
|
||||
std::fill_n(dependencies_, DependentCode::kGroupCount, nullptr);
|
||||
}
|
||||
|
||||
|
||||
CompilationInfo::~CompilationInfo() {
|
||||
@ -164,11 +166,60 @@ CompilationInfo::~CompilationInfo() {
|
||||
#ifdef DEBUG
|
||||
// Check that no dependent maps have been added or added dependent maps have
|
||||
// been rolled back or committed.
|
||||
DCHECK(dependencies()->IsEmpty());
|
||||
for (int i = 0; i < DependentCode::kGroupCount; i++) {
|
||||
DCHECK(!dependencies_[i]);
|
||||
}
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
|
||||
void CompilationInfo::CommitDependencies(Handle<Code> code) {
|
||||
bool has_dependencies = false;
|
||||
for (int i = 0; i < DependentCode::kGroupCount; i++) {
|
||||
has_dependencies |=
|
||||
dependencies_[i] != NULL && dependencies_[i]->length() > 0;
|
||||
}
|
||||
// Avoid creating a weak cell for code with no dependencies.
|
||||
if (!has_dependencies) return;
|
||||
|
||||
AllowDeferredHandleDereference get_object_wrapper;
|
||||
WeakCell* cell = *Code::WeakCellFor(code);
|
||||
for (int i = 0; i < DependentCode::kGroupCount; i++) {
|
||||
ZoneList<Handle<HeapObject> >* group_objects = dependencies_[i];
|
||||
if (group_objects == NULL) continue;
|
||||
DCHECK(!object_wrapper_.is_null());
|
||||
for (int j = 0; j < group_objects->length(); j++) {
|
||||
DependentCode::DependencyGroup group =
|
||||
static_cast<DependentCode::DependencyGroup>(i);
|
||||
Foreign* info = *object_wrapper();
|
||||
DependentCode* dependent_code =
|
||||
DependentCode::ForObject(group_objects->at(j), group);
|
||||
dependent_code->UpdateToFinishedCode(group, info, cell);
|
||||
}
|
||||
dependencies_[i] = NULL; // Zone-allocated, no need to delete.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CompilationInfo::RollbackDependencies() {
|
||||
AllowDeferredHandleDereference get_object_wrapper;
|
||||
// Unregister from all dependent maps if not yet committed.
|
||||
for (int i = 0; i < DependentCode::kGroupCount; i++) {
|
||||
ZoneList<Handle<HeapObject> >* group_objects = dependencies_[i];
|
||||
if (group_objects == NULL) continue;
|
||||
for (int j = 0; j < group_objects->length(); j++) {
|
||||
DependentCode::DependencyGroup group =
|
||||
static_cast<DependentCode::DependencyGroup>(i);
|
||||
Foreign* info = *object_wrapper();
|
||||
DependentCode* dependent_code =
|
||||
DependentCode::ForObject(group_objects->at(j), group);
|
||||
dependent_code->RemoveCompilationInfo(group, info);
|
||||
}
|
||||
dependencies_[i] = NULL; // Zone-allocated, no need to delete.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CompilationInfo::num_parameters() const {
|
||||
return has_scope() ? scope()->num_parameters() : parameter_count_;
|
||||
}
|
||||
@ -442,7 +493,7 @@ OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() {
|
||||
|
||||
if (graph_ == NULL) return SetLastStatus(BAILED_OUT);
|
||||
|
||||
if (info()->dependencies()->HasAborted()) {
|
||||
if (info()->HasAbortedDueToDependencyChange()) {
|
||||
// Dependency has changed during graph creation. Let's try again later.
|
||||
return RetryOptimization(kBailedOutDueToDependencyChange);
|
||||
}
|
||||
@ -490,7 +541,7 @@ OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() {
|
||||
return last_status();
|
||||
}
|
||||
|
||||
DCHECK(!info()->dependencies()->HasAborted());
|
||||
DCHECK(!info()->HasAbortedDueToDependencyChange());
|
||||
DisallowCodeDependencyChange no_dependency_change;
|
||||
DisallowJavascriptExecution no_js(isolate());
|
||||
{ // Scope for timer.
|
||||
@ -1471,7 +1522,7 @@ Handle<Code> Compiler::GetConcurrentlyOptimizedCode(OptimizedCompileJob* job) {
|
||||
if (job->last_status() == OptimizedCompileJob::SUCCEEDED) {
|
||||
if (shared->optimization_disabled()) {
|
||||
job->RetryOptimization(kOptimizationDisabled);
|
||||
} else if (info->dependencies()->HasAborted()) {
|
||||
} else if (info->HasAbortedDueToDependencyChange()) {
|
||||
job->RetryOptimization(kBailedOutDueToDependencyChange);
|
||||
} else if (isolate->debug()->has_break_points()) {
|
||||
job->RetryOptimization(kDebuggerHasBreakPoints);
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "src/allocation.h"
|
||||
#include "src/ast.h"
|
||||
#include "src/bailout-reason.h"
|
||||
#include "src/compilation-dependencies.h"
|
||||
#include "src/zone.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -300,6 +299,18 @@ class CompilationInfo {
|
||||
deferred_handles_ = deferred_handles;
|
||||
}
|
||||
|
||||
ZoneList<Handle<HeapObject> >* dependencies(
|
||||
DependentCode::DependencyGroup group) {
|
||||
if (dependencies_[group] == NULL) {
|
||||
dependencies_[group] = new(zone_) ZoneList<Handle<HeapObject> >(2, zone_);
|
||||
}
|
||||
return dependencies_[group];
|
||||
}
|
||||
|
||||
void CommitDependencies(Handle<Code> code);
|
||||
|
||||
void RollbackDependencies();
|
||||
|
||||
void ReopenHandlesInNewHandleScope() {
|
||||
unoptimized_code_ = Handle<Code>(*unoptimized_code_);
|
||||
}
|
||||
@ -352,7 +363,21 @@ class CompilationInfo {
|
||||
int TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
|
||||
SourcePosition position, int pareint_id);
|
||||
|
||||
CompilationDependencies* dependencies() { return &dependencies_; }
|
||||
Handle<Foreign> object_wrapper() {
|
||||
if (object_wrapper_.is_null()) {
|
||||
object_wrapper_ =
|
||||
isolate()->factory()->NewForeign(reinterpret_cast<Address>(this));
|
||||
}
|
||||
return object_wrapper_;
|
||||
}
|
||||
|
||||
void AbortDueToDependencyChange() {
|
||||
aborted_due_to_dependency_change_ = true;
|
||||
}
|
||||
|
||||
bool HasAbortedDueToDependencyChange() const {
|
||||
return aborted_due_to_dependency_change_;
|
||||
}
|
||||
|
||||
bool HasSameOsrEntry(Handle<JSFunction> function, BailoutId osr_ast_id) {
|
||||
return osr_ast_id_ == osr_ast_id && function.is_identical_to(closure());
|
||||
@ -435,8 +460,7 @@ class CompilationInfo {
|
||||
|
||||
DeferredHandles* deferred_handles_;
|
||||
|
||||
// Dependencies for this compilation, e.g. stable maps.
|
||||
CompilationDependencies dependencies_;
|
||||
ZoneList<Handle<HeapObject> >* dependencies_[DependentCode::kGroupCount];
|
||||
|
||||
BailoutReason bailout_reason_;
|
||||
|
||||
@ -453,8 +477,14 @@ class CompilationInfo {
|
||||
// Number of parameters used for compilation of stubs that require arguments.
|
||||
int parameter_count_;
|
||||
|
||||
Handle<Foreign> object_wrapper_;
|
||||
|
||||
int optimization_id_;
|
||||
|
||||
// This flag is used by the main thread to track whether this compilation
|
||||
// should be abandoned due to dependency change.
|
||||
bool aborted_due_to_dependency_change_;
|
||||
|
||||
int osr_expr_stack_height_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
|
||||
|
@ -5396,7 +5396,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
|
||||
|
||||
if (type == kUseCell) {
|
||||
Handle<PropertyCell> cell = it.GetPropertyCell();
|
||||
top_info()->dependencies()->AssumePropertyCell(cell);
|
||||
PropertyCell::AddDependentCompilationInfo(cell, top_info());
|
||||
if (it.property_details().cell_type() == PropertyCellType::kConstant) {
|
||||
Handle<Object> constant_object(cell->value(), isolate());
|
||||
if (constant_object->IsConsString()) {
|
||||
@ -5777,7 +5777,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
4);
|
||||
|
||||
// Register to deopt if the boilerplate ElementsKind changes.
|
||||
top_info()->dependencies()->AssumeTransitionStable(site);
|
||||
AllocationSite::RegisterForDeoptOnTransitionChange(site, top_info());
|
||||
}
|
||||
|
||||
// The array is expected in the bailout environment during computation
|
||||
@ -6092,7 +6092,8 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
|
||||
DCHECK(field_type_.IsHeapObject());
|
||||
|
||||
// Add dependency on the map that introduced the field.
|
||||
top_info()->dependencies()->AssumeFieldType(GetFieldOwnerFromMap(map));
|
||||
Map::AddDependentCompilationInfo(GetFieldOwnerFromMap(map),
|
||||
DependentCode::kFieldTypeGroup, top_info());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6561,7 +6562,7 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
|
||||
GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE);
|
||||
if (type == kUseCell) {
|
||||
Handle<PropertyCell> cell = it.GetPropertyCell();
|
||||
top_info()->dependencies()->AssumePropertyCell(cell);
|
||||
PropertyCell::AddDependentCompilationInfo(cell, top_info());
|
||||
if (it.property_details().cell_type() == PropertyCellType::kConstant) {
|
||||
Handle<Object> constant(cell->value(), isolate());
|
||||
if (value->IsConstant()) {
|
||||
@ -9355,7 +9356,7 @@ void HOptimizedGraphBuilder::BuildInlinedCallArray(
|
||||
HValue* constructor = environment()->ExpressionStackAt(argument_count);
|
||||
|
||||
// Register on the site for deoptimization if the transition feedback changes.
|
||||
top_info()->dependencies()->AssumeTransitionStable(site);
|
||||
AllocationSite::RegisterForDeoptOnTransitionChange(site, top_info());
|
||||
ElementsKind kind = site->GetElementsKind();
|
||||
HInstruction* site_instruction = Add<HConstant>(site);
|
||||
|
||||
@ -9491,7 +9492,8 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
|
||||
Handle<AllocationSite> allocation_site = expr->allocation_site();
|
||||
allocation_mode = HAllocationMode(allocation_site);
|
||||
// Take a dependency on allocation site.
|
||||
top_info()->dependencies()->AssumeTenuringDecision(allocation_site);
|
||||
AllocationSite::RegisterForDeoptOnTenureChange(allocation_site,
|
||||
top_info());
|
||||
}
|
||||
}
|
||||
|
||||
@ -9535,7 +9537,8 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
|
||||
// Inlining worked, add a dependency on the initial map to make sure that
|
||||
// this code is deoptimized whenever the initial map of the constructor
|
||||
// changes.
|
||||
top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
|
||||
Map::AddDependentCompilationInfo(
|
||||
initial_map, DependentCode::kInitialMapChangedGroup, top_info());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -10509,7 +10512,7 @@ HValue* HGraphBuilder::BuildBinaryOperation(
|
||||
if (!allocation_mode.feedback_site().is_null()) {
|
||||
DCHECK(!graph()->info()->IsStub());
|
||||
Handle<AllocationSite> site(allocation_mode.feedback_site());
|
||||
top_info()->dependencies()->AssumeTenuringDecision(site);
|
||||
AllocationSite::RegisterForDeoptOnTenureChange(site, top_info());
|
||||
}
|
||||
|
||||
// Inline the string addition into the stub when creating allocation
|
||||
@ -11080,10 +11083,10 @@ HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
|
||||
Handle<AllocationSite> site(site_context->current());
|
||||
if (FLAG_allocation_site_pretenuring) {
|
||||
pretenure_flag = site_context->current()->GetPretenureMode();
|
||||
top_info()->dependencies()->AssumeTenuringDecision(site);
|
||||
AllocationSite::RegisterForDeoptOnTenureChange(site, top_info());
|
||||
}
|
||||
|
||||
top_info()->dependencies()->AssumeTransitionStable(site);
|
||||
AllocationSite::RegisterForDeoptOnTransitionChange(site, top_info());
|
||||
|
||||
HInstruction* object = Add<HAllocate>(object_size_constant, type,
|
||||
pretenure_flag, instance_type, site_context->current());
|
||||
|
@ -416,10 +416,12 @@ class HGraph FINAL : public ZoneObject {
|
||||
void MarkDependsOnEmptyArrayProtoElements() {
|
||||
// Add map dependency if not already added.
|
||||
if (depends_on_empty_array_proto_elements_) return;
|
||||
info()->dependencies()->AssumeElementsCantBeAdded(
|
||||
handle(isolate()->initial_object_prototype()->map()));
|
||||
info()->dependencies()->AssumeElementsCantBeAdded(
|
||||
handle(isolate()->initial_array_prototype()->map()));
|
||||
Map::AddDependentCompilationInfo(
|
||||
handle(isolate()->initial_object_prototype()->map()),
|
||||
DependentCode::kElementsCantBeAddedGroup, info());
|
||||
Map::AddDependentCompilationInfo(
|
||||
handle(isolate()->initial_array_prototype()->map()),
|
||||
DependentCode::kElementsCantBeAddedGroup, info());
|
||||
depends_on_empty_array_proto_elements_ = true;
|
||||
}
|
||||
|
||||
|
@ -484,7 +484,7 @@ void LChunk::CommitDependencies(Handle<Code> code) const {
|
||||
Map::AddDependentCode(map, DependentCode::kPrototypeCheckGroup, code);
|
||||
}
|
||||
|
||||
info_->dependencies()->Commit(code);
|
||||
info_->CommitDependencies(code);
|
||||
RegisterWeakObjectsInOptimizedCode(code);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "src/bootstrapper.h"
|
||||
#include "src/code-stubs.h"
|
||||
#include "src/codegen.h"
|
||||
#include "src/compilation-dependencies.h"
|
||||
#include "src/compiler.h"
|
||||
#include "src/cpu-profiler.h"
|
||||
#include "src/date.h"
|
||||
@ -12138,6 +12137,18 @@ MaybeHandle<Object> JSArray::SetElementsLength(
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void Map::AddDependentCompilationInfo(Handle<Map> map,
|
||||
DependentCode::DependencyGroup group,
|
||||
CompilationInfo* info) {
|
||||
Handle<DependentCode> codes = DependentCode::InsertCompilationInfo(
|
||||
handle(map->dependent_code(), info->isolate()), group,
|
||||
info->object_wrapper());
|
||||
if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
|
||||
info->dependencies(group)->Add(map, info->zone());
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void Map::AddDependentCode(Handle<Map> map,
|
||||
DependentCode::DependencyGroup group,
|
||||
@ -12163,7 +12174,20 @@ void DependentCode::GroupStartIndexes::Recompute(DependentCode* entries) {
|
||||
}
|
||||
|
||||
|
||||
Handle<DependentCode> DependentCode::InsertCompilationDependencies(
|
||||
DependentCode* DependentCode::ForObject(Handle<HeapObject> object,
|
||||
DependencyGroup group) {
|
||||
AllowDeferredHandleDereference dependencies_are_safe;
|
||||
if (group == DependentCode::kPropertyCellChangedGroup) {
|
||||
return Handle<PropertyCell>::cast(object)->dependent_code();
|
||||
} else if (group == DependentCode::kAllocationSiteTenuringChangedGroup ||
|
||||
group == DependentCode::kAllocationSiteTransitionChangedGroup) {
|
||||
return Handle<AllocationSite>::cast(object)->dependent_code();
|
||||
}
|
||||
return Handle<Map>::cast(object)->dependent_code();
|
||||
}
|
||||
|
||||
|
||||
Handle<DependentCode> DependentCode::InsertCompilationInfo(
|
||||
Handle<DependentCode> entries, DependencyGroup group,
|
||||
Handle<Foreign> info) {
|
||||
return Insert(entries, group, info);
|
||||
@ -12269,8 +12293,8 @@ void DependentCode::UpdateToFinishedCode(DependencyGroup group, Foreign* info,
|
||||
}
|
||||
|
||||
|
||||
void DependentCode::RemoveCompilationDependencies(
|
||||
DependentCode::DependencyGroup group, Foreign* info) {
|
||||
void DependentCode::RemoveCompilationInfo(DependentCode::DependencyGroup group,
|
||||
Foreign* info) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
GroupStartIndexes starts(this);
|
||||
int start = starts.at(group);
|
||||
@ -12344,10 +12368,9 @@ bool DependentCode::MarkCodeForDeoptimization(
|
||||
}
|
||||
} else {
|
||||
DCHECK(obj->IsForeign());
|
||||
CompilationDependencies* info =
|
||||
reinterpret_cast<CompilationDependencies*>(
|
||||
Foreign::cast(obj)->foreign_address());
|
||||
info->Abort();
|
||||
CompilationInfo* info = reinterpret_cast<CompilationInfo*>(
|
||||
Foreign::cast(obj)->foreign_address());
|
||||
info->AbortDueToDependencyChange();
|
||||
}
|
||||
}
|
||||
// Compact the array by moving all subsequent groups to fill in the new holes.
|
||||
@ -13429,6 +13452,41 @@ void AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void AllocationSite::RegisterForDeoptOnTenureChange(Handle<AllocationSite> site,
|
||||
CompilationInfo* info) {
|
||||
AddDependentCompilationInfo(
|
||||
site, DependentCode::kAllocationSiteTenuringChangedGroup, info);
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void AllocationSite::RegisterForDeoptOnTransitionChange(
|
||||
Handle<AllocationSite> site, CompilationInfo* info) {
|
||||
// Do nothing if the object doesn't have any useful element transitions left.
|
||||
ElementsKind kind =
|
||||
site->SitePointsToLiteral()
|
||||
? JSObject::cast(site->transition_info())->GetElementsKind()
|
||||
: site->GetElementsKind();
|
||||
if (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) {
|
||||
AddDependentCompilationInfo(
|
||||
site, DependentCode::kAllocationSiteTransitionChangedGroup, info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void AllocationSite::AddDependentCompilationInfo(
|
||||
Handle<AllocationSite> site, DependentCode::DependencyGroup group,
|
||||
CompilationInfo* info) {
|
||||
Handle<DependentCode> dep(site->dependent_code());
|
||||
Handle<DependentCode> codes =
|
||||
DependentCode::InsertCompilationInfo(dep, group, info->object_wrapper());
|
||||
if (*codes != site->dependent_code()) site->set_dependent_code(*codes);
|
||||
info->dependencies(group)->Add(Handle<HeapObject>(*site), info->zone());
|
||||
}
|
||||
|
||||
|
||||
const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
|
||||
switch (decision) {
|
||||
case kUndecided: return "undecided";
|
||||
@ -17082,4 +17140,16 @@ Handle<Object> PropertyCell::UpdateCell(Handle<NameDictionary> dictionary,
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void PropertyCell::AddDependentCompilationInfo(Handle<PropertyCell> cell,
|
||||
CompilationInfo* info) {
|
||||
Handle<DependentCode> codes = DependentCode::InsertCompilationInfo(
|
||||
handle(cell->dependent_code(), info->isolate()),
|
||||
DependentCode::kPropertyCellChangedGroup, info->object_wrapper());
|
||||
if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes);
|
||||
info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
|
||||
cell, info->zone());
|
||||
}
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -5696,6 +5696,8 @@ class Code: public HeapObject {
|
||||
};
|
||||
|
||||
|
||||
class CompilationInfo;
|
||||
|
||||
// This class describes the layout of dependent codes array of a map. The
|
||||
// array is partitioned into several groups of dependent codes. Each group
|
||||
// contains codes with the same dependency on the map. The array has the
|
||||
@ -5765,7 +5767,7 @@ class DependentCode: public FixedArray {
|
||||
|
||||
bool Contains(DependencyGroup group, WeakCell* code_cell);
|
||||
|
||||
static Handle<DependentCode> InsertCompilationDependencies(
|
||||
static Handle<DependentCode> InsertCompilationInfo(
|
||||
Handle<DependentCode> entries, DependencyGroup group,
|
||||
Handle<Foreign> info);
|
||||
|
||||
@ -5776,8 +5778,8 @@ class DependentCode: public FixedArray {
|
||||
void UpdateToFinishedCode(DependencyGroup group, Foreign* info,
|
||||
WeakCell* code_cell);
|
||||
|
||||
void RemoveCompilationDependencies(DependentCode::DependencyGroup group,
|
||||
Foreign* info);
|
||||
void RemoveCompilationInfo(DependentCode::DependencyGroup group,
|
||||
Foreign* info);
|
||||
|
||||
void DeoptimizeDependentCodeGroup(Isolate* isolate,
|
||||
DependentCode::DependencyGroup group);
|
||||
@ -5795,6 +5797,9 @@ class DependentCode: public FixedArray {
|
||||
inline void copy(int from, int to);
|
||||
DECLARE_CAST(DependentCode)
|
||||
|
||||
static DependentCode* ForObject(Handle<HeapObject> object,
|
||||
DependencyGroup group);
|
||||
|
||||
static const char* DependencyGroupName(DependencyGroup group);
|
||||
static void SetMarkedForDeoptimization(Code* code, DependencyGroup group);
|
||||
|
||||
@ -6352,6 +6357,10 @@ class Map: public HeapObject {
|
||||
|
||||
inline bool CanOmitMapChecks();
|
||||
|
||||
static void AddDependentCompilationInfo(Handle<Map> map,
|
||||
DependentCode::DependencyGroup group,
|
||||
CompilationInfo* info);
|
||||
|
||||
static void AddDependentCode(Handle<Map> map,
|
||||
DependentCode::DependencyGroup group,
|
||||
Handle<Code> code);
|
||||
@ -8554,6 +8563,12 @@ class AllocationSite: public Struct {
|
||||
static void DigestTransitionFeedback(Handle<AllocationSite> site,
|
||||
ElementsKind to_kind);
|
||||
|
||||
static void RegisterForDeoptOnTenureChange(Handle<AllocationSite> site,
|
||||
CompilationInfo* info);
|
||||
|
||||
static void RegisterForDeoptOnTransitionChange(Handle<AllocationSite> site,
|
||||
CompilationInfo* info);
|
||||
|
||||
DECLARE_PRINTER(AllocationSite)
|
||||
DECLARE_VERIFIER(AllocationSite)
|
||||
|
||||
@ -8584,6 +8599,10 @@ class AllocationSite: public Struct {
|
||||
kSize> BodyDescriptor;
|
||||
|
||||
private:
|
||||
static void AddDependentCompilationInfo(Handle<AllocationSite> site,
|
||||
DependentCode::DependencyGroup group,
|
||||
CompilationInfo* info);
|
||||
|
||||
bool PretenuringDecisionMade() {
|
||||
return pretenure_decision() != kUndecided;
|
||||
}
|
||||
@ -9816,6 +9835,9 @@ class PropertyCell : public HeapObject {
|
||||
static Handle<PropertyCell> InvalidateEntry(Handle<NameDictionary> dictionary,
|
||||
int entry);
|
||||
|
||||
static void AddDependentCompilationInfo(Handle<PropertyCell> cell,
|
||||
CompilationInfo* info);
|
||||
|
||||
DECLARE_CAST(PropertyCell)
|
||||
|
||||
// Dispatched behavior.
|
||||
|
@ -591,9 +591,10 @@ static void TestGeneralizeRepresentation(
|
||||
// Create new maps by generalizing representation of propX field.
|
||||
Handle<Map> field_owner(map->FindFieldOwner(property_index), isolate);
|
||||
CompilationInfo info(&stub, isolate, &zone);
|
||||
CHECK(!info.dependencies()->HasAborted());
|
||||
CHECK(!info.HasAbortedDueToDependencyChange());
|
||||
|
||||
info.dependencies()->AssumeFieldType(field_owner);
|
||||
Map::AddDependentCompilationInfo(field_owner, DependentCode::kFieldTypeGroup,
|
||||
&info);
|
||||
|
||||
Handle<Map> new_map =
|
||||
Map::ReconfigureProperty(map, property_index, kData, NONE,
|
||||
@ -609,22 +610,23 @@ static void TestGeneralizeRepresentation(
|
||||
CHECK(map->is_deprecated());
|
||||
CHECK_NE(*map, *new_map);
|
||||
CHECK_EQ(expected_field_type_dependency && !field_owner->is_deprecated(),
|
||||
info.dependencies()->HasAborted());
|
||||
info.HasAbortedDueToDependencyChange());
|
||||
|
||||
} else if (expected_deprecation) {
|
||||
CHECK(map->is_deprecated());
|
||||
CHECK(field_owner->is_deprecated());
|
||||
CHECK_NE(*map, *new_map);
|
||||
CHECK(!info.dependencies()->HasAborted());
|
||||
CHECK(!info.HasAbortedDueToDependencyChange());
|
||||
|
||||
} else {
|
||||
CHECK(!field_owner->is_deprecated());
|
||||
CHECK_EQ(*map, *new_map);
|
||||
|
||||
CHECK_EQ(expected_field_type_dependency, info.dependencies()->HasAborted());
|
||||
CHECK_EQ(expected_field_type_dependency,
|
||||
info.HasAbortedDueToDependencyChange());
|
||||
}
|
||||
|
||||
info.dependencies()->Rollback(); // Properly cleanup compilation info.
|
||||
info.RollbackDependencies(); // Properly cleanup compilation info.
|
||||
|
||||
// Update all deprecated maps and check that they are now the same.
|
||||
Handle<Map> updated_map = Map::Update(map);
|
||||
@ -959,8 +961,9 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
|
||||
FakeStubForTesting stub(isolate);
|
||||
Handle<Map> field_owner(map->FindFieldOwner(kSplitProp), isolate);
|
||||
CompilationInfo info(&stub, isolate, &zone);
|
||||
CHECK(!info.dependencies()->HasAborted());
|
||||
info.dependencies()->AssumeFieldType(field_owner);
|
||||
CHECK(!info.HasAbortedDueToDependencyChange());
|
||||
Map::AddDependentCompilationInfo(field_owner, DependentCode::kFieldTypeGroup,
|
||||
&info);
|
||||
|
||||
// Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
|
||||
// should generalize representations in |map1|.
|
||||
@ -977,8 +980,8 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
|
||||
expectations.SetDataField(i, expected_representation, expected_type);
|
||||
}
|
||||
CHECK(map->is_deprecated());
|
||||
CHECK(!info.dependencies()->HasAborted());
|
||||
info.dependencies()->Rollback(); // Properly cleanup compilation info.
|
||||
CHECK(!info.HasAbortedDueToDependencyChange());
|
||||
info.RollbackDependencies(); // Properly cleanup compilation info.
|
||||
CHECK_NE(*map, *new_map);
|
||||
|
||||
CHECK(!new_map->is_deprecated());
|
||||
@ -1044,8 +1047,9 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
|
||||
FakeStubForTesting stub(isolate);
|
||||
Handle<Map> field_owner(map->FindFieldOwner(kSplitProp), isolate);
|
||||
CompilationInfo info(&stub, isolate, &zone);
|
||||
CHECK(!info.dependencies()->HasAborted());
|
||||
info.dependencies()->AssumeFieldType(field_owner);
|
||||
CHECK(!info.HasAbortedDueToDependencyChange());
|
||||
Map::AddDependentCompilationInfo(field_owner, DependentCode::kFieldTypeGroup,
|
||||
&info);
|
||||
|
||||
// Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
|
||||
// should generalize representations in |map1|.
|
||||
@ -1066,8 +1070,9 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
|
||||
}
|
||||
CHECK(!map->is_deprecated());
|
||||
CHECK_EQ(*map, *new_map);
|
||||
CHECK_EQ(expected_field_type_dependency, info.dependencies()->HasAborted());
|
||||
info.dependencies()->Rollback(); // Properly cleanup compilation info.
|
||||
CHECK_EQ(expected_field_type_dependency,
|
||||
info.HasAbortedDueToDependencyChange());
|
||||
info.RollbackDependencies(); // Properly cleanup compilation info.
|
||||
|
||||
CHECK(!new_map->is_deprecated());
|
||||
CHECK(expectations.Check(*new_map));
|
||||
|
@ -422,8 +422,6 @@
|
||||
'../../src/codegen.h',
|
||||
'../../src/compilation-cache.cc',
|
||||
'../../src/compilation-cache.h',
|
||||
'../../src/compilation-dependencies.cc',
|
||||
'../../src/compilation-dependencies.h',
|
||||
'../../src/compilation-statistics.cc',
|
||||
'../../src/compilation-statistics.h',
|
||||
'../../src/compiler/access-builder.cc',
|
||||
|
Loading…
Reference in New Issue
Block a user