Revert "[turbofan] Rewrite CompilationDependencies"

This reverts commit 52a10e5081.

Reason for revert: https://test-results.appspot.com/data/layout_results/V8-Blink_Linux_64__dbg_/12434/layout-test-results/results.html

Crash e.g. in http/tests/devtools/oopif/oopif-performance-cpu-profiles.js

crash log for devtools (pid <unknown>):
STDOUT: <empty>
STDERR: 
STDERR: 
STDERR: #
STDERR: # Fatal error in ../../v8/src/compilation-dependencies.cc, line 281
STDERR: # Debug check failed: descriptor == owner->LastAdded() (10 vs. 22).
STDERR: #
STDERR: #
STDERR: #
STDERR: #FailureMessage Object: 0x7fff86878630#0 0x0000031c642c base::debug::StackTrace::StackTrace()
STDERR: #1 0x0000046a56bb gin::(anonymous namespace)::PrintStackTrace()
STDERR: #2 0x00000469c528 V8_Fatal()
STDERR: #3 0x00000469c285 v8::base::(anonymous namespace)::DefaultDcheckHandler()
STDERR: #4 0x000001cc5253 v8::internal::CompilationDependencies::DependOnFieldType()
STDERR: #5 0x000001cdcc46 v8::internal::compiler::AccessInfoFactory::ComputePropertyAccessInfo()
STDERR: #6 0x000001cde661 v8::internal::compiler::AccessInfoFactory::ComputePropertyAccessInfos()
STDERR: #7 0x000001dd982b v8::internal::compiler::JSNativeContextSpecialization::ReduceNamedAccess()
STDERR: #8 0x000001ddb715 v8::internal::compiler::JSNativeContextSpecialization::ReduceNamedAccessFromNexus()
STDERR: #9 0x000001dd656d v8::internal::compiler::JSNativeContextSpecialization::ReduceJSLoadNamed()
STDERR: #10 0x000001d53872 v8::internal::compiler::GraphReducer::Reduce()
STDERR: #11 0x000001d534a5 v8::internal::compiler::GraphReducer::ReduceTop()
STDERR: #12 0x000001d52e58 v8::internal::compiler::GraphReducer::ReduceNode()
STDERR: #13 0x000001e4c201 v8::internal::compiler::InliningPhase::Run()
STDERR: #14 0x000001e44f79 v8::internal::compiler::PipelineImpl::Run<>()
STDERR: #15 0x000001e41058 v8::internal::compiler::PipelineImpl::CreateGraph()
STDERR: #16 0x000001e40c75 v8::internal::compiler::PipelineCompilationJob::PrepareJobImpl()
STDERR: #17 0x000001ccd437 v8::internal::OptimizedCompilationJob::PrepareJob()
STDERR: #18 0x000001cd071e v8::internal::(anonymous namespace)::GetOptimizedCode()
STDERR: #19 0x000001cd0c6f v8::internal::Compiler::CompileOptimized()
STDERR: #20 0x00000231fb62 v8::internal::__RT_impl_Runtime_CompileOptimized_Concurrent()
STDERR: #21 0x00000288e535 <unknown>

Original change's description:
> [turbofan] Rewrite CompilationDependencies
> 
> Instead of installing code dependencies during graph reduction,
> install them after code generation.
> 
> Bug: v8:7902, v8:7790
> Change-Id: I8a3798254abb5b9ec7c295a1592aeb6b51f24c7a
> Reviewed-on: https://chromium-review.googlesource.com/1119913
> Commit-Queue: Georg Neis <neis@chromium.org>
> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#54170}

TBR=mstarzinger@chromium.org,jarin@chromium.org,neis@chromium.org

Change-Id: Ic58c2bfadbd34bb6ba7dc0d2b74871cc90b0a74f
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:7902, v8:7790
Reviewed-on: https://chromium-review.googlesource.com/1125680
Reviewed-by: Yang Guo <yangguo@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54192}
This commit is contained in:
Yang Guo 2018-07-04 08:59:10 +00:00 committed by Commit Bot
parent ade7f55b3a
commit b1cf1e1e07
20 changed files with 349 additions and 495 deletions

View File

