9b14e5bb63
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}
155 lines
5.0 KiB
C++
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
|