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

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

Also refactor two other oddities in JSNativeContextSpecialization.

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

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

Cr-Commit-Position: refs/heads/master@{#32076}
2015-11-18 10:04:03 +00:00

155 lines
5.0 KiB
C++

// 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/compilation-dependencies.h"
#include "src/factory.h"
#include "src/handles-inl.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/zone.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::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);
AssumeMapStable(handle(current->map()));
Handle<JSReceiver> last;
if (prototype.ToHandle(&last) && last.is_identical_to(current)) {
break;
}
}
}
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 internal
} // namespace v8