Immediately "optimize as prototype" when setting as prototype of a function.
This saves space since OptimizeAsPrototype detaches from the transition tree, reclaiming intermediate maps. On gmail this corresponds to roughly 20% of all maps. BUG= Review URL: https://codereview.chromium.org/941213005 Cr-Commit-Position: refs/heads/master@{#26772}
This commit is contained in:
parent
f4bd25da69
commit
fade797d02
@ -10033,6 +10033,41 @@ void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void GetMinInobjectSlack(Map* map, void* data) {
|
||||||
|
int slack = map->unused_property_fields();
|
||||||
|
if (*reinterpret_cast<int*>(data) > slack) {
|
||||||
|
*reinterpret_cast<int*>(data) = slack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ShrinkInstanceSize(Map* map, void* data) {
|
||||||
|
int slack = *reinterpret_cast<int*>(data);
|
||||||
|
map->set_inobject_properties(map->inobject_properties() - slack);
|
||||||
|
map->set_unused_property_fields(map->unused_property_fields() - slack);
|
||||||
|
map->set_instance_size(map->instance_size() - slack * kPointerSize);
|
||||||
|
|
||||||
|
// Visitor id might depend on the instance size, recalculate it.
|
||||||
|
map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JSFunction::CompleteInobjectSlackTracking() {
|
||||||
|
DCHECK(has_initial_map());
|
||||||
|
Map* map = initial_map();
|
||||||
|
|
||||||
|
DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1);
|
||||||
|
map->set_counter(Map::kRetainingCounterStart);
|
||||||
|
|
||||||
|
int slack = map->unused_property_fields();
|
||||||
|
map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
|
||||||
|
if (slack != 0) {
|
||||||
|
// Resize the initial map and all maps in its transition tree.
|
||||||
|
map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
|
void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
|
||||||
PrototypeOptimizationMode mode) {
|
PrototypeOptimizationMode mode) {
|
||||||
if (object->IsGlobalObject()) return;
|
if (object->IsGlobalObject()) return;
|
||||||
@ -10224,6 +10259,11 @@ void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
|
|||||||
// needed. At that point, a new initial map is created and the
|
// needed. At that point, a new initial map is created and the
|
||||||
// prototype is put into the initial map where it belongs.
|
// prototype is put into the initial map where it belongs.
|
||||||
function->set_prototype_or_initial_map(*value);
|
function->set_prototype_or_initial_map(*value);
|
||||||
|
if (value->IsJSObject()) {
|
||||||
|
// Optimize as prototype to detach it from its transition tree.
|
||||||
|
JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value),
|
||||||
|
FAST_PROTOTYPE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
isolate->heap()->ClearInstanceofCache();
|
isolate->heap()->ClearInstanceofCache();
|
||||||
}
|
}
|
||||||
@ -10766,41 +10806,6 @@ void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void GetMinInobjectSlack(Map* map, void* data) {
|
|
||||||
int slack = map->unused_property_fields();
|
|
||||||
if (*reinterpret_cast<int*>(data) > slack) {
|
|
||||||
*reinterpret_cast<int*>(data) = slack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void ShrinkInstanceSize(Map* map, void* data) {
|
|
||||||
int slack = *reinterpret_cast<int*>(data);
|
|
||||||
map->set_inobject_properties(map->inobject_properties() - slack);
|
|
||||||
map->set_unused_property_fields(map->unused_property_fields() - slack);
|
|
||||||
map->set_instance_size(map->instance_size() - slack * kPointerSize);
|
|
||||||
|
|
||||||
// Visitor id might depend on the instance size, recalculate it.
|
|
||||||
map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void JSFunction::CompleteInobjectSlackTracking() {
|
|
||||||
DCHECK(has_initial_map());
|
|
||||||
Map* map = initial_map();
|
|
||||||
|
|
||||||
DCHECK(map->counter() >= Map::kSlackTrackingCounterEnd - 1);
|
|
||||||
map->set_counter(Map::kRetainingCounterStart);
|
|
||||||
|
|
||||||
int slack = map->unused_property_fields();
|
|
||||||
map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
|
|
||||||
if (slack != 0) {
|
|
||||||
// Resize the initial map and all maps in its transition tree.
|
|
||||||
map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context,
|
int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context,
|
||||||
BailoutId osr_ast_id) {
|
BailoutId osr_ast_id) {
|
||||||
DisallowHeapAllocation no_gc;
|
DisallowHeapAllocation no_gc;
|
||||||
|
Loading…
Reference in New Issue
Block a user