Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
Revert part of 11727 as it sometimes tanked V8 benchmark (raytrace) p…
Browse files Browse the repository at this point in the history
…erformance for reasons that are not obvious. Now we make objects into fast-case objects when they are made prototypes for other objects, but we do not mark objects that are already fast case with a bit that helps keep them in fast case. Review URL: https://chromiumcodereview.appspot.com/10556004

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@11831 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
  • Loading branch information
erikcorry authored and piscisaureus committed Jun 19, 2012
1 parent bf682af commit f94b85d
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 66 deletions.
17 changes: 1 addition & 16 deletions deps/v8/src/objects-inl.h
Expand Up @@ -1616,8 +1616,7 @@ bool JSObject::TooManyFastProperties(int properties,
int inobject = map()->inobject_properties();

int limit;
if (store_mode == CERTAINLY_NOT_STORE_FROM_KEYED ||
map()->used_for_prototype()) {
if (store_mode == CERTAINLY_NOT_STORE_FROM_KEYED) {
limit = Max(inobject, kMaxFastProperties);
} else {
limit = Max(inobject, kFastPropertiesSoftLimit);
Expand Down Expand Up @@ -2982,20 +2981,6 @@ bool Map::is_shared() {
}


void Map::set_used_for_prototype(bool value) {
if (value) {
set_bit_field3(bit_field3() | (1 << kUsedForPrototype));
} else {
set_bit_field3(bit_field3() & ~(1 << kUsedForPrototype));
}
}


bool Map::used_for_prototype() {
return ((1 << kUsedForPrototype) & bit_field3()) != 0;
}


JSFunction* Map::unchecked_constructor() {
return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
}
Expand Down
37 changes: 7 additions & 30 deletions deps/v8/src/objects.cc
Expand Up @@ -7515,34 +7515,11 @@ MaybeObject* JSObject::OptimizeAsPrototype() {
// Make sure prototypes are fast objects and their maps have the bit set
// so they remain fast.
Map* proto_map = map();
if (!proto_map->used_for_prototype()) {
if (!HasFastProperties()) {
MaybeObject* new_proto = TransformToFastProperties(0);
if (new_proto->IsFailure()) return new_proto;
ASSERT(new_proto == this);
proto_map = map();
if (!proto_map->is_shared()) {
proto_map->set_used_for_prototype(true);
}
} else {
Heap* heap = GetHeap();
// We use the hole value as a singleton key in the prototype transition
// map so that we don't multiply the number of maps unnecessarily.
Map* new_map =
proto_map->GetPrototypeTransition(heap->the_hole_value());
if (new_map == NULL) {
MaybeObject* maybe_new_map =
proto_map->CopyDropTransitions(DescriptorArray::MAY_BE_SHARED);
if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map;
new_map->set_used_for_prototype(true);
MaybeObject* ok =
proto_map->PutPrototypeTransition(heap->the_hole_value(),
new_map);
if (ok->IsFailure()) return ok;
}
ASSERT(!proto_map->is_shared() && !new_map->is_shared());
set_map(new_map);
}
if (!HasFastProperties()) {
MaybeObject* new_proto = TransformToFastProperties(0);
if (new_proto->IsFailure()) return new_proto;
ASSERT(new_proto == this);
proto_map = map();
}
return this;
}
Expand All @@ -7552,8 +7529,8 @@ MaybeObject* JSFunction::SetInstancePrototype(Object* value) {
ASSERT(value->IsJSReceiver());
Heap* heap = GetHeap();

// First some logic for the map of the prototype to make sure the
// used_for_prototype flag is set.
// First some logic for the map of the prototype to make sure it is in fast
// mode.
if (value->IsJSObject()) {
MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype();
if (ok->IsFailure()) return ok;
Expand Down
13 changes: 1 addition & 12 deletions deps/v8/src/objects.h
Expand Up @@ -4749,14 +4749,6 @@ class Map: public HeapObject {
inline void set_is_shared(bool value);
inline bool is_shared();

// Tells whether the map is used for an object that is a prototype for another
// object or is the prototype on a function. Such maps are made faster by
// tweaking the heuristics that distinguish between regular object-oriented
// objects and the objects that are being used as hash maps. This flag is
// for optimization, not correctness.
inline void set_used_for_prototype(bool value);
inline bool used_for_prototype();

// Tells whether the instance needs security checks when accessing its
// properties.
inline void set_is_access_check_needed(bool access_check_needed);
Expand Down Expand Up @@ -4944,9 +4936,7 @@ class Map: public HeapObject {
// the original map. That way we can transition to the same map if the same
// prototype is set, rather than creating a new map every time. The
// transitions are in the form of a map where the keys are prototype objects
// and the values are the maps the are transitioned to. The special key
// the_hole denotes the map we should transition to when the
// used_for_prototype flag is set.
// and the values are the maps the are transitioned to.
static const int kMaxCachedPrototypeTransitions = 256;

Map* GetPrototypeTransition(Object* prototype);
Expand Down Expand Up @@ -5042,7 +5032,6 @@ class Map: public HeapObject {
// Bit positions for bit field 3
static const int kIsShared = 0;
static const int kFunctionWithPrototype = 1;
static const int kUsedForPrototype = 2;

typedef FixedBodyDescriptor<kPointerFieldsBeginOffset,
kPointerFieldsEndOffset,
Expand Down
9 changes: 3 additions & 6 deletions deps/v8/test/cctest/test-heap.cc
Expand Up @@ -1579,13 +1579,10 @@ TEST(PrototypeTransitionClearing) {
*v8::Handle<v8::Object>::Cast(
v8::Context::GetCurrent()->Global()->Get(v8_str("base"))));

// Verify that only dead prototype transitions are cleared. There is an
// extra, 11th, prototype transition on the Object map, which is the
// transition to a map with the used_for_prototype flag set (the key is
// the_hole).
CHECK_EQ(11, baseObject->map()->NumberOfProtoTransitions());
// Verify that only dead prototype transitions are cleared.
CHECK_EQ(10, baseObject->map()->NumberOfProtoTransitions());
HEAP->CollectAllGarbage(Heap::kNoGCFlags);
const int transitions = 11 - 3;
const int transitions = 10 - 3;
CHECK_EQ(transitions, baseObject->map()->NumberOfProtoTransitions());

// Verify that prototype transitions array was compacted.
Expand Down
4 changes: 2 additions & 2 deletions deps/v8/test/mjsunit/fast-prototype.js
Expand Up @@ -71,8 +71,8 @@ function test(use_new, add_first, set__proto__, same_map_as) {
// Still fast
assertTrue(%HasFastProperties(proto));
AddProps(proto);
// Setting the bit means it is still fast with all these properties.
assertTrue(%HasFastProperties(proto));
// After we add all those properties it went slow mode again :-(
assertFalse(%HasFastProperties(proto));
}
if (same_map_as && !add_first) {
assertTrue(%HaveSameMap(same_map_as, proto));
Expand Down

0 comments on commit f94b85d

Please sign in to comment.