@ -5,14 +5,15 @@
#include "src/compilation-dependencies.h"
#include "src/handles-inl.h"
#include "src/heap/factory.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/zone/zone.h"
namespace v8 {
namespace internal {
// TODO(neis): Move these to the DependentCode class.
namespace {
DependentCode* GetDependentCode(Handle<Object> object) {
DependentCode* CompilationDependencies::Get(Handle<Object> object) const {
if (object->IsMap()) {
return Handle<Map>::cast(object)->dependent_code();
} else if (object->IsPropertyCell()) {
@ -23,7 +24,9 @@ DependentCode* GetDependentCode(Handle<Object> object) {
UNREACHABLE();
}
void SetDependentCode(Handle<Object> object, Handle<DependentCode> dep) {
void CompilationDependencies::Set(Handle<Object> object,
Handle<DependentCode> dep) {
if (object->IsMap()) {
Handle<Map>::cast(object)->set_dependent_code(*dep);
} else if (object->IsPropertyCell()) {
@ -35,332 +38,106 @@ void SetDependentCode(Handle<Object> object, Handle<DependentCode> dep) {
}
}
void InstallDependency(Isolate* isolate, Handle<WeakCell> source,
Handle<HeapObject> target,
DependentCode::DependencyGroup group) {
Handle<DependentCode> old_deps(GetDependentCode(target), isolate);
Handle<DependentCode> new_deps =
DependentCode::InsertWeakCode(old_deps, group, source);
// Update the list head if necessary.
if (!new_deps.is_identical_to(old_deps)) SetDependentCode(target, new_deps);
}
} // namespace
CompilationDependencies::CompilationDependencies(Isolate* isolate, Zone* zone)
: isolate_(isolate), zone_(zone), dependencies_(zone) {}
void CompilationDependencies::Insert(DependentCode::DependencyGroup group,
Handle<HeapObject> object) {
if (groups_[group] == nullptr) {
groups_[group] = new (zone_->New(sizeof(ZoneVector<Handle<HeapObject>>)))
ZoneVector<Handle<HeapObject>>(zone_);
}
groups_[group]->push_back(object);
class CompilationDependencies::Dependency : public ZoneObject {
public:
virtual bool IsValid() const = 0;
virtual void Install(Isolate* isolate, Handle<WeakCell> code) = 0;
};
class InitialMapDependency final : public CompilationDependencies::Dependency {
public:
InitialMapDependency(Handle<JSFunction> function, Handle<Map> initial_map)
: function_(function), initial_map_(initial_map) {
DCHECK(IsValid());
if (object_wrapper_.is_null()) {
// Allocate the wrapper if necessary.
object_wrapper_ =
isolate_->factory()->NewForeign(reinterpret_cast<Address>(this));
}
bool IsValid() const override {
DisallowHeapAllocation no_heap_allocation;
DCHECK(function_->has_initial_map());
return *initial_map_ == function_->initial_map();
}
// 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_);
void Install(Isolate* isolate, Handle<WeakCell> code) override {
DCHECK(IsValid());
InstallDependency(isolate, code, initial_map_,
DependentCode::kInitialMapChangedGroup);
}
private:
Handle<JSFunction> function_;
Handle<Map> initial_map_;
};
class StableMapDependency final : public CompilationDependencies::Dependency {
public:
explicit StableMapDependency(Handle<Map> map) : map_(map) {
DCHECK(IsValid());
}
bool IsValid() const override {
DisallowHeapAllocation no_heap_allocation;
return map_->is_stable();
}
void Install(Isolate* isolate, Handle<WeakCell> code) override {
DCHECK(IsValid());
InstallDependency(isolate, code, map_, DependentCode::kPrototypeCheckGroup);
}
private:
Handle<Map> map_;
};
class TransitionDependency final : public CompilationDependencies::Dependency {
public:
explicit TransitionDependency(Handle<Map> map) : map_(map) {
DCHECK(IsValid());
}
bool IsValid() const override {
DisallowHeapAllocation no_heap_allocation;
return !map_->is_deprecated();
}
void Install(Isolate* isolate, Handle<WeakCell> code) override {
DCHECK(IsValid());
InstallDependency(isolate, code, map_, DependentCode::kTransitionGroup);
}
private:
Handle<Map> map_;
};
class PretenureModeDependency final
: public CompilationDependencies::Dependency {
public:
PretenureModeDependency(Handle<AllocationSite> site, PretenureFlag mode)
: site_(site), mode_(mode) {
DCHECK(IsValid());
}
bool IsValid() const override {
DisallowHeapAllocation no_heap_allocation;
return mode_ == site_->GetPretenureMode();
}
void Install(Isolate* isolate, Handle<WeakCell> code) override {
DCHECK(IsValid());
InstallDependency(isolate, code, site_,
DependentCode::kAllocationSiteTenuringChangedGroup);
}
private:
Handle<AllocationSite> site_;
PretenureFlag mode_;
};
class FieldTypeDependency final : public CompilationDependencies::Dependency {
public:
FieldTypeDependency(Isolate* isolate, Handle<Map> owner,
Handle<FieldType> type)
: isolate_(isolate), owner_(owner), type_(type) {
DCHECK(IsValid());
}
bool IsValid() const override {
DisallowHeapAllocation no_heap_allocation;
int descriptor = owner_->LastAdded();
CHECK_EQ(*owner_, owner_->FindFieldOwner(isolate_, descriptor));
return *type_ == owner_->instance_descriptors()->GetFieldType(descriptor);
}
void Install(Isolate* isolate, Handle<WeakCell> code) override {
DCHECK(IsValid());
InstallDependency(isolate, code, owner_, DependentCode::kFieldOwnerGroup);
}
private:
Isolate* isolate_;
Handle<Map> owner_;
Handle<FieldType> type_;
};
class GlobalPropertyDependency final
: public CompilationDependencies::Dependency {
public:
GlobalPropertyDependency(Handle<PropertyCell> cell, PropertyCellType type,
bool read_only)
: cell_(cell), type_(type), read_only_(read_only) {
DCHECK(IsValid());
}
bool IsValid() const override {
DisallowHeapAllocation no_heap_allocation;
return type_ == cell_->property_details().cell_type() &&
read_only_ == cell_->property_details().IsReadOnly();
}
void Install(Isolate* isolate, Handle<WeakCell> code) override {
DCHECK(IsValid());
InstallDependency(isolate, code, cell_,
DependentCode::kPropertyCellChangedGroup);
}
private:
Handle<PropertyCell> cell_;
PropertyCellType type_;
bool read_only_;
};
class ProtectorDependency final : public CompilationDependencies::Dependency {
public:
explicit ProtectorDependency(Handle<PropertyCell> cell) : cell_(cell) {
DCHECK(IsValid());
}
bool IsValid() const override {
DisallowHeapAllocation no_heap_allocation;
return cell_->value() == Smi::FromInt(Isolate::kProtectorValid);
}
void Install(Isolate* isolate, Handle<WeakCell> code) override {
DCHECK(IsValid());
InstallDependency(isolate, code, cell_,
DependentCode::kPropertyCellChangedGroup);
}
private:
Handle<PropertyCell> cell_;
};
class ElementsKindDependency final
: public CompilationDependencies::Dependency {
public:
ElementsKindDependency(Handle<AllocationSite> site, ElementsKind kind)
: site_(site), kind_(kind) {
DCHECK(IsValid());
}
bool IsValid() const override {
DisallowHeapAllocation no_heap_allocation;
DCHECK(AllocationSite::ShouldTrack(kind_));
ElementsKind kind = site_->PointsToLiteral()
? site_->boilerplate()->GetElementsKind()
: site_->GetElementsKind();
return kind_ == kind;
}
void Install(Isolate* isolate, Handle<WeakCell> code) override {
DCHECK(IsValid());
InstallDependency(isolate, code, site_,
DependentCode::kAllocationSiteTransitionChangedGroup);
}
private:
Handle<AllocationSite> site_;
ElementsKind kind_;
};
Handle<Map> CompilationDependencies::DependOnInitialMap(
Handle<JSFunction> function) {
Handle<Map> map(function->initial_map(), function->GetIsolate());
dependencies_.push_front(new (zone_) InitialMapDependency(function, map));
return map;
}
void CompilationDependencies::DependOnStableMap(Handle<Map> map) {
if (map->CanTransition()) {
dependencies_.push_front(new (zone_) StableMapDependency(map));
} else {
DCHECK(map->is_stable());
// 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::DependOnTransition(Handle<Map> target_map) {
if (target_map->CanBeDeprecated()) {
dependencies_.push_front(new (zone_) TransitionDependency(target_map));
} else {
DCHECK(!target_map->is_deprecated());
}
}
PretenureFlag CompilationDependencies::DependOnPretenureMode(
Handle<AllocationSite> site) {
PretenureFlag mode = site->GetPretenureMode();
dependencies_.push_front(new (zone_) PretenureModeDependency(site, mode));
return mode;
}
void CompilationDependencies::DependOnFieldType(Handle<Map> map,
int descriptor) {
Handle<Map> owner(map->FindFieldOwner(isolate_, descriptor), isolate_);
DCHECK_EQ(descriptor, owner->LastAdded());
Handle<FieldType> type(
owner->instance_descriptors()->GetFieldType(descriptor), isolate_);
DCHECK_EQ(*type, map->instance_descriptors()->GetFieldType(descriptor));
dependencies_.push_front(new (zone_)
FieldTypeDependency(isolate_, owner, type));
}
void CompilationDependencies::DependOnFieldType(const LookupIterator* it) {
Handle<Map> owner = it->GetFieldOwnerMap();
int descriptor = it->GetFieldDescriptorIndex();
DCHECK_EQ(descriptor, owner->LastAdded());
Handle<FieldType> type = it->GetFieldType();
CHECK_EQ(*type,
it->GetHolder<Map>()->map()->instance_descriptors()->GetFieldType(
descriptor));
dependencies_.push_front(new (zone_)
FieldTypeDependency(isolate_, owner, type));
}
void CompilationDependencies::DependOnGlobalProperty(
Handle<PropertyCell> cell) {
PropertyCellType type = cell->property_details().cell_type();
bool read_only = cell->property_details().IsReadOnly();
dependencies_.push_front(new (zone_)
GlobalPropertyDependency(cell, type, read_only));
}
void CompilationDependencies::DependOnProtector(Handle<PropertyCell> cell) {
dependencies_.push_front(new (zone_) ProtectorDependency(cell));
}
void CompilationDependencies::DependOnElementsKind(
Handle<AllocationSite> site) {
// Do nothing if the object doesn't have any useful element transitions left.
ElementsKind kind = site->PointsToLiteral()
? site->boilerplate()->GetElementsKind()
: site->GetElementsKind();
if (AllocationSite::ShouldTrack(kind)) {
dependencies_.push_front(new (zone_) ElementsKindDependency(site, kind));
}
}
bool CompilationDependencies::AreValid() const {
for (auto dep : dependencies_) {
if (!dep->IsValid()) return false;
}
return true;
}
bool CompilationDependencies::Commit(Handle<Code> code) {
// Check validity of all dependencies first, such that we can abort before
// installing anything.
if (!AreValid()) {
dependencies_.clear();
return false;
}
void CompilationDependencies::Commit(Handle<Code> code) {
if (IsEmpty()) return;
DCHECK(!object_wrapper_.is_null());
Handle<WeakCell> cell = Code::WeakCellFor(code);
for (auto dep : dependencies_) {
dep->Install(isolate_, cell);
AllowDeferredHandleDereference get_wrapper;
for (int i = 0; i < DependentCode::kGroupCount; i++) {
ZoneVector<Handle<HeapObject>>* group_objects = groups_[i];
if (group_objects == nullptr) continue;
DependentCode::DependencyGroup group =
static_cast<DependentCode::DependencyGroup>(i);
for (size_t j = 0; j < group_objects->size(); 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.
}
dependencies_.clear();
return true;
}
namespace {
void DependOnStablePrototypeChain(CompilationDependencies* deps,
Handle<Map> map,
MaybeHandle<JSReceiver> last_prototype) {
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++) {
ZoneVector<Handle<HeapObject>>* group_objects = groups_[i];
if (group_objects == nullptr) continue;
DependentCode::DependencyGroup group =
static_cast<DependentCode::DependencyGroup>(i);
for (size_t j = 0; j < group_objects->size(); 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::AssumeMapNotDeprecated(Handle<Map> map) {
DCHECK(!map->is_deprecated());
// Do nothing if the map cannot be deprecated.
if (map->CanBeDeprecated()) {
Insert(DependentCode::kTransitionGroup, map);
}
}
void CompilationDependencies::AssumeMapStable(Handle<Map> map) {
DCHECK(map->is_stable());
// Do nothing if the map cannot transition.
if (map->CanTransition()) {
Insert(DependentCode::kPrototypeCheckGroup, 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);
deps->DependOnStableMap(handle(current->map(), current->GetIsolate()));
AssumeMapStable(handle(current->map(), isolate_));
Handle<JSReceiver> last;
if (last_prototype.ToHandle(&last) && last.is_identical_to(current)) {
if (prototype.ToHandle(&last) && last.is_identical_to(current)) {
break;
}
}
}
} // namespace
void CompilationDependencies::DependOnStablePrototypeChains(
void CompilationDependencies::AssumePrototypesStable(
Handle<Context> native_context,
std::vector<Handle<Map>> const& receiver_maps, Handle<JSObject> holder) {
// Determine actual holder and perform prototype chain checks.
@ -370,20 +147,21 @@ void CompilationDependencies::DependOnStablePrototypeChains(
Handle<JSFunction> constructor;
if (Map::GetConstructorFunction(map, native_context)
.ToHandle(&constructor)) {
map = handle(constructor->initial_map(), isolate_);
map = handle(constructor->initial_map(), holder->GetIsolate());
}
DependOnStablePrototypeChain(this, map, holder);
AssumePrototypeMapsStable(map, holder);
}
}
void CompilationDependencies::DependOnElementsKinds(
void CompilationDependencies::AssumeTransitionStable(
Handle<AllocationSite> site) {
while (true) {
DependOnElementsKind(site);
if (!site->nested_site()->IsAllocationSite()) break;
site = handle(AllocationSite::cast(site->nested_site()), isolate_);
// Do nothing if the object doesn't have any useful element transitions left.
ElementsKind kind = site->PointsToLiteral()
? site->boilerplate()->GetElementsKind()
: site->GetElementsKind();
if (AllocationSite::ShouldTrack(kind)) {
Insert(DependentCode::kAllocationSiteTransitionChangedGroup, site);
}
CHECK_EQ(site->nested_site(), Smi::kZero);
}
} // namespace internal

View File

@ -5,70 +5,75 @@
#ifndef V8_COMPILATION_DEPENDENCIES_H_
#define V8_COMPILATION_DEPENDENCIES_H_
#include "src/handles.h"
#include "src/objects.h"
#include "src/objects/map.h"
#include "src/zone/zone-containers.h"
namespace v8 {
namespace internal {
// Collects and installs dependencies of the code that is being generated.
// Collects dependencies for this compilation, e.g. assumptions about
// stable maps, constant globals, etc.
class V8_EXPORT_PRIVATE CompilationDependencies {
public:
CompilationDependencies(Isolate* isolate, Zone* zone);
CompilationDependencies(Isolate* isolate, Zone* zone)
: isolate_(isolate),
zone_(zone),
object_wrapper_(Handle<Foreign>::null()),
aborted_(false) {
std::fill_n(groups_, DependentCode::kGroupCount, nullptr);
}
V8_WARN_UNUSED_RESULT bool Commit(Handle<Code> code);
void Insert(DependentCode::DependencyGroup group, Handle<HeapObject> handle);
// Return the initial map of {function} and record the assumption that it
// stays the intial map.
Handle<Map> DependOnInitialMap(Handle<JSFunction> function);
void AssumeInitialMapCantChange(Handle<Map> map) {
Insert(DependentCode::kInitialMapChangedGroup, map);
}
void AssumeFieldOwner(Handle<Map> map) {
Insert(DependentCode::kFieldOwnerGroup, map);
}
void AssumeMapStable(Handle<Map> map);
void AssumePrototypeMapsStable(
Handle<Map> map,
MaybeHandle<JSReceiver> prototype = MaybeHandle<JSReceiver>());
void AssumeMapNotDeprecated(Handle<Map> map);
void AssumePropertyCell(Handle<PropertyCell> cell) {
Insert(DependentCode::kPropertyCellChangedGroup, cell);
}
void AssumeTenuringDecision(Handle<AllocationSite> site) {
Insert(DependentCode::kAllocationSiteTenuringChangedGroup, site);
}
void AssumeTransitionStable(Handle<AllocationSite> site);
// Record the assumption that {map} stays stable.
void DependOnStableMap(Handle<Map> map);
// Record the assumption that {target_map} can be transitioned to, i.e., that
// it does not become deprecated.
void DependOnTransition(Handle<Map> target_map);
// Return the pretenure mode of {site} and record the assumption that it does
// not change.
PretenureFlag DependOnPretenureMode(Handle<AllocationSite> site);
// Record the assumption that the field type of a field does not change. The
// field is identified by the argument(s).
void DependOnFieldType(Handle<Map> map, int descriptor);
void DependOnFieldType(const LookupIterator* it);
// Record the assumption that neither {cell}'s {CellType} changes, nor the
// {IsReadOnly()} flag of {cell}'s {PropertyDetails}.
void DependOnGlobalProperty(Handle<PropertyCell> cell);
// Record the assumption that the protector remains valid.
void DependOnProtector(Handle<PropertyCell> cell);
// Record the assumption that {site}'s {ElementsKind} doesn't change.
void DependOnElementsKind(Handle<AllocationSite> site);
// Depend on the stability of (the maps of) all prototypes of every class in
// Adds stability dependencies on all prototypes of every class in
// {receiver_type} up to (and including) the {holder}.
void DependOnStablePrototypeChains(
Handle<Context> native_context,
std::vector<Handle<Map>> const& receiver_maps, Handle<JSObject> holder);
void AssumePrototypesStable(Handle<Context> native_context,
std::vector<Handle<Map>> const& receiver_maps,
Handle<JSObject> holder);
// Like DependOnElementsKind but also applies to all nested allocation sites.
void DependOnElementsKinds(Handle<AllocationSite> site);
void Commit(Handle<Code> code);
void Rollback();
void Abort() { aborted_ = true; }
bool HasAborted() const { return aborted_; }
// Exposed only for testing purposes.
bool AreValid() const;
// Exposed only because C++.
class Dependency;
bool IsEmpty() const {
for (int i = 0; i < DependentCode::kGroupCount; i++) {
if (groups_[i]) return false;
}
return true;
}
private:
Isolate* isolate_;
Zone* zone_;
ZoneForwardList<Dependency*> dependencies_;
};
Handle<Foreign> object_wrapper_;
bool aborted_;
ZoneVector<Handle<HeapObject> >* groups_[DependentCode::kGroupCount];
DependentCode* Get(Handle<Object> object) const;
void Set(Handle<Object> object, Handle<DependentCode> dep);
};
} // namespace internal
} // namespace v8

View File

@ -227,6 +227,8 @@ CompilationJob::Status OptimizedCompilationJob::FinalizeJob(Isolate* isolate) {
DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
DisallowCodeDependencyChange no_dependency_change;
DisallowJavascriptExecution no_js(isolate);
CHECK(!compilation_info()->dependencies() ||
!compilation_info()->dependencies()->HasAborted());
// Delegate to the underlying implementation.
DCHECK_EQ(state(), State::kReadyToFinalize);
@ -800,6 +802,8 @@ CompilationJob::Status FinalizeOptimizedCompilationJob(
if (job->state() == CompilationJob::State::kReadyToFinalize) {
if (shared->optimization_disabled()) {
job->RetryOptimization(BailoutReason::kOptimizationDisabled);
} else if (compilation_info->dependencies()->HasAborted()) {
job->RetryOptimization(BailoutReason::kBailedOutDueToDependencyChange);
} else if (job->FinalizeJob(isolate) == CompilationJob::SUCCEEDED) {
job->RecordCompilationStats();
job->RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,

View File

@ -395,7 +395,11 @@ bool AccessInfoFactory::ComputePropertyAccessInfo(
// The field type was cleared by the GC, so we don't know anything
// about the contents now.
} else if (descriptors_field_type->IsClass()) {
dependencies()->DependOnFieldType(map, number);
// Add proper code dependencies in case of stable field map(s).
Handle<Map> field_owner_map(
map->FindFieldOwner(isolate(), number), isolate());
dependencies()->AssumeFieldOwner(field_owner_map);
// Remember the field map, and try to infer a useful type.
field_type = Type::For(js_heap_broker(),
descriptors_field_type->AsClass());
@ -697,14 +701,18 @@ bool AccessInfoFactory::LookupTransition(Handle<Map> map, Handle<Name> name,
// Store is not safe if the field type was cleared.
return false;
} else if (descriptors_field_type->IsClass()) {
dependencies()->DependOnFieldType(transition_map, number);
// Add proper code dependencies in case of stable field map(s).
Handle<Map> field_owner_map(
transition_map->FindFieldOwner(isolate(), number), isolate());
dependencies()->AssumeFieldOwner(field_owner_map);
// Remember the field map, and try to infer a useful type.
field_type =
Type::For(js_heap_broker(), descriptors_field_type->AsClass());
field_map = descriptors_field_type->AsClass();
}
}
dependencies()->DependOnTransition(transition_map);
dependencies()->AssumeMapNotDeprecated(transition_map);
// Transitioning stores are never stores to constant fields.
*access_info = PropertyAccessInfo::DataField(
PropertyConstness::kMutable, MapHandles{map}, field_index,

View File

@ -594,7 +594,7 @@ Reduction JSCallReducer::ReduceObjectGetPrototype(Node* node, Node* object) {
}
if (result == NodeProperties::kUnreliableReceiverMaps) {
for (size_t i = 0; i < object_maps.size(); ++i) {
dependencies()->DependOnStableMap(object_maps[i]);
dependencies()->AssumeMapStable(object_maps[i]);
}
}
Node* value = jsgraph()->Constant(candidate_prototype);
@ -1050,7 +1050,7 @@ Reduction JSCallReducer::ReduceArrayForEach(Node* node,
// Install code dependencies on the {receiver} prototype maps and the
// global array protector cell.
dependencies()->DependOnProtector(factory()->no_elements_protector());
dependencies()->AssumePropertyCell(factory()->no_elements_protector());
// If we have unreliable maps, we need a map check.
if (result == NodeProperties::kUnreliableReceiverMaps) {
@ -1234,7 +1234,7 @@ Reduction JSCallReducer::ReduceArrayReduce(Node* node,
// Install code dependencies on the {receiver} prototype maps and the
// global array protector cell.
dependencies()->DependOnProtector(factory()->no_elements_protector());
dependencies()->AssumePropertyCell(factory()->no_elements_protector());
// If we have unreliable maps, we need a map check.
if (result == NodeProperties::kUnreliableReceiverMaps) {
@ -1504,7 +1504,7 @@ Reduction JSCallReducer::ReduceArrayMap(Node* node,
if (receiver_map->elements_kind() != kind) return NoChange();
}
dependencies()->DependOnProtector(factory()->array_species_protector());
dependencies()->AssumePropertyCell(factory()->array_species_protector());
Handle<JSFunction> handle_constructor(
JSFunction::cast(
@ -1711,7 +1711,7 @@ Reduction JSCallReducer::ReduceArrayFilter(Node* node,
if (receiver_map->elements_kind() != kind) return NoChange();
}
dependencies()->DependOnProtector(factory()->array_species_protector());
dependencies()->AssumePropertyCell(factory()->array_species_protector());
Handle<Map> initial_map(
Map::cast(native_context()->GetInitialJSArrayMap(packed_kind)),
@ -1988,7 +1988,7 @@ Reduction JSCallReducer::ReduceArrayFind(Node* node, ArrayFindVariant variant,
// Install code dependencies on the {receiver} prototype maps and the
// global array protector cell.
dependencies()->DependOnProtector(factory()->no_elements_protector());
dependencies()->AssumePropertyCell(factory()->no_elements_protector());
// If we have unreliable maps, we need a map check.
if (result == NodeProperties::kUnreliableReceiverMaps) {
@ -2303,7 +2303,7 @@ Reduction JSCallReducer::ReduceArrayEvery(Node* node,
if (receiver_map->elements_kind() != kind) return NoChange();
}
dependencies()->DependOnProtector(factory()->array_species_protector());
dependencies()->AssumePropertyCell(factory()->array_species_protector());
// If we have unreliable maps, we need a map check.
if (result == NodeProperties::kUnreliableReceiverMaps) {
@ -2643,7 +2643,7 @@ Reduction JSCallReducer::ReduceArraySome(Node* node,
if (receiver_map->elements_kind() != kind) return NoChange();
}
dependencies()->DependOnProtector(factory()->array_species_protector());
dependencies()->AssumePropertyCell(factory()->array_species_protector());
Node* k = jsgraph()->ZeroConstant();
@ -2891,7 +2891,7 @@ Reduction JSCallReducer::ReduceCallApiFunction(
// Install stability dependencies for unreliable {receiver_maps}.
if (result == NodeProperties::kUnreliableReceiverMaps) {
for (size_t i = 0; i < receiver_maps.size(); ++i) {
dependencies()->DependOnStableMap(receiver_maps[i]);
dependencies()->AssumeMapStable(receiver_maps[i]);
}
}
@ -3061,7 +3061,7 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
// that no one messed with the %ArrayIteratorPrototype%.next method.
if (node->opcode() == IrOpcode::kJSCallWithSpread ||
node->opcode() == IrOpcode::kJSConstructWithSpread) {
dependencies()->DependOnProtector(factory()->array_iterator_protector());
dependencies()->AssumePropertyCell(factory()->array_iterator_protector());
}
// Remove the {arguments_list} input from the {node}.
@ -4295,7 +4295,7 @@ Reduction JSCallReducer::ReduceArrayPrototypePush(Node* node) {
}
// Install code dependencies on the {receiver} global array protector cell.
dependencies()->DependOnProtector(factory()->no_elements_protector());
dependencies()->AssumePropertyCell(factory()->no_elements_protector());
// If the {receiver_maps} information is not reliable, we need
// to check that the {receiver} still has one of these maps.
@ -4409,7 +4409,7 @@ Reduction JSCallReducer::ReduceArrayPrototypePop(Node* node) {
}
// Install code dependencies on the {receiver} global array protector cell.
dependencies()->DependOnProtector(factory()->no_elements_protector());
dependencies()->AssumePropertyCell(factory()->no_elements_protector());
// If the {receiver_maps} information is not reliable, we need
// to check that the {receiver} still has one of these maps.
@ -4527,7 +4527,7 @@ Reduction JSCallReducer::ReduceArrayPrototypeShift(Node* node) {
}
// Install code dependencies on the {receiver} global array protector cell.
dependencies()->DependOnProtector(factory()->no_elements_protector());
dependencies()->AssumePropertyCell(factory()->no_elements_protector());
// If the {receiver_maps} information is not reliable, we need
// to check that the {receiver} still has one of these maps.
@ -4808,7 +4808,7 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
// Install code dependency on the array protector for holey arrays.
if (IsHoleyElementsKind(elements_kind)) {
dependencies()->DependOnProtector(factory()->no_elements_protector());
dependencies()->AssumePropertyCell(factory()->no_elements_protector());
}
// Load the (current) {iterated_object} from the {iterator}; this might be
@ -4832,7 +4832,7 @@ Reduction JSCallReducer::ReduceArrayIteratorPrototypeNext(Node* node) {
if (isolate()->IsArrayBufferNeuteringIntact()) {
// Add a code dependency so we are deoptimized in case an ArrayBuffer
// gets neutered.
dependencies()->DependOnProtector(
dependencies()->AssumePropertyCell(
factory()->array_buffer_neutering_protector());
} else {
// Deoptimize if the array buffer was neutered.
@ -5318,7 +5318,7 @@ Reduction JSCallReducer::ReduceAsyncFunctionPromiseCreate(Node* node) {
if (!isolate()->IsPromiseHookProtectorIntact()) return NoChange();
// Install a code dependency on the promise hook protector cell.
dependencies()->DependOnProtector(factory()->promise_hook_protector());
dependencies()->AssumePropertyCell(factory()->promise_hook_protector());
// Morph this {node} into a JSCreatePromise node.
RelaxControls(node);
@ -5333,7 +5333,8 @@ Reduction JSCallReducer::ReduceAsyncFunctionPromiseRelease(Node* node) {
DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
if (!isolate()->IsPromiseHookProtectorIntact()) return NoChange();
dependencies()->DependOnProtector(factory()->promise_hook_protector());
// Install a code dependency on the promise hook protector cell.
dependencies()->AssumePropertyCell(factory()->promise_hook_protector());
// The AsyncFunctionPromiseRelease builtin is a no-op as long as neither
// the debugger is active nor any promise hook has been installed (ever).
@ -5502,7 +5503,8 @@ Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
// Only handle builtins Promises, not subclasses.
if (target != new_target) return NoChange();
dependencies()->DependOnProtector(factory()->promise_hook_protector());
// Add a code dependency on the promise hook protector.
dependencies()->AssumePropertyCell(factory()->promise_hook_protector());
Handle<SharedFunctionInfo> promise_shared(
handle(native_context()->promise_function()->shared(), isolate()));
@ -5655,7 +5657,8 @@ Reduction JSCallReducer::ReducePromiseInternalConstructor(Node* node) {
// Check that promises aren't being observed through (debug) hooks.
if (!isolate()->IsPromiseHookProtectorIntact()) return NoChange();
dependencies()->DependOnProtector(factory()->promise_hook_protector());
// Install a code dependency on the promise hook protector cell.
dependencies()->AssumePropertyCell(factory()->promise_hook_protector());
// Create a new pending promise.
Node* value = effect =
@ -5747,7 +5750,8 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
}
}
dependencies()->DependOnProtector(factory()->promise_then_protector());
// Add a code dependency on the necessary protectors.
dependencies()->AssumePropertyCell(factory()->promise_then_protector());
// If the {receiver_maps} aren't reliable, we need to repeat the
// map check here, guarded by the CALL_IC.
@ -5823,9 +5827,10 @@ Reduction JSCallReducer::ReducePromisePrototypeFinally(Node* node) {
}
}
dependencies()->DependOnProtector(factory()->promise_hook_protector());
dependencies()->DependOnProtector(factory()->promise_then_protector());
dependencies()->DependOnProtector(factory()->promise_species_protector());
// Add a code dependency on the necessary protectors.
dependencies()->AssumePropertyCell(factory()->promise_hook_protector());
dependencies()->AssumePropertyCell(factory()->promise_then_protector());
dependencies()->AssumePropertyCell(factory()->promise_species_protector());
// If the {receiver_maps} aren't reliable, we need to repeat the
// map check here, guarded by the CALL_IC.
@ -5975,8 +5980,9 @@ Reduction JSCallReducer::ReducePromisePrototypeThen(Node* node) {
}
}
dependencies()->DependOnProtector(factory()->promise_hook_protector());
dependencies()->DependOnProtector(factory()->promise_species_protector());
// Add a code dependency on the necessary protectors.
dependencies()->AssumePropertyCell(factory()->promise_hook_protector());
dependencies()->AssumePropertyCell(factory()->promise_species_protector());
// If the {receiver_maps} aren't reliable, we need to repeat the
// map check here, guarded by the CALL_IC.
@ -6653,7 +6659,7 @@ Reduction JSCallReducer::ReduceArrayBufferViewAccessor(
if (isolate()->IsArrayBufferNeuteringIntact()) {
// Add a code dependency so we are deoptimized in case an ArrayBuffer
// gets neutered.
dependencies()->DependOnProtector(
dependencies()->AssumePropertyCell(
factory()->array_buffer_neutering_protector());
} else {
// Check if the {receiver}s buffer was neutered.
@ -6997,8 +7003,8 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
// Add proper dependencies on the {regexp}s [[Prototype]]s.
Handle<JSObject> holder;
if (ai_exec.holder().ToHandle(&holder)) {
dependencies()->DependOnStablePrototypeChains(
native_context(), ai_exec.receiver_maps(), holder);
dependencies()->AssumePrototypesStable(native_context(),
ai_exec.receiver_maps(), holder);
}
if (need_map_check) {

View File

@ -133,12 +133,12 @@ Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
// Force completion of inobject slack tracking before
// generating code to finalize the instance size.
original_constructor->CompleteInobjectSlackTrackingIfActive();
Handle<Map> initial_map(original_constructor->initial_map(), isolate());
int const instance_size = initial_map->instance_size();
// Add a dependency on the {initial_map} to make sure that this code is
// deoptimized whenever the {initial_map} changes.
Handle<Map> initial_map =
dependencies()->DependOnInitialMap(original_constructor);
int const instance_size = initial_map->instance_size();
dependencies()->AssumeInitialMapCantChange(initial_map);
// Emit code to allocate the JSObject instance for the
// {original_constructor}.
@ -425,12 +425,13 @@ Reduction JSCreateLowering::ReduceJSCreateGeneratorObject(Node* node) {
// Force completion of inobject slack tracking before
// generating code to finalize the instance size.
js_function->CompleteInobjectSlackTrackingIfActive();
Handle<Map> initial_map(js_function->initial_map(), isolate());
DCHECK(initial_map->instance_type() == JS_GENERATOR_OBJECT_TYPE ||
initial_map->instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE);
// Add a dependency on the {initial_map} to make sure that this code is
// deoptimized whenever the {initial_map} changes.
Handle<Map> initial_map = dependencies()->DependOnInitialMap(js_function);
DCHECK(initial_map->instance_type() == JS_GENERATOR_OBJECT_TYPE ||
initial_map->instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE);
dependencies()->AssumeInitialMapCantChange(initial_map);
// Allocate a register file.
DCHECK(js_function->shared()->HasBytecodeArray());
@ -724,11 +725,11 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
// Force completion of inobject slack tracking before
// generating code to finalize the instance size.
original_constructor->CompleteInobjectSlackTrackingIfActive();
Handle<Map> initial_map(original_constructor->initial_map(), isolate());
// Add a dependency on the {initial_map} to make sure that this code is
// deoptimized whenever the {initial_map} changes.
Handle<Map> initial_map =
dependencies()->DependOnInitialMap(original_constructor);
dependencies()->AssumeInitialMapCantChange(initial_map);
// Tells whether we are protected by either the {site} or a
// protector cell to do certain speculative optimizations.
@ -742,8 +743,10 @@ Reduction JSCreateLowering::ReduceJSCreateArray(Node* node) {
Map::AsElementsKind(isolate(), initial_map, elements_kind);
}
can_inline_call = site->CanInlineCall();
pretenure = dependencies()->DependOnPretenureMode(site);
dependencies()->DependOnElementsKind(site);
pretenure = site->GetPretenureMode();
dependencies()->AssumeTransitionStable(site);
dependencies()->AssumeTenuringDecision(site);
} else {
can_inline_call = isolate()->IsArrayConstructorIntact();
}
@ -1133,6 +1136,17 @@ Reduction JSCreateLowering::ReduceJSCreatePromise(Node* node) {
return Changed(node);
}
void AssumeAllocationSiteTransitionDeepDependencies(
CompilationDependencies* dependencies, Isolate* isolate,
Handle<AllocationSite> site) {
while (true) {
dependencies->AssumeTransitionStable(site);
if (!site->nested_site()->IsAllocationSite()) break;
site = handle(AllocationSite::cast(site->nested_site()), isolate);
}
CHECK_EQ(site->nested_site(), Smi::kZero);
}
Reduction JSCreateLowering::ReduceJSCreateLiteralArrayOrObject(Node* node) {
DCHECK(node->opcode() == IrOpcode::kJSCreateLiteralArray ||
node->opcode() == IrOpcode::kJSCreateLiteralObject);
@ -1148,11 +1162,12 @@ Reduction JSCreateLowering::ReduceJSCreateLiteralArrayOrObject(Node* node) {
if (site.IsFastLiteral(js_heap_broker())) {
PretenureFlag pretenure = NOT_TENURED;
if (FLAG_allocation_site_pretenuring) {
pretenure = dependencies()->DependOnPretenureMode(
site.object<AllocationSite>());
pretenure = site.GetPretenureMode();
dependencies()->AssumeTenuringDecision(site.object<AllocationSite>());
}
dependencies()->DependOnElementsKinds(site.object<AllocationSite>());
JSObjectRef boilerplate = site.boilerplate(js_heap_broker());
AssumeAllocationSiteTransitionDeepDependencies(
dependencies(), isolate(), site.object<AllocationSite>());
Node* value = effect =
AllocateFastLiteral(effect, control, boilerplate, pretenure);
ReplaceWithValue(node, value, effect, control);
@ -1173,8 +1188,9 @@ Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralArray(Node* node) {
Handle<Map> const initial_map(
native_context()->GetInitialJSArrayMap(site->GetElementsKind()),
isolate());
PretenureFlag const pretenure = dependencies()->DependOnPretenureMode(site);
dependencies()->DependOnElementsKind(site);
PretenureFlag const pretenure = site->GetPretenureMode();
dependencies()->AssumeTransitionStable(site);
dependencies()->AssumeTenuringDecision(site);
Node* length = jsgraph()->ZeroConstant();
return ReduceNewArray(node, length, 0, initial_map, pretenure);
}

View File

@ -155,7 +155,7 @@ Reduction JSNativeContextSpecialization::ReduceJSGetSuperConstructor(
// {function}s map is stable, i.e. we can use a code dependency
// to guard against [[Prototype]] changes of {function}.
if (function_map->is_stable() && function_prototype->IsConstructor()) {
dependencies()->DependOnStableMap(function_map);
dependencies()->AssumeMapStable(function_map);
Node* value = jsgraph()->Constant(function_prototype);
ReplaceWithValue(node, value);
return Replace(value);
@ -208,7 +208,7 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
// Determine actual holder and perform prototype chain checks.
Handle<JSObject> holder;
if (access_info.holder().ToHandle(&holder)) {
dependencies()->DependOnStablePrototypeChains(
dependencies()->AssumePrototypesStable(
native_context().object<Context>(), access_info.receiver_maps(),
holder);
}
@ -234,9 +234,9 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
// Determine actual holder and perform prototype chain checks.
Handle<JSObject> holder;
if (access_info.holder().ToHandle(&holder)) {
dependencies()->DependOnStablePrototypeChains(
native_context().object<Context>(), access_info.receiver_maps(),
holder);
dependencies()->AssumePrototypesStable(native_context().object<Context>(),
access_info.receiver_maps(),
holder);
} else {
holder = receiver;
}
@ -411,7 +411,9 @@ Reduction JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance(
// depend on that for the prototype constant-folding below.
JSFunction::EnsureHasInitialMap(function);
Handle<Map> initial_map = dependencies()->DependOnInitialMap(function);
// Install a code dependency on the {function}s initial map.
Handle<Map> initial_map(function->initial_map(), isolate());
dependencies()->AssumeInitialMapCantChange(initial_map);
Node* prototype =
jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
@ -500,9 +502,8 @@ Reduction JSNativeContextSpecialization::ReduceJSResolvePromise(Node* node) {
// Add proper dependencies on the {resolution}s [[Prototype]]s.
Handle<JSObject> holder;
if (access_info.holder().ToHandle(&holder)) {
dependencies()->DependOnStablePrototypeChains(
native_context().object<Context>(), access_info.receiver_maps(),
holder);
dependencies()->AssumePrototypesStable(native_context().object<Context>(),
access_info.receiver_maps(), holder);
}
// Simply fulfill the {promise} with the {resolution}.
@ -608,7 +609,7 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
// can be deleted or reconfigured to an accessor property).
if (property_details.cell_type() != PropertyCellType::kMutable ||
property_details.IsConfigurable()) {
dependencies()->DependOnGlobalProperty(property_cell);
dependencies()->AssumePropertyCell(property_cell);
}
// Load from constant/undefined global property can be constant-folded.
@ -640,7 +641,7 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
// elimination if it's stable, i.e. the HeapObject wasn't
// mutated without the cell state being updated.
if (property_cell_value_map->is_stable()) {
dependencies()->DependOnStableMap(property_cell_value_map);
dependencies()->AssumeMapStable(property_cell_value_map);
map = property_cell_value_map;
}
}
@ -662,7 +663,7 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
case PropertyCellType::kConstant: {
// Record a code dependency on the cell, and just deoptimize if the new
// value doesn't match the previous value stored inside the cell.
dependencies()->DependOnGlobalProperty(property_cell);
dependencies()->AssumePropertyCell(property_cell);
Node* check =
graph()->NewNode(simplified()->ReferenceEqual(), value,
jsgraph()->Constant(property_cell_value));
@ -675,7 +676,7 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
// Record a code dependency on the cell, and just deoptimize if the new
// values' type doesn't match the type of the previous value in the
// cell.
dependencies()->DependOnGlobalProperty(property_cell);
dependencies()->AssumePropertyCell(property_cell);
Type property_cell_value_type;
MachineRepresentation representation = MachineRepresentation::kTagged;
if (property_cell_value->IsHeapObject()) {
@ -684,7 +685,7 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
Handle<Map> property_cell_value_map(
Handle<HeapObject>::cast(property_cell_value)->map(), isolate());
DCHECK(property_cell_value_map->is_stable());
dependencies()->DependOnStableMap(property_cell_value_map);
dependencies()->AssumeMapStable(property_cell_value_map);
// Check that the {value} is a HeapObject.
value = effect = graph()->NewNode(simplified()->CheckHeapObject(),
@ -715,7 +716,7 @@ Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
case PropertyCellType::kMutable: {
// Record a code dependency on the cell, and just deoptimize if the
// property ever becomes read-only.
dependencies()->DependOnGlobalProperty(property_cell);
dependencies()->AssumePropertyCell(property_cell);
effect = graph()->NewNode(
simplified()->StoreField(ForPropertyCellValue(
MachineRepresentation::kTagged, Type::NonInternal(),
@ -1096,7 +1097,8 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
// {function} in order to be notified about changes to the
// "prototype" of {function}.
JSFunction::EnsureHasInitialMap(function);
dependencies()->DependOnInitialMap(function);
Handle<Map> initial_map(function->initial_map(), isolate());
dependencies()->AssumeInitialMapCantChange(initial_map);
Handle<Object> prototype(function->prototype(), isolate());
Node* value = jsgraph()->Constant(prototype);
ReplaceWithValue(node, value);
@ -1230,7 +1232,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
// Install dependencies on the relevant prototype maps.
for (Handle<Map> prototype_map : prototype_maps) {
dependencies()->DependOnStableMap(prototype_map);
dependencies()->AssumeMapStable(prototype_map);
}
}
@ -1800,9 +1802,8 @@ JSNativeContextSpecialization::BuildPropertyLoad(
Handle<JSObject> holder;
PropertyAccessBuilder access_builder(jsgraph(), dependencies());
if (access_info.holder().ToHandle(&holder)) {
dependencies()->DependOnStablePrototypeChains(
native_context().object<Context>(), access_info.receiver_maps(),
holder);
dependencies()->AssumePrototypesStable(native_context().object<Context>(),
access_info.receiver_maps(), holder);
}
// Generate the actual property access.
@ -1858,9 +1859,8 @@ JSNativeContextSpecialization::BuildPropertyStore(
PropertyAccessBuilder access_builder(jsgraph(), dependencies());
if (access_info.holder().ToHandle(&holder)) {
DCHECK_NE(AccessMode::kStoreInLiteral, access_mode);
dependencies()->DependOnStablePrototypeChains(
native_context().object<Context>(), access_info.receiver_maps(),
holder);
dependencies()->AssumePrototypesStable(native_context().object<Context>(),
access_info.receiver_maps(), holder);
}
DCHECK(!access_info.IsNotFound());
@ -2258,7 +2258,7 @@ JSNativeContextSpecialization::BuildElementAccess(
if (isolate()->IsArrayBufferNeuteringIntact()) {
// Add a code dependency so we are deoptimized in case an ArrayBuffer
// gets neutered.
dependencies()->DependOnProtector(
dependencies()->AssumePropertyCell(
factory()->array_buffer_neutering_protector());
} else {
// Default to zero if the {receiver}s buffer was neutered.
@ -2661,7 +2661,8 @@ Node* JSNativeContextSpecialization::BuildIndexedStringLoad(
KeyedAccessLoadMode load_mode) {
if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS &&
isolate()->IsNoElementsProtectorIntact()) {
dependencies()->DependOnProtector(factory()->no_elements_protector());
// Add a code dependency on the "no elements" protector.
dependencies()->AssumePropertyCell(factory()->no_elements_protector());
// Ensure that the {index} is a valid String length.
index = *effect = graph()->NewNode(
@ -2810,7 +2811,8 @@ bool JSNativeContextSpecialization::CanTreatHoleAsUndefined(
// Check if the array prototype chain is intact.
if (!isolate()->IsNoElementsProtectorIntact()) return false;
dependencies()->DependOnProtector(factory()->no_elements_protector());
// Install code dependency on the array protector cell.
dependencies()->AssumePropertyCell(factory()->no_elements_protector());
return true;
}

View File

@ -918,9 +918,7 @@ PipelineCompilationJob::Status PipelineCompilationJob::FinalizeJobImpl(
}
return FAILED;
}
if (!compilation_info()->dependencies()->Commit(code)) {
return AbortOptimization(BailoutReason::kBailedOutDueToDependencyChange);
}
compilation_info()->dependencies()->Commit(code);
compilation_info()->SetCode(code);
compilation_info()->context()->native_context()->AddOptimizedCode(*code);

View File

@ -136,7 +136,7 @@ void PropertyAccessBuilder::BuildCheckMaps(
if (receiver_map->is_stable()) {
for (Handle<Map> map : receiver_maps) {
if (map.is_identical_to(receiver_map)) {
dependencies()->DependOnStableMap(receiver_map);
dependencies()->AssumeMapStable(receiver_map);
return;
}
}
@ -195,17 +195,18 @@ Node* PropertyAccessBuilder::TryBuildLoadConstantDataField(
// but for now let's just do what Crankshaft does.
LookupIterator it(m.Value(), name, LookupIterator::OWN_SKIP_INTERCEPTOR);
if (it.state() == LookupIterator::DATA) {
bool is_readonly_non_configurable =
bool is_reaonly_non_configurable =
it.IsReadOnly() && !it.IsConfigurable();
if (is_readonly_non_configurable ||
if (is_reaonly_non_configurable ||
(FLAG_track_constant_fields && access_info.IsDataConstantField())) {
Node* value = jsgraph()->Constant(JSReceiver::GetDataProperty(&it));
if (!is_readonly_non_configurable) {
if (!is_reaonly_non_configurable) {
// It's necessary to add dependency on the map that introduced
// the field.
DCHECK(access_info.IsDataConstantField());
DCHECK(!it.is_dictionary_holder());
dependencies()->DependOnFieldType(&it);
Handle<Map> field_owner_map = it.GetFieldOwnerMap();
dependencies()->AssumeFieldOwner(field_owner_map);
}
return value;
}
@ -263,7 +264,7 @@ Node* PropertyAccessBuilder::BuildLoadDataField(
Handle<Map> field_map;
if (access_info.field_map().ToHandle(&field_map)) {
if (field_map->is_stable()) {
dependencies()->DependOnStableMap(field_map);
dependencies()->AssumeMapStable(field_map);
field_access.map = field_map;
}
}

View File

@ -148,7 +148,7 @@ Reduction TypedOptimization::ReduceCheckMaps(Node* node) {
if (map_type.IsHeapConstant() &&
map_type.AsHeapConstant()->Value().is_identical_to(object_map)) {
if (object_map->CanTransition()) {
dependencies()->DependOnStableMap(object_map);
dependencies()->AssumeMapStable(object_map);
}
return Replace(effect);
}
@ -213,7 +213,7 @@ Reduction TypedOptimization::ReduceLoadField(Node* node) {
Handle<Map> object_map;
if (GetStableMapFromObjectType(object_type).ToHandle(&object_map)) {
if (object_map->CanTransition()) {
dependencies()->DependOnStableMap(object_map);
dependencies()->AssumeMapStable(object_map);
}
Node* const value = jsgraph()->HeapConstant(object_map);
ReplaceWithValue(node, value);

View File

@ -2553,7 +2553,7 @@ MaybeHandle<Code> Factory::TryNewCode(
Heap* heap = isolate()->heap();
CodePageCollectionMemoryModificationScope code_allocation(heap);
HeapObject* result =
heap->AllocateRawWithLightRetry(object_size, CODE_SPACE);
heap->AllocateRawWithLigthRetry(object_size, CODE_SPACE);
// Return an empty handle if we cannot allocate the code object.
if (!result) return MaybeHandle<Code>();

View File

@ -4473,7 +4473,7 @@ HeapObject* Heap::EnsureImmovableCode(HeapObject* heap_object,
return heap_object;
}
HeapObject* Heap::AllocateRawWithLightRetry(int size, AllocationSpace space,
HeapObject* Heap::AllocateRawWithLigthRetry(int size, AllocationSpace space,
AllocationAlignment alignment) {
HeapObject* result;
AllocationResult alloc = AllocateRaw(size, space, alignment);
@ -4497,7 +4497,7 @@ HeapObject* Heap::AllocateRawWithLightRetry(int size, AllocationSpace space,
HeapObject* Heap::AllocateRawWithRetryOrFail(int size, AllocationSpace space,
AllocationAlignment alignment) {
AllocationResult alloc;
HeapObject* result = AllocateRawWithLightRetry(size, space, alignment);
HeapObject* result = AllocateRawWithLigthRetry(size, space, alignment);
if (result) return result;
isolate()->counters()->gc_last_resort_from_handles()->Increment();

View File

@ -1910,7 +1910,7 @@ class Heap {
// triggered and the allocation is retried. This is performed multiple times.
// If after that retry procedure the allocation still fails nullptr is
// returned.
HeapObject* AllocateRawWithLightRetry(
HeapObject* AllocateRawWithLigthRetry(
int size, AllocationSpace space,
AllocationAlignment alignment = kWordAligned);

View File

@ -25,6 +25,7 @@
#include "src/bootstrapper.h"
#include "src/builtins/builtins.h"
#include "src/code-stubs.h"
#include "src/compilation-dependencies.h"
#include "src/compiler.h"
#include "src/counters-inl.h"
#include "src/counters.h"
@ -15017,6 +15018,34 @@ bool DependentCode::Compact() {
}
void DependentCode::UpdateToFinishedCode(DependencyGroup group, Foreign* info,
WeakCell* code_cell) {
if (this->length() == 0 || this->group() > group) {
// There is no such group.
return;
}
if (this->group() < group) {
// The group comes later in the list.
next_link()->UpdateToFinishedCode(group, info, code_cell);
return;
}
DCHECK_EQ(group, this->group());
DisallowHeapAllocation no_gc;
int count = this->count();
for (int i = 0; i < count; i++) {
if (object_at(i) == info) {
set_object_at(i, code_cell);
break;
}
}
#ifdef DEBUG
for (int i = 0; i < count; i++) {
DCHECK(object_at(i) != info);
}
#endif
}
void DependentCode::RemoveCompilationDependencies(
DependentCode::DependencyGroup group, Foreign* info) {
if (this->length() == 0 || this->group() > group) {
@ -15105,12 +15134,20 @@ bool DependentCode::MarkCodeForDeoptimization(
int count = this->count();
for (int i = 0; i < count; i++) {
Object* obj = object_at(i);
WeakCell* cell = WeakCell::cast(obj);
if (cell->cleared()) continue;
Code* code = Code::cast(cell->value());
if (!code->marked_for_deoptimization()) {
code->SetMarkedForDeoptimization(DependencyGroupName(group));
marked = true;
if (obj->IsWeakCell()) {
WeakCell* cell = WeakCell::cast(obj);
if (cell->cleared()) continue;
Code* code = Code::cast(cell->value());
if (!code->marked_for_deoptimization()) {
code->SetMarkedForDeoptimization(DependencyGroupName(group));
marked = true;
}
} else {
DCHECK(obj->IsForeign());
CompilationDependencies* info =
reinterpret_cast<CompilationDependencies*>(
Foreign::cast(obj)->foreign_address());
info->Abort();
}
}
for (int i = 0; i < count; i++) {

View File

@ -624,6 +624,9 @@ class DependentCode : public FixedArray {
DependencyGroup group,
Handle<WeakCell> code_cell);
void UpdateToFinishedCode(DependencyGroup group, Foreign* info,
WeakCell* code_cell);
void RemoveCompilationDependencies(DependentCode::DependencyGroup group,
Foreign* info);

View File

@ -87,6 +87,9 @@ OptimizedCompilationInfo::~OptimizedCompilationInfo() {
if (GetFlag(kDisableFutureOptimization) && has_shared_info()) {
shared_info()->DisableOptimization(bailout_reason());
}
if (dependencies()) {
dependencies()->Rollback();
}
}
void OptimizedCompilationInfo::set_deferred_handles(

View File

@ -309,7 +309,6 @@ class V8_EXPORT_PRIVATE OptimizedCompilationInfo final {
std::shared_ptr<DeferredHandles> deferred_handles_;
// Dependencies for this compilation, e.g. stable maps.
// TODO(neis): Move this to PipelineData.
std::unique_ptr<CompilationDependencies> dependencies_;
BailoutReason bailout_reason_;

View File

@ -153,7 +153,7 @@ Handle<JSFunction> FunctionTester::Compile(Handle<JSFunction> function) {
Handle<Code> code =
Pipeline::GenerateCodeForTesting(&info, isolate).ToHandleChecked();
CHECK(info.dependencies()->Commit(code));
info.dependencies()->Commit(code);
info.context()->native_context()->AddOptimizedCode(*code);
function->set_code(*code);
return function;

View File

@ -477,7 +477,6 @@ TEST(ReconfigureAccessorToNonExistingDataField) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> none_type = FieldType::None(isolate);
Handle<AccessorPair> pair = CreateAccessorPair(true, true);
@ -541,9 +540,9 @@ TEST(ReconfigureAccessorToNonExistingDataField) {
// to a map with a property with None representation.
TEST(ReconfigureAccessorToNonExistingDataFieldHeavy) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
v8::HandleScope scope(CcTest::isolate());
CompileRun(
"function getter() { return 1; };"
@ -654,7 +653,9 @@ static void TestGeneralizeField(int detach_property_at_index,
Handle<Map> field_owner(map->FindFieldOwner(isolate, property_index),
isolate);
CompilationDependencies dependencies(isolate, &zone);
dependencies.DependOnFieldType(map, property_index);
CHECK(!dependencies.HasAborted());
dependencies.AssumeFieldOwner(field_owner);
Handle<Map> new_map = Map::ReconfigureProperty(
isolate, map, property_index, kData, NONE, to.representation, to.type);
@ -670,21 +671,21 @@ static void TestGeneralizeField(int detach_property_at_index,
CHECK(map->is_deprecated());
CHECK_NE(*map, *new_map);
CHECK_EQ(expected_field_type_dependency && !field_owner->is_deprecated(),
!dependencies.AreValid());
dependencies.HasAborted());
} else if (expected_deprecation) {
CHECK(!map->is_stable());
CHECK(map->is_deprecated());
CHECK(field_owner->is_deprecated());
CHECK_NE(*map, *new_map);
CHECK(dependencies.AreValid());
CHECK(!dependencies.HasAborted());
} else {
CHECK(!field_owner->is_deprecated());
CHECK(map->is_stable()); // Map did not change, must be left stable.
CHECK_EQ(*map, *new_map);
CHECK_EQ(expected_field_type_dependency, !dependencies.AreValid());
CHECK_EQ(expected_field_type_dependency, dependencies.HasAborted());
}
{
@ -698,6 +699,8 @@ static void TestGeneralizeField(int detach_property_at_index,
}
}
dependencies.Rollback(); // Properly cleanup compilation info.
// Update all deprecated maps and check that they are now the same.
Handle<Map> updated_map = Map::Update(isolate, map);
CHECK_EQ(*new_map, *updated_map);
@ -754,7 +757,6 @@ TEST(GeneralizeSmiFieldToDouble) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
TestGeneralizeField(
@ -767,7 +769,6 @@ TEST(GeneralizeSmiFieldToTagged) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
@ -782,7 +783,6 @@ TEST(GeneralizeDoubleFieldToTagged) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
@ -797,7 +797,6 @@ TEST(GeneralizeHeapObjectFieldToTagged) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
@ -812,7 +811,6 @@ TEST(GeneralizeHeapObjectFieldToHeapObject) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> current_type =
@ -843,7 +841,6 @@ TEST(GeneralizeNoneFieldToSmi) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> none_type = FieldType::None(isolate);
Handle<FieldType> any_type = FieldType::Any(isolate);
@ -858,7 +855,6 @@ TEST(GeneralizeNoneFieldToDouble) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> none_type = FieldType::None(isolate);
Handle<FieldType> any_type = FieldType::Any(isolate);
@ -873,7 +869,6 @@ TEST(GeneralizeNoneFieldToHeapObject) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> none_type = FieldType::None(isolate);
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
@ -889,7 +884,6 @@ TEST(GeneralizeNoneFieldToTagged) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> none_type = FieldType::None(isolate);
Handle<FieldType> any_type = FieldType::Any(isolate);
@ -909,7 +903,6 @@ TEST(GeneralizeFieldWithAccessorProperties) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<AccessorPair> pair = CreateAccessorPair(true, true);
@ -1021,8 +1014,10 @@ static void TestReconfigureDataFieldAttribute_GeneralizeField(
CHECK(expectations2.Check(*map2));
Zone zone(isolate->allocator(), ZONE_NAME);
Handle<Map> field_owner(map->FindFieldOwner(isolate, kSplitProp), isolate);
CompilationDependencies dependencies(isolate, &zone);
dependencies.DependOnFieldType(map, kSplitProp);
CHECK(!dependencies.HasAborted());
dependencies.AssumeFieldOwner(field_owner);
// Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
// should generalize representations in |map1|.
@ -1041,7 +1036,8 @@ static void TestReconfigureDataFieldAttribute_GeneralizeField(
expected.type);
}
CHECK(map->is_deprecated());
CHECK(dependencies.AreValid());
CHECK(!dependencies.HasAborted());
dependencies.Rollback(); // Properly cleanup compilation info.
CHECK_NE(*map, *new_map);
CHECK(!new_map->is_deprecated());
@ -1103,8 +1099,10 @@ static void TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
CHECK(expectations2.Check(*map2));
Zone zone(isolate->allocator(), ZONE_NAME);
Handle<Map> field_owner(map->FindFieldOwner(isolate, kSplitProp), isolate);
CompilationDependencies dependencies(isolate, &zone);
dependencies.DependOnFieldType(map, kSplitProp);
CHECK(!dependencies.HasAborted());
dependencies.AssumeFieldOwner(field_owner);
// Reconfigure attributes of property |kSplitProp| of |map2| to NONE, which
// should generalize representations in |map1|.
@ -1127,7 +1125,8 @@ static void TestReconfigureDataFieldAttribute_GeneralizeFieldTrivial(
}
CHECK(!map->is_deprecated());
CHECK_EQ(*map, *new_map);
CHECK_EQ(expected_field_type_dependency, !dependencies.AreValid());
CHECK_EQ(expected_field_type_dependency, dependencies.HasAborted());
dependencies.Rollback(); // Properly cleanup compilation info.
CHECK(!new_map->is_deprecated());
CHECK(expectations.Check(*new_map));
@ -1140,7 +1139,6 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToDouble) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
if (FLAG_track_constant_fields) {
@ -1170,7 +1168,6 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeSmiFieldToTagged) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
@ -1202,7 +1199,6 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeDoubleFieldToTagged) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
@ -1234,7 +1230,6 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjFieldToHeapObj) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> current_type =
@ -1330,7 +1325,6 @@ TEST(ReconfigureDataFieldAttribute_GeneralizeHeapObjectFieldToTagged) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
@ -1782,8 +1776,10 @@ static void TestReconfigureElementsKind_GeneralizeField(
CHECK(expectations2.Check(*map2));
Zone zone(isolate->allocator(), ZONE_NAME);
Handle<Map> field_owner(map->FindFieldOwner(isolate, kDiffProp), isolate);
CompilationDependencies dependencies(isolate, &zone);
dependencies.DependOnFieldType(map, kDiffProp);
CHECK(!dependencies.HasAborted());
dependencies.AssumeFieldOwner(field_owner);
// Reconfigure elements kinds of |map2|, which should generalize
// representations in |map|.
@ -1801,7 +1797,8 @@ static void TestReconfigureElementsKind_GeneralizeField(
expected.representation, expected.type);
CHECK(map->is_deprecated());
CHECK(dependencies.AreValid());
CHECK(!dependencies.HasAborted());
dependencies.Rollback(); // Properly cleanup compilation info.
CHECK_NE(*map, *new_map);
CHECK(!new_map->is_deprecated());
@ -1875,8 +1872,10 @@ static void TestReconfigureElementsKind_GeneralizeFieldTrivial(
CHECK(expectations2.Check(*map2));
Zone zone(isolate->allocator(), ZONE_NAME);
Handle<Map> field_owner(map->FindFieldOwner(isolate, kDiffProp), isolate);
CompilationDependencies dependencies(isolate, &zone);
dependencies.DependOnFieldType(map, kDiffProp);
CHECK(!dependencies.HasAborted());
dependencies.AssumeFieldOwner(field_owner);
// Reconfigure elements kinds of |map2|, which should generalize
// representations in |map|.
@ -1897,7 +1896,8 @@ static void TestReconfigureElementsKind_GeneralizeFieldTrivial(
expected.representation, expected.type);
CHECK(!map->is_deprecated());
CHECK_EQ(*map, *new_map);
CHECK(dependencies.AreValid());
CHECK(!dependencies.HasAborted());
dependencies.Rollback(); // Properly cleanup compilation info.
CHECK(!new_map->is_deprecated());
CHECK(expectations.Check(*new_map));
@ -1920,7 +1920,6 @@ TEST(ReconfigureElementsKind_GeneralizeSmiFieldToDouble) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
if (FLAG_track_constant_fields) {
@ -1949,7 +1948,6 @@ TEST(ReconfigureElementsKind_GeneralizeSmiFieldToTagged) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
@ -1980,7 +1978,6 @@ TEST(ReconfigureElementsKind_GeneralizeDoubleFieldToTagged) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
@ -2011,7 +2008,6 @@ TEST(ReconfigureElementsKind_GeneralizeHeapObjFieldToHeapObj) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> current_type =
@ -2104,7 +2100,6 @@ TEST(ReconfigureElementsKind_GeneralizeHeapObjectFieldToTagged) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
@ -2139,7 +2134,6 @@ TEST(ReconfigurePropertySplitMapTransitionsOverflow) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Expectations expectations(isolate);
@ -2328,7 +2322,6 @@ TEST(ElementsKindTransitionFromMapOwningDescriptor) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
@ -2358,7 +2351,6 @@ TEST(ElementsKindTransitionFromMapNotOwningDescriptor) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<FieldType> value_type =
FieldType::Class(Map::Create(isolate, 0), isolate);
@ -2680,7 +2672,6 @@ TEST(TransitionDataFieldToDataField) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<Object> value1 = handle(Smi::kZero, isolate);
@ -2717,7 +2708,6 @@ TEST(TransitionDataConstantToAnotherDataConstant) {
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
Handle<String> name = factory->empty_string();
Handle<Map> sloppy_map =
Map::CopyInitialMap(isolate, isolate->sloppy_function_map());
@ -2752,7 +2742,6 @@ TEST(TransitionDataConstantToDataField) {
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<JSFunction> js_func1 =

View File

@ -57,6 +57,11 @@ class JSCallReducerTest : public TypedGraphTest {
i::FLAG_lazy_handler_deserialization = old_flag_lazy_handler_;
}
// Ensure uncommitted compilation dependencies are discarded after each test.
// This prevents use-after-free accesses through invalidation of compilation
// dependencies.
void TearDown() override { deps_.Rollback(); }
Node* GlobalFunction(const char* name) {
Handle<JSFunction> f = Handle<JSFunction>::cast(
Object::GetProperty(