| Index: src/hydrogen-instructions.h
|
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
|
| index 7acec8bcd5ebc3e2e0757d312ee591f5e5174e72..befc228d919dafa1303c7dd1b54b5f4ab9e3b3cb 100644
|
| --- a/src/hydrogen-instructions.h
|
| +++ b/src/hydrogen-instructions.h
|
| @@ -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()
|
| @@ -1057,6 +1049,10 @@ class HValue: public ZoneObject {
|
| bool Equals(HValue* other);
|
| virtual intptr_t Hashcode();
|
|
|
| + // Some instructions' hash code is dependent on object addresses and are not
|
| + // safe regarding GC and parallel recompilation. Compute the hash upfront.
|
| + virtual void FinalizeUniqueId() { }
|
| +
|
| // Printing support.
|
| virtual void PrintTo(StringStream* stream) = 0;
|
| void PrintNameTo(StringStream* stream);
|
| @@ -2643,7 +2639,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_raw_addresses_(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 +2652,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_raw_addresses_(0, zone) {
|
| SetOperandAt(0, value);
|
| SetOperandAt(1, value);
|
| set_representation(Representation::Tagged());
|
| @@ -2702,28 +2700,36 @@ class HCheckMaps: public HTemplateInstruction<2> {
|
| HValue* value() { return OperandAt(0); }
|
| SmallMapList* map_set() { return &map_set_; }
|
|
|
| + virtual void FinalizeUniqueId();
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
|
|
|
| protected:
|
| virtual bool DataEquals(HValue* other) {
|
| + ASSERT_EQ(map_set_.length(), map_raw_addresses_.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_raw_addresses_.length() != b->map_raw_addresses_.length()) {
|
| + return false;
|
| + }
|
| + for (int i = 0; i < map_raw_addresses_.length(); i++) {
|
| + if (map_raw_addresses_.at(i) != b->map_raw_addresses_.at(i)) {
|
| + return false;
|
| + }
|
| }
|
| return true;
|
| }
|
|
|
| private:
|
| SmallMapList map_set_;
|
| + ZoneList<Address> map_raw_addresses_;
|
| };
|
|
|
|
|
| class HCheckFunction: public HUnaryOperation {
|
| public:
|
| HCheckFunction(HValue* value, Handle<JSFunction> function)
|
| - : HUnaryOperation(value), target_(function) {
|
| + : HUnaryOperation(value), target_(function), raw_address_(NULL) {
|
| set_representation(Representation::Tagged());
|
| SetFlag(kUseGVN);
|
| target_in_new_space_ = Isolate::Current()->heap()->InNewSpace(*function);
|
| @@ -2739,6 +2745,13 @@ class HCheckFunction: public HUnaryOperation {
|
| virtual void Verify();
|
| #endif
|
|
|
| + virtual void FinalizeUniqueId() {
|
| + // Raw address may have already been collected.
|
| + ASSERT(raw_address_ == NULL ||
|
| + raw_address_ == reinterpret_cast<Address>(*target_));
|
| + raw_address_ = reinterpret_cast<Address>(*target_);
|
| + }
|
| +
|
| Handle<JSFunction> target() const { return target_; }
|
| bool target_in_new_space() const { return target_in_new_space_; }
|
|
|
| @@ -2747,11 +2760,13 @@ class HCheckFunction: public HUnaryOperation {
|
| protected:
|
| virtual bool DataEquals(HValue* other) {
|
| HCheckFunction* b = HCheckFunction::cast(other);
|
| - return target_.is_identical_to(b->target());
|
| + ASSERT_NE(NULL, raw_address_);
|
| + return raw_address_ == b->raw_address_;
|
| }
|
|
|
| private:
|
| Handle<JSFunction> target_;
|
| + Address raw_address_;
|
| bool target_in_new_space_;
|
| };
|
|
|
| @@ -2856,7 +2871,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_raw_address_(NULL),
|
| + last_prototype_raw_address_(NULL) {
|
| SetFlag(kUseGVN);
|
| SetGVNFlag(kDependsOnMaps);
|
| // Keep a list of all objects on the prototype chain up to the holder
|
| @@ -2882,18 +2901,23 @@ 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;
|
| + ASSERT_NE(NULL, last_prototype_raw_address_);
|
| + return reinterpret_cast<intptr_t>(first_prototype_raw_address_) * 17 +
|
| + reinterpret_cast<intptr_t>(last_prototype_raw_address_);
|
| + }
|
| +
|
| + virtual void FinalizeUniqueId() {
|
| + // Raw addresses may have already been collected.
|
| + ASSERT(first_prototype_raw_address_ == 0 ||
|
| + first_prototype_raw_address_ ==
|
| + reinterpret_cast<Address>(*prototypes_.first()));
|
| + first_prototype_raw_address_ =
|
| + reinterpret_cast<Address>(*prototypes_.first());
|
| + ASSERT(last_prototype_raw_address_ == 0 ||
|
| + last_prototype_raw_address_ ==
|
| + reinterpret_cast<Address>(*prototypes_.last()));
|
| + last_prototype_raw_address_ =
|
| + reinterpret_cast<Address>(*prototypes_.last());
|
| }
|
|
|
| bool CanOmitPrototypeChecks() {
|
| @@ -2906,22 +2930,16 @@ 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
|
| + ASSERT_NE(NULL, first_prototype_raw_address_);
|
| + return first_prototype_raw_address_ == b->first_prototype_raw_address_ &&
|
| + last_prototype_raw_address_ == b->last_prototype_raw_address_;
|
| }
|
|
|
| private:
|
| ZoneList<Handle<JSObject> > prototypes_;
|
| ZoneList<Handle<Map> > maps_;
|
| + Address first_prototype_raw_address_;
|
| + Address last_prototype_raw_address_;
|
| };
|
|
|
|
|
| @@ -3176,6 +3194,7 @@ class HConstant: public HTemplateInstruction<0> {
|
| Representation r,
|
| Handle<Object> optional_handle = Handle<Object>::null());
|
| HConstant(Handle<Object> handle,
|
| + Address raw_address,
|
| Representation r,
|
| HType type,
|
| bool is_internalized_string,
|
| @@ -3189,8 +3208,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 +3227,19 @@ class HConstant: public HTemplateInstruction<0> {
|
| }
|
|
|
| ASSERT(!handle_.is_null());
|
| + HandleDereferenceGuard allow_dereference_for_immovable_check(
|
| + isolate(), HandleDereferenceGuard::ALLOW);
|
| + ASSERT_NE(NULL, raw_address_);
|
| + Object* obj = reinterpret_cast<Object*>(raw_address_);
|
| 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(obj != heap->minus_zero_value());
|
| + ASSERT(obj != heap->nan_value());
|
| + return obj == heap->undefined_value() ||
|
| + obj == heap->null_value() ||
|
| + obj == heap->true_value() ||
|
| + obj == heap->false_value() ||
|
| + obj == heap->the_hole_value() ||
|
| + obj == heap->empty_string();
|
| }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| @@ -3293,24 +3309,25 @@ 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_);
|
| + ASSERT_NE(NULL, raw_address_);
|
| + return reinterpret_cast<intptr_t>(raw_address_);
|
| }
|
| + }
|
|
|
| - return hash;
|
| + virtual void FinalizeUniqueId() {
|
| + if (!has_double_value_) {
|
| + ASSERT(!handle_.is_null());
|
| + // Raw address may have already been collected.
|
| + ASSERT(raw_address_ == NULL ||
|
| + raw_address_ == reinterpret_cast<Address>(*handle_));
|
| + raw_address_ = reinterpret_cast<Address>(*handle_);
|
| + }
|
| }
|
|
|
| #ifdef DEBUG
|
| @@ -3333,8 +3350,9 @@ class HConstant: public HTemplateInstruction<0> {
|
| BitCast<int64_t>(other_constant->double_value_);
|
| } else {
|
| ASSERT(!handle_.is_null());
|
| + ASSERT_NE(NULL, raw_address_);
|
| return !other_constant->handle_.is_null() &&
|
| - handle_.is_identical_to(other_constant->handle_);
|
| + raw_address_ == other_constant->raw_address_;
|
| }
|
| }
|
|
|
| @@ -3358,7 +3376,12 @@ class HConstant: public HTemplateInstruction<0> {
|
| bool has_double_value_ : 1;
|
| bool is_internalized_string_ : 1; // TODO(yangguo): make this part of HType.
|
| bool boolean_value_ : 1;
|
| - int32_t int32_value_;
|
| + // An extra hash code is only necessary if the value is not a number.
|
| + // So has_double_value_ governs how to interpret the union.
|
| + union {
|
| + int32_t int32_value_;
|
| + Address raw_address_;
|
| + };
|
| double double_value_;
|
| HType type_from_value_;
|
| };
|
| @@ -4759,7 +4782,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_(0) {
|
| set_representation(Representation::Tagged());
|
| SetFlag(kUseGVN);
|
| SetGVNFlag(kDependsOnGlobalVars);
|
| @@ -4771,13 +4794,15 @@ 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_);
|
| + ASSERT_NE(0, unique_id_);
|
| + return unique_id_;
|
| + }
|
| +
|
| + virtual void FinalizeUniqueId() {
|
| + // Raw address may have already been collected.
|
| + ASSERT(unique_id_ == 0 ||
|
| + unique_id_ == reinterpret_cast<intptr_t>(*cell_));
|
| + unique_id_ = reinterpret_cast<intptr_t>(*cell_);
|
| }
|
|
|
| virtual Representation RequiredInputRepresentation(int index) {
|
| @@ -4789,7 +4814,8 @@ class HLoadGlobalCell: public HTemplateInstruction<0> {
|
| protected:
|
| virtual bool DataEquals(HValue* other) {
|
| HLoadGlobalCell* b = HLoadGlobalCell::cast(other);
|
| - return cell_.is_identical_to(b->cell());
|
| + ASSERT_NE(0, unique_id_);
|
| + return unique_id_ == b->unique_id_;
|
| }
|
|
|
| private:
|
| @@ -4797,6 +4823,7 @@ class HLoadGlobalCell: public HTemplateInstruction<0> {
|
|
|
| Handle<JSGlobalPropertyCell> cell_;
|
| PropertyDetails details_;
|
| + intptr_t unique_id_;
|
| };
|
|
|
|
|
| @@ -5256,12 +5283,16 @@ class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
|
|
|
| static const int kMaxLoadPolymorphism = 4;
|
|
|
| + virtual void FinalizeUniqueId();
|
| +
|
| protected:
|
| virtual bool DataEquals(HValue* value);
|
|
|
| private:
|
| SmallMapList types_;
|
| Handle<String> name_;
|
| + ZoneList<Address> types_raw_address_;
|
| + Address name_raw_address_;
|
| bool need_generic_;
|
| };
|
|
|
| @@ -5525,6 +5556,7 @@ class HStoreNamedField: public HTemplateInstruction<2> {
|
| : name_(name),
|
| is_in_object_(in_object),
|
| offset_(offset),
|
| + transition_raw_address_(NULL),
|
| new_space_dominator_(NULL) {
|
| SetOperandAt(0, obj);
|
| SetOperandAt(1, val);
|
| @@ -5555,6 +5587,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_; }
|
| + Address transition_raw_address() const { return transition_raw_address_; }
|
| void set_transition(Handle<Map> map) { transition_ = map; }
|
| HValue* new_space_dominator() const { return new_space_dominator_; }
|
|
|
| @@ -5567,11 +5600,20 @@ class HStoreNamedField: public HTemplateInstruction<2> {
|
| return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
|
| }
|
|
|
| + virtual void FinalizeUniqueId() {
|
| + if (transition_.is_null()) return;
|
| + // Raw address may have already been collected.
|
| + ASSERT(transition_raw_address_ == NULL ||
|
| + transition_raw_address_ == reinterpret_cast<Address>(*transition_));
|
| + transition_raw_address_ = reinterpret_cast<Address>(*transition_);
|
| + }
|
| +
|
| private:
|
| Handle<String> name_;
|
| bool is_in_object_;
|
| int offset_;
|
| Handle<Map> transition_;
|
| + Address transition_raw_address_;
|
| HValue* new_space_dominator_;
|
| };
|
|
|
| @@ -5772,6 +5814,8 @@ class HTransitionElementsKind: public HTemplateInstruction<2> {
|
| Handle<Map> transitioned_map)
|
| : original_map_(original_map),
|
| transitioned_map_(transitioned_map),
|
| + original_map_raw_address_(NULL),
|
| + transitioned_map_raw_address_(NULL),
|
| from_kind_(original_map->elements_kind()),
|
| to_kind_(transitioned_map->elements_kind()) {
|
| SetOperandAt(0, object);
|
| @@ -5802,18 +5846,35 @@ class HTransitionElementsKind: public HTemplateInstruction<2> {
|
|
|
| virtual void PrintDataTo(StringStream* stream);
|
|
|
| + virtual void FinalizeUniqueId() {
|
| + // Raw addresses may have already been collected.
|
| + ASSERT(original_map_raw_address_ == NULL ||
|
| + original_map_raw_address_ ==
|
| + reinterpret_cast<Address>(*original_map_));
|
| + ASSERT(transitioned_map_raw_address_ == NULL ||
|
| + transitioned_map_raw_address_ ==
|
| + reinterpret_cast<Address>(*transitioned_map_));
|
| + original_map_raw_address_ = reinterpret_cast<Address>(*original_map_);
|
| + transitioned_map_raw_address_ =
|
| + reinterpret_cast<Address>(*transitioned_map_);
|
| + }
|
| +
|
| DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind)
|
|
|
| protected:
|
| virtual bool DataEquals(HValue* other) {
|
| + ASSERT_NE(NULL, original_map_raw_address_);
|
| + ASSERT_NE(NULL, transitioned_map_raw_address_);
|
| 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_raw_address_ == instr->original_map_raw_address_ &&
|
| + transitioned_map_raw_address_ == instr->transitioned_map_raw_address_;
|
| }
|
|
|
| private:
|
| Handle<Map> original_map_;
|
| Handle<Map> transitioned_map_;
|
| + Address original_map_raw_address_;
|
| + Address transitioned_map_raw_address_;
|
| ElementsKind from_kind_;
|
| ElementsKind to_kind_;
|
| };
|
|
|