Remove relocation lock.
Freeze HValue hash codes that are based on object addresses. R=svenpanne@chromium.org BUG= Review URL: https://chromiumcodereview.appspot.com/14040006 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14273 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
9585ead1e9
commit
e1742a6716
@ -59,7 +59,6 @@ inline bool Handle<T>::is_identical_to(const Handle<T> other) const {
|
||||
if (FLAG_enable_slow_asserts) {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
CHECK(isolate->AllowHandleDereference() ||
|
||||
Heap::RelocationLock::IsLocked(isolate->heap()) ||
|
||||
!isolate->optimizing_compiler_thread()->IsOptimizerThread());
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
12
src/heap.cc
12
src/heap.cc
@ -162,8 +162,7 @@ Heap::Heap()
|
||||
#endif
|
||||
promotion_queue_(this),
|
||||
configured_(false),
|
||||
chunks_queued_for_free_(NULL),
|
||||
relocation_mutex_(NULL) {
|
||||
chunks_queued_for_free_(NULL) {
|
||||
// Allow build-time customization of the max semispace size. Building
|
||||
// V8 with snapshots and a non-default max semispace size is much
|
||||
// easier if you can define it as part of the build environment.
|
||||
@ -1294,8 +1293,6 @@ class ScavengeWeakObjectRetainer : public WeakObjectRetainer {
|
||||
|
||||
|
||||
void Heap::Scavenge() {
|
||||
RelocationLock relocation_lock(this);
|
||||
|
||||
#ifdef VERIFY_HEAP
|
||||
if (FLAG_verify_heap) VerifyNonPointerSpacePointers();
|
||||
#endif
|
||||
@ -6628,11 +6625,6 @@ bool Heap::SetUp() {
|
||||
|
||||
store_buffer()->SetUp();
|
||||
|
||||
if (FLAG_parallel_recompilation) relocation_mutex_ = OS::CreateMutex();
|
||||
#ifdef DEBUG
|
||||
relocation_mutex_locked_ = false;
|
||||
#endif // DEBUG
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6735,8 +6727,6 @@ void Heap::TearDown() {
|
||||
incremental_marking()->TearDown();
|
||||
|
||||
isolate_->memory_allocator()->TearDown();
|
||||
|
||||
delete relocation_mutex_;
|
||||
}
|
||||
|
||||
|
||||
|
37
src/heap.h
37
src/heap.h
@ -1846,38 +1846,6 @@ class Heap {
|
||||
|
||||
void CheckpointObjectStats();
|
||||
|
||||
// We don't use a ScopedLock here since we want to lock the heap
|
||||
// only when FLAG_parallel_recompilation is true.
|
||||
class RelocationLock {
|
||||
public:
|
||||
explicit RelocationLock(Heap* heap) : heap_(heap) {
|
||||
if (FLAG_parallel_recompilation) {
|
||||
heap_->relocation_mutex_->Lock();
|
||||
#ifdef DEBUG
|
||||
heap_->relocation_mutex_locked_ = true;
|
||||
#endif // DEBUG
|
||||
}
|
||||
}
|
||||
|
||||
~RelocationLock() {
|
||||
if (FLAG_parallel_recompilation) {
|
||||
#ifdef DEBUG
|
||||
heap_->relocation_mutex_locked_ = false;
|
||||
#endif // DEBUG
|
||||
heap_->relocation_mutex_->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool IsLocked(Heap* heap) {
|
||||
return heap->relocation_mutex_locked_;
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
private:
|
||||
Heap* heap_;
|
||||
};
|
||||
|
||||
private:
|
||||
Heap();
|
||||
|
||||
@ -2347,11 +2315,6 @@ class Heap {
|
||||
|
||||
MemoryChunk* chunks_queued_for_free_;
|
||||
|
||||
Mutex* relocation_mutex_;
|
||||
#ifdef DEBUG
|
||||
bool relocation_mutex_locked_;
|
||||
#endif // DEBUG;
|
||||
|
||||
friend class Factory;
|
||||
friend class GCTracer;
|
||||
friend class DisallowAllocationFailure;
|
||||
|
@ -1584,10 +1584,10 @@ void HCheckMaps::SetSideEffectDominator(GVNFlag side_effect,
|
||||
// for which the map is known.
|
||||
if (HasNoUses() && dominator->IsStoreNamedField()) {
|
||||
HStoreNamedField* store = HStoreNamedField::cast(dominator);
|
||||
Handle<Map> map = store->transition();
|
||||
if (map.is_null() || store->object() != value()) return;
|
||||
UniqueValueId map_unique_id = store->transition_unique_id();
|
||||
if (!map_unique_id.IsInitialized() || store->object() != value()) return;
|
||||
for (int i = 0; i < map_set()->length(); i++) {
|
||||
if (map.is_identical_to(map_set()->at(i))) {
|
||||
if (map_unique_id == map_unique_ids_.at(i)) {
|
||||
DeleteAndReplaceWith(NULL);
|
||||
return;
|
||||
}
|
||||
@ -2047,6 +2047,7 @@ static bool IsInteger32(double value) {
|
||||
|
||||
HConstant::HConstant(Handle<Object> handle, Representation r)
|
||||
: handle_(handle),
|
||||
unique_id_(),
|
||||
has_int32_value_(false),
|
||||
has_double_value_(false),
|
||||
is_internalized_string_(false),
|
||||
@ -2075,11 +2076,13 @@ HConstant::HConstant(Handle<Object> handle, Representation r)
|
||||
|
||||
|
||||
HConstant::HConstant(Handle<Object> handle,
|
||||
UniqueValueId unique_id,
|
||||
Representation r,
|
||||
HType type,
|
||||
bool is_internalize_string,
|
||||
bool boolean_value)
|
||||
: handle_(handle),
|
||||
unique_id_(unique_id),
|
||||
has_int32_value_(false),
|
||||
has_double_value_(false),
|
||||
is_internalized_string_(is_internalize_string),
|
||||
@ -2095,7 +2098,9 @@ HConstant::HConstant(Handle<Object> handle,
|
||||
HConstant::HConstant(int32_t integer_value,
|
||||
Representation r,
|
||||
Handle<Object> optional_handle)
|
||||
: has_int32_value_(true),
|
||||
: handle_(optional_handle),
|
||||
unique_id_(),
|
||||
has_int32_value_(true),
|
||||
has_double_value_(true),
|
||||
is_internalized_string_(false),
|
||||
boolean_value_(integer_value != 0),
|
||||
@ -2108,7 +2113,9 @@ HConstant::HConstant(int32_t integer_value,
|
||||
HConstant::HConstant(double double_value,
|
||||
Representation r,
|
||||
Handle<Object> optional_handle)
|
||||
: has_int32_value_(IsInteger32(double_value)),
|
||||
: handle_(optional_handle),
|
||||
unique_id_(),
|
||||
has_int32_value_(IsInteger32(double_value)),
|
||||
has_double_value_(true),
|
||||
is_internalized_string_(false),
|
||||
boolean_value_(double_value != 0 && !isnan(double_value)),
|
||||
@ -2133,8 +2140,12 @@ HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const {
|
||||
if (has_int32_value_) return new(zone) HConstant(int32_value_, r, handle_);
|
||||
if (has_double_value_) return new(zone) HConstant(double_value_, r, handle_);
|
||||
ASSERT(!handle_.is_null());
|
||||
return new(zone) HConstant(
|
||||
handle_, r, type_from_value_, is_internalized_string_, boolean_value_);
|
||||
return new(zone) HConstant(handle_,
|
||||
unique_id_,
|
||||
r,
|
||||
type_from_value_,
|
||||
is_internalized_string_,
|
||||
boolean_value_);
|
||||
}
|
||||
|
||||
|
||||
@ -2459,6 +2470,8 @@ HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
|
||||
Zone* zone)
|
||||
: types_(Min(types->length(), kMaxLoadPolymorphism), zone),
|
||||
name_(name),
|
||||
types_unique_ids_(0, zone),
|
||||
name_unique_id_(),
|
||||
need_generic_(false) {
|
||||
SetOperandAt(0, context);
|
||||
SetOperandAt(1, object);
|
||||
@ -2525,15 +2538,39 @@ HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
|
||||
}
|
||||
|
||||
|
||||
bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
|
||||
HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value);
|
||||
if (types_.length() != other->types()->length()) return false;
|
||||
if (!name_.is_identical_to(other->name())) return false;
|
||||
if (need_generic_ != other->need_generic_) return false;
|
||||
void HCheckMaps::FinalizeUniqueValueId() {
|
||||
if (!map_unique_ids_.is_empty()) return;
|
||||
Zone* zone = block()->zone();
|
||||
map_unique_ids_.Initialize(map_set_.length(), zone);
|
||||
for (int i = 0; i < map_set_.length(); i++) {
|
||||
map_unique_ids_.Add(UniqueValueId(map_set_.at(i)), zone);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HLoadNamedFieldPolymorphic::FinalizeUniqueValueId() {
|
||||
if (!types_unique_ids_.is_empty()) return;
|
||||
Zone* zone = block()->zone();
|
||||
types_unique_ids_.Initialize(types_.length(), zone);
|
||||
for (int i = 0; i < types_.length(); i++) {
|
||||
types_unique_ids_.Add(UniqueValueId(types_.at(i)), zone);
|
||||
}
|
||||
name_unique_id_ = UniqueValueId(name_);
|
||||
}
|
||||
|
||||
|
||||
bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
|
||||
ASSERT_EQ(types_.length(), types_unique_ids_.length());
|
||||
HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value);
|
||||
if (name_unique_id_ != other->name_unique_id_) return false;
|
||||
if (types_unique_ids_.length() != other->types_unique_ids_.length()) {
|
||||
return false;
|
||||
}
|
||||
if (need_generic_ != other->need_generic_) return false;
|
||||
for (int i = 0; i < types_unique_ids_.length(); i++) {
|
||||
bool found = false;
|
||||
for (int j = 0; j < types_.length(); j++) {
|
||||
if (types_.at(j).is_identical_to(other->types()->at(i))) {
|
||||
for (int j = 0; j < types_unique_ids_.length(); j++) {
|
||||
if (types_unique_ids_.at(j) == other->types_unique_ids_.at(i)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -234,14 +234,6 @@ class LChunkBuilder;
|
||||
virtual Opcode opcode() const { return HValue::k##type; }
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ASSERT_ALLOCATION_DISABLED \
|
||||
ASSERT(isolate()->optimizing_compiler_thread()->IsOptimizerThread() || \
|
||||
!isolate()->heap()->IsAllocationAllowed())
|
||||
#else
|
||||
#define ASSERT_ALLOCATION_DISABLED do {} while (0)
|
||||
#endif
|
||||
|
||||
class Range: public ZoneObject {
|
||||
public:
|
||||
Range()
|
||||
@ -364,6 +356,48 @@ class Representation {
|
||||
};
|
||||
|
||||
|
||||
class UniqueValueId {
|
||||
public:
|
||||
UniqueValueId() : raw_address_(NULL) { }
|
||||
|
||||
explicit UniqueValueId(Object* object) {
|
||||
raw_address_ = reinterpret_cast<Address>(object);
|
||||
ASSERT(IsInitialized());
|
||||
}
|
||||
|
||||
explicit UniqueValueId(Handle<Object> handle) {
|
||||
static const Address kEmptyHandleSentinel = reinterpret_cast<Address>(1);
|
||||
if (handle.is_null()) {
|
||||
raw_address_ = kEmptyHandleSentinel;
|
||||
} else {
|
||||
raw_address_ = reinterpret_cast<Address>(*handle);
|
||||
ASSERT_NE(kEmptyHandleSentinel, raw_address_);
|
||||
}
|
||||
ASSERT(IsInitialized());
|
||||
}
|
||||
|
||||
bool IsInitialized() const { return raw_address_ != NULL; }
|
||||
|
||||
bool operator==(const UniqueValueId& other) const {
|
||||
ASSERT(IsInitialized() && other.IsInitialized());
|
||||
return raw_address_ == other.raw_address_;
|
||||
}
|
||||
|
||||
bool operator!=(const UniqueValueId& other) const {
|
||||
ASSERT(IsInitialized() && other.IsInitialized());
|
||||
return raw_address_ != other.raw_address_;
|
||||
}
|
||||
|
||||
intptr_t Hashcode() const {
|
||||
ASSERT(IsInitialized());
|
||||
return reinterpret_cast<intptr_t>(raw_address_);
|
||||
}
|
||||
|
||||
private:
|
||||
Address raw_address_;
|
||||
};
|
||||
|
||||
|
||||
class HType {
|
||||
public:
|
||||
HType() : type_(kUninitialized) { }
|
||||
@ -1057,6 +1091,9 @@ class HValue: public ZoneObject {
|
||||
bool Equals(HValue* other);
|
||||
virtual intptr_t Hashcode();
|
||||
|
||||
// Compute unique ids upfront that is safe wrt GC and parallel recompilation.
|
||||
virtual void FinalizeUniqueValueId() { }
|
||||
|
||||
// Printing support.
|
||||
virtual void PrintTo(StringStream* stream) = 0;
|
||||
void PrintNameTo(StringStream* stream);
|
||||
@ -2643,7 +2680,8 @@ class HLoadExternalArrayPointer: public HUnaryOperation {
|
||||
class HCheckMaps: public HTemplateInstruction<2> {
|
||||
public:
|
||||
HCheckMaps(HValue* value, Handle<Map> map, Zone* zone,
|
||||
HValue* typecheck = NULL) {
|
||||
HValue* typecheck = NULL)
|
||||
: map_unique_ids_(0, zone) {
|
||||
SetOperandAt(0, value);
|
||||
// If callers don't depend on a typecheck, they can pass in NULL. In that
|
||||
// case we use a copy of the |value| argument as a dummy value.
|
||||
@ -2655,7 +2693,8 @@ class HCheckMaps: public HTemplateInstruction<2> {
|
||||
SetGVNFlag(kDependsOnElementsKind);
|
||||
map_set()->Add(map, zone);
|
||||
}
|
||||
HCheckMaps(HValue* value, SmallMapList* maps, Zone* zone) {
|
||||
HCheckMaps(HValue* value, SmallMapList* maps, Zone* zone)
|
||||
: map_unique_ids_(0, zone) {
|
||||
SetOperandAt(0, value);
|
||||
SetOperandAt(1, value);
|
||||
set_representation(Representation::Tagged());
|
||||
@ -2702,28 +2741,36 @@ class HCheckMaps: public HTemplateInstruction<2> {
|
||||
HValue* value() { return OperandAt(0); }
|
||||
SmallMapList* map_set() { return &map_set_; }
|
||||
|
||||
virtual void FinalizeUniqueValueId();
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
|
||||
|
||||
protected:
|
||||
virtual bool DataEquals(HValue* other) {
|
||||
ASSERT_EQ(map_set_.length(), map_unique_ids_.length());
|
||||
HCheckMaps* b = HCheckMaps::cast(other);
|
||||
// Relies on the fact that map_set has been sorted before.
|
||||
if (map_set()->length() != b->map_set()->length()) return false;
|
||||
for (int i = 0; i < map_set()->length(); i++) {
|
||||
if (!map_set()->at(i).is_identical_to(b->map_set()->at(i))) return false;
|
||||
if (map_unique_ids_.length() != b->map_unique_ids_.length()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < map_unique_ids_.length(); i++) {
|
||||
if (map_unique_ids_.at(i) != b->map_unique_ids_.at(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
SmallMapList map_set_;
|
||||
ZoneList<UniqueValueId> map_unique_ids_;
|
||||
};
|
||||
|
||||
|
||||
class HCheckFunction: public HUnaryOperation {
|
||||
public:
|
||||
HCheckFunction(HValue* value, Handle<JSFunction> function)
|
||||
: HUnaryOperation(value), target_(function) {
|
||||
: HUnaryOperation(value), target_(function), target_unique_id_() {
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kUseGVN);
|
||||
target_in_new_space_ = Isolate::Current()->heap()->InNewSpace(*function);
|
||||
@ -2739,6 +2786,10 @@ class HCheckFunction: public HUnaryOperation {
|
||||
virtual void Verify();
|
||||
#endif
|
||||
|
||||
virtual void FinalizeUniqueValueId() {
|
||||
target_unique_id_ = UniqueValueId(target_);
|
||||
}
|
||||
|
||||
Handle<JSFunction> target() const { return target_; }
|
||||
bool target_in_new_space() const { return target_in_new_space_; }
|
||||
|
||||
@ -2747,11 +2798,12 @@ class HCheckFunction: public HUnaryOperation {
|
||||
protected:
|
||||
virtual bool DataEquals(HValue* other) {
|
||||
HCheckFunction* b = HCheckFunction::cast(other);
|
||||
return target_.is_identical_to(b->target());
|
||||
return target_unique_id_ == b->target_unique_id_;
|
||||
}
|
||||
|
||||
private:
|
||||
Handle<JSFunction> target_;
|
||||
UniqueValueId target_unique_id_;
|
||||
bool target_in_new_space_;
|
||||
};
|
||||
|
||||
@ -2856,7 +2908,11 @@ class HCheckPrototypeMaps: public HTemplateInstruction<0> {
|
||||
public:
|
||||
HCheckPrototypeMaps(Handle<JSObject> prototype,
|
||||
Handle<JSObject> holder,
|
||||
Zone* zone) : prototypes_(2, zone), maps_(2, zone) {
|
||||
Zone* zone)
|
||||
: prototypes_(2, zone),
|
||||
maps_(2, zone),
|
||||
first_prototype_unique_id_(),
|
||||
last_prototype_unique_id_() {
|
||||
SetFlag(kUseGVN);
|
||||
SetGVNFlag(kDependsOnMaps);
|
||||
// Keep a list of all objects on the prototype chain up to the holder
|
||||
@ -2882,18 +2938,13 @@ class HCheckPrototypeMaps: public HTemplateInstruction<0> {
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
|
||||
virtual intptr_t Hashcode() {
|
||||
ASSERT_ALLOCATION_DISABLED;
|
||||
// Dereferencing to use the object's raw address for hashing is safe.
|
||||
HandleDereferenceGuard allow_handle_deref(isolate(),
|
||||
HandleDereferenceGuard::ALLOW);
|
||||
SLOW_ASSERT(Heap::RelocationLock::IsLocked(isolate()->heap()) ||
|
||||
!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
|
||||
intptr_t hash = 0;
|
||||
for (int i = 0; i < prototypes_.length(); i++) {
|
||||
hash = 17 * hash + reinterpret_cast<intptr_t>(*prototypes_[i]);
|
||||
hash = 17 * hash + reinterpret_cast<intptr_t>(*maps_[i]);
|
||||
}
|
||||
return hash;
|
||||
return first_prototype_unique_id_.Hashcode() * 17 +
|
||||
last_prototype_unique_id_.Hashcode();
|
||||
}
|
||||
|
||||
virtual void FinalizeUniqueValueId() {
|
||||
first_prototype_unique_id_ = UniqueValueId(prototypes_.first());
|
||||
last_prototype_unique_id_ = UniqueValueId(prototypes_.last());
|
||||
}
|
||||
|
||||
bool CanOmitPrototypeChecks() {
|
||||
@ -2906,22 +2957,15 @@ class HCheckPrototypeMaps: public HTemplateInstruction<0> {
|
||||
protected:
|
||||
virtual bool DataEquals(HValue* other) {
|
||||
HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
|
||||
#ifdef DEBUG
|
||||
if (prototypes_.length() != b->prototypes()->length()) return false;
|
||||
for (int i = 0; i < prototypes_.length(); i++) {
|
||||
if (!prototypes_[i].is_identical_to(b->prototypes()->at(i))) return false;
|
||||
if (!maps_[i].is_identical_to(b->maps()->at(i))) return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return prototypes_.first().is_identical_to(b->prototypes()->first()) &&
|
||||
prototypes_.last().is_identical_to(b->prototypes()->last());
|
||||
#endif // DEBUG
|
||||
return first_prototype_unique_id_ == b->first_prototype_unique_id_ &&
|
||||
last_prototype_unique_id_ == b->last_prototype_unique_id_;
|
||||
}
|
||||
|
||||
private:
|
||||
ZoneList<Handle<JSObject> > prototypes_;
|
||||
ZoneList<Handle<Map> > maps_;
|
||||
UniqueValueId first_prototype_unique_id_;
|
||||
UniqueValueId last_prototype_unique_id_;
|
||||
};
|
||||
|
||||
|
||||
@ -3176,6 +3220,7 @@ class HConstant: public HTemplateInstruction<0> {
|
||||
Representation r,
|
||||
Handle<Object> optional_handle = Handle<Object>::null());
|
||||
HConstant(Handle<Object> handle,
|
||||
UniqueValueId unique_id,
|
||||
Representation r,
|
||||
HType type,
|
||||
bool is_internalized_string,
|
||||
@ -3189,8 +3234,6 @@ class HConstant: public HTemplateInstruction<0> {
|
||||
return handle_;
|
||||
}
|
||||
|
||||
bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); }
|
||||
|
||||
bool IsSpecialDouble() const {
|
||||
return has_double_value_ &&
|
||||
(BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) ||
|
||||
@ -3210,20 +3253,17 @@ class HConstant: public HTemplateInstruction<0> {
|
||||
}
|
||||
|
||||
ASSERT(!handle_.is_null());
|
||||
HandleDereferenceGuard allow_dereference_for_immovable_check(
|
||||
isolate(), HandleDereferenceGuard::ALLOW);
|
||||
Heap* heap = isolate()->heap();
|
||||
// We should have handled minus_zero_value and nan_value in the
|
||||
// has_double_value_ clause above.
|
||||
// Dereferencing is safe to compare against immovable singletons.
|
||||
HandleDereferenceGuard allow_handle_deref(isolate(),
|
||||
HandleDereferenceGuard::ALLOW);
|
||||
ASSERT(*handle_ != heap->minus_zero_value());
|
||||
ASSERT(*handle_ != heap->nan_value());
|
||||
return *handle_ == heap->undefined_value() ||
|
||||
*handle_ == heap->null_value() ||
|
||||
*handle_ == heap->true_value() ||
|
||||
*handle_ == heap->false_value() ||
|
||||
*handle_ == heap->the_hole_value() ||
|
||||
*handle_ == heap->empty_string();
|
||||
ASSERT(unique_id_ != UniqueValueId(heap->minus_zero_value()));
|
||||
ASSERT(unique_id_ != UniqueValueId(heap->nan_value()));
|
||||
return unique_id_ == UniqueValueId(heap->undefined_value()) ||
|
||||
unique_id_ == UniqueValueId(heap->null_value()) ||
|
||||
unique_id_ == UniqueValueId(heap->true_value()) ||
|
||||
unique_id_ == UniqueValueId(heap->false_value()) ||
|
||||
unique_id_ == UniqueValueId(heap->the_hole_value()) ||
|
||||
unique_id_ == UniqueValueId(heap->empty_string());
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
@ -3293,24 +3333,21 @@ class HConstant: public HTemplateInstruction<0> {
|
||||
}
|
||||
|
||||
virtual intptr_t Hashcode() {
|
||||
ASSERT_ALLOCATION_DISABLED;
|
||||
intptr_t hash;
|
||||
|
||||
if (has_int32_value_) {
|
||||
hash = static_cast<intptr_t>(int32_value_);
|
||||
return static_cast<intptr_t>(int32_value_);
|
||||
} else if (has_double_value_) {
|
||||
hash = static_cast<intptr_t>(BitCast<int64_t>(double_value_));
|
||||
return static_cast<intptr_t>(BitCast<int64_t>(double_value_));
|
||||
} else {
|
||||
ASSERT(!handle_.is_null());
|
||||
// Dereferencing to use the object's raw address for hashing is safe.
|
||||
HandleDereferenceGuard allow_handle_deref(isolate(),
|
||||
HandleDereferenceGuard::ALLOW);
|
||||
SLOW_ASSERT(Heap::RelocationLock::IsLocked(isolate()->heap()) ||
|
||||
!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
|
||||
hash = reinterpret_cast<intptr_t>(*handle_);
|
||||
return unique_id_.Hashcode();
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
virtual void FinalizeUniqueValueId() {
|
||||
if (!has_double_value_) {
|
||||
ASSERT(!handle_.is_null());
|
||||
unique_id_ = UniqueValueId(handle_);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -3334,7 +3371,7 @@ class HConstant: public HTemplateInstruction<0> {
|
||||
} else {
|
||||
ASSERT(!handle_.is_null());
|
||||
return !other_constant->handle_.is_null() &&
|
||||
handle_.is_identical_to(other_constant->handle_);
|
||||
unique_id_ == other_constant->unique_id_;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3348,6 +3385,7 @@ class HConstant: public HTemplateInstruction<0> {
|
||||
// constant is non-numeric, handle_ always points to a valid
|
||||
// constant HeapObject.
|
||||
Handle<Object> handle_;
|
||||
UniqueValueId unique_id_;
|
||||
|
||||
// We store the HConstant in the most specific form safely possible.
|
||||
// The two flags, has_int32_value_ and has_double_value_ tell us if
|
||||
@ -4759,7 +4797,7 @@ class HUnknownOSRValue: public HTemplateInstruction<0> {
|
||||
class HLoadGlobalCell: public HTemplateInstruction<0> {
|
||||
public:
|
||||
HLoadGlobalCell(Handle<JSGlobalPropertyCell> cell, PropertyDetails details)
|
||||
: cell_(cell), details_(details) {
|
||||
: cell_(cell), details_(details), unique_id_() {
|
||||
set_representation(Representation::Tagged());
|
||||
SetFlag(kUseGVN);
|
||||
SetGVNFlag(kDependsOnGlobalVars);
|
||||
@ -4771,13 +4809,11 @@ class HLoadGlobalCell: public HTemplateInstruction<0> {
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
|
||||
virtual intptr_t Hashcode() {
|
||||
ASSERT_ALLOCATION_DISABLED;
|
||||
// Dereferencing to use the object's raw address for hashing is safe.
|
||||
HandleDereferenceGuard allow_handle_deref(isolate(),
|
||||
HandleDereferenceGuard::ALLOW);
|
||||
SLOW_ASSERT(Heap::RelocationLock::IsLocked(isolate()->heap()) ||
|
||||
!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
|
||||
return reinterpret_cast<intptr_t>(*cell_);
|
||||
return unique_id_.Hashcode();
|
||||
}
|
||||
|
||||
virtual void FinalizeUniqueValueId() {
|
||||
unique_id_ = UniqueValueId(cell_);
|
||||
}
|
||||
|
||||
virtual Representation RequiredInputRepresentation(int index) {
|
||||
@ -4789,7 +4825,7 @@ class HLoadGlobalCell: public HTemplateInstruction<0> {
|
||||
protected:
|
||||
virtual bool DataEquals(HValue* other) {
|
||||
HLoadGlobalCell* b = HLoadGlobalCell::cast(other);
|
||||
return cell_.is_identical_to(b->cell());
|
||||
return unique_id_ == b->unique_id_;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -4797,6 +4833,7 @@ class HLoadGlobalCell: public HTemplateInstruction<0> {
|
||||
|
||||
Handle<JSGlobalPropertyCell> cell_;
|
||||
PropertyDetails details_;
|
||||
UniqueValueId unique_id_;
|
||||
};
|
||||
|
||||
|
||||
@ -5255,12 +5292,16 @@ class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
|
||||
|
||||
static const int kMaxLoadPolymorphism = 4;
|
||||
|
||||
virtual void FinalizeUniqueValueId();
|
||||
|
||||
protected:
|
||||
virtual bool DataEquals(HValue* value);
|
||||
|
||||
private:
|
||||
SmallMapList types_;
|
||||
Handle<String> name_;
|
||||
ZoneList<UniqueValueId> types_unique_ids_;
|
||||
UniqueValueId name_unique_id_;
|
||||
bool need_generic_;
|
||||
};
|
||||
|
||||
@ -5524,6 +5565,7 @@ class HStoreNamedField: public HTemplateInstruction<2> {
|
||||
: name_(name),
|
||||
is_in_object_(in_object),
|
||||
offset_(offset),
|
||||
transition_unique_id_(),
|
||||
new_space_dominator_(NULL) {
|
||||
SetOperandAt(0, obj);
|
||||
SetOperandAt(1, val);
|
||||
@ -5554,6 +5596,7 @@ class HStoreNamedField: public HTemplateInstruction<2> {
|
||||
bool is_in_object() const { return is_in_object_; }
|
||||
int offset() const { return offset_; }
|
||||
Handle<Map> transition() const { return transition_; }
|
||||
UniqueValueId transition_unique_id() const { return transition_unique_id_; }
|
||||
void set_transition(Handle<Map> map) { transition_ = map; }
|
||||
HValue* new_space_dominator() const { return new_space_dominator_; }
|
||||
|
||||
@ -5566,11 +5609,16 @@ class HStoreNamedField: public HTemplateInstruction<2> {
|
||||
return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
|
||||
}
|
||||
|
||||
virtual void FinalizeUniqueValueId() {
|
||||
transition_unique_id_ = UniqueValueId(transition_);
|
||||
}
|
||||
|
||||
private:
|
||||
Handle<String> name_;
|
||||
bool is_in_object_;
|
||||
int offset_;
|
||||
Handle<Map> transition_;
|
||||
UniqueValueId transition_unique_id_;
|
||||
HValue* new_space_dominator_;
|
||||
};
|
||||
|
||||
@ -5771,6 +5819,8 @@ class HTransitionElementsKind: public HTemplateInstruction<2> {
|
||||
Handle<Map> transitioned_map)
|
||||
: original_map_(original_map),
|
||||
transitioned_map_(transitioned_map),
|
||||
original_map_unique_id_(),
|
||||
transitioned_map_unique_id_(),
|
||||
from_kind_(original_map->elements_kind()),
|
||||
to_kind_(transitioned_map->elements_kind()) {
|
||||
SetOperandAt(0, object);
|
||||
@ -5801,18 +5851,25 @@ class HTransitionElementsKind: public HTemplateInstruction<2> {
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
|
||||
virtual void FinalizeUniqueValueId() {
|
||||
original_map_unique_id_ = UniqueValueId(original_map_);
|
||||
transitioned_map_unique_id_ = UniqueValueId(transitioned_map_);
|
||||
}
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
|
||||
|
||||
protected:
|
||||
virtual bool DataEquals(HValue* other) {
|
||||
HTransitionElementsKind* instr = HTransitionElementsKind::cast(other);
|
||||
return original_map_.is_identical_to(instr->original_map()) &&
|
||||
transitioned_map_.is_identical_to(instr->transitioned_map());
|
||||
return original_map_unique_id_ == instr->original_map_unique_id_ &&
|
||||
transitioned_map_unique_id_ == instr->transitioned_map_unique_id_;
|
||||
}
|
||||
|
||||
private:
|
||||
Handle<Map> original_map_;
|
||||
Handle<Map> transitioned_map_;
|
||||
UniqueValueId original_map_unique_id_;
|
||||
UniqueValueId transitioned_map_unique_id_;
|
||||
ElementsKind from_kind_;
|
||||
ElementsKind to_kind_;
|
||||
};
|
||||
|
@ -517,7 +517,6 @@ class ReachabilityAnalyzer BASE_EMBEDDED {
|
||||
|
||||
void HGraph::Verify(bool do_full_verify) const {
|
||||
// Allow dereferencing for debug mode verification.
|
||||
Heap::RelocationLock(isolate()->heap());
|
||||
HandleDereferenceGuard allow_handle_deref(isolate(),
|
||||
HandleDereferenceGuard::ALLOW);
|
||||
for (int i = 0; i < blocks_.length(); i++) {
|
||||
@ -619,6 +618,7 @@ HConstant* HGraph::GetConstant##Name() { \
|
||||
if (!constant_##name##_.is_set()) { \
|
||||
HConstant* constant = new(zone()) HConstant( \
|
||||
isolate()->factory()->name##_value(), \
|
||||
UniqueValueId(isolate()->heap()->name##_value()), \
|
||||
Representation::Tagged(), \
|
||||
htype, \
|
||||
false, \
|
||||
@ -880,6 +880,7 @@ HGraph* HGraphBuilder::CreateGraph() {
|
||||
HPhase phase("H_Block building", isolate());
|
||||
set_current_block(graph()->entry_block());
|
||||
if (!BuildGraph()) return NULL;
|
||||
graph()->FinalizeUniqueValueIds();
|
||||
return graph_;
|
||||
}
|
||||
|
||||
@ -1696,6 +1697,19 @@ HBasicBlock* HGraph::CreateBasicBlock() {
|
||||
}
|
||||
|
||||
|
||||
void HGraph::FinalizeUniqueValueIds() {
|
||||
AssertNoAllocation no_gc;
|
||||
ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
|
||||
for (int i = 0; i < blocks()->length(); ++i) {
|
||||
for (HInstruction* instr = blocks()->at(i)->first();
|
||||
instr != NULL;
|
||||
instr = instr->next()) {
|
||||
instr->FinalizeUniqueValueId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HGraph::Canonicalize() {
|
||||
if (!FLAG_use_canonicalizing) return;
|
||||
HPhase phase("H_Canonicalize", this);
|
||||
@ -4327,8 +4341,6 @@ bool HOptimizedGraphBuilder::BuildGraph() {
|
||||
void HGraph::GlobalValueNumbering() {
|
||||
// Perform common subexpression elimination and loop-invariant code motion.
|
||||
if (FLAG_use_gvn) {
|
||||
// We use objects' raw addresses for identification, so they must not move.
|
||||
Heap::RelocationLock relocation_lock(isolate()->heap());
|
||||
HPhase phase("H_Global value numbering", this);
|
||||
HGlobalValueNumberer gvn(this, info());
|
||||
bool removed_side_effects = gvn.Analyze();
|
||||
|
@ -260,6 +260,7 @@ class HGraph: public ZoneObject {
|
||||
HBasicBlock* entry_block() const { return entry_block_; }
|
||||
HEnvironment* start_environment() const { return start_environment_; }
|
||||
|
||||
void FinalizeUniqueValueIds();
|
||||
void InitializeInferredTypes();
|
||||
void InsertTypeConversions();
|
||||
void MergeRemovableSimulates();
|
||||
|
@ -3125,8 +3125,6 @@ void MarkCompactCollector::ProcessInvalidatedCode(ObjectVisitor* visitor) {
|
||||
|
||||
|
||||
void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
|
||||
Heap::RelocationLock relocation_lock(heap());
|
||||
|
||||
bool code_slots_filtering_required;
|
||||
{ GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE);
|
||||
code_slots_filtering_required = MarkInvalidatedCode();
|
||||
|
Loading…
Reference in New Issue
Block a user