Revert "Inline instance object hash code into object header on 64 bit."

This reverts commit ac6310d5f3 because
of test failures on real ARM64 hardware as opposed to the DartVM
simulator.  Original review: https://codereview.chromium.org/2912863006/

R=kustermann@google.com
BUG=

Review-Url: https://codereview.chromium.org/2953753002 .
This commit is contained in:
Erik Corry 2017-06-22 10:22:45 +02:00
parent ac6310d5f3
commit 847cd093ba
37 changed files with 147 additions and 500 deletions

View file

@ -42,25 +42,17 @@ DEFINE_NATIVE_ENTRY(Object_getHash, 1) {
// Please note that no handle is created for the argument.
// This is safe since the argument is only used in a tail call.
// The performance benefit is more than 5% when using hashCode.
#if defined(HASH_IN_OBJECT_HEADER)
return Smi::New(Object::GetCachedHash(arguments->NativeArgAt(0)));
#else
Heap* heap = isolate->heap();
ASSERT(arguments->NativeArgAt(0)->IsDartInstance());
return Smi::New(heap->GetHash(arguments->NativeArgAt(0)));
#endif
}
DEFINE_NATIVE_ENTRY(Object_setHash, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Smi, hash, arguments->NativeArgAt(1));
#if defined(HASH_IN_OBJECT_HEADER)
Object::SetCachedHash(arguments->NativeArgAt(0), hash.Value());
#else
const Instance& instance = Instance::CheckedHandle(arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Smi, hash, arguments->NativeArgAt(1));
Heap* heap = isolate->heap();
heap->SetHash(instance.raw(), hash.Value());
#endif
return Object::null();
}

View file

@ -2,9 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
int _getHash(obj) native "Object_getHash";
int _setHash(obj, hash) native "Object_setHash";
@patch
class Object {
// The VM has its own implementation of equals.
@ -12,18 +9,22 @@ class Object {
bool operator ==(other) native "Object_equals";
// Helpers used to implement hashCode. If a hashCode is used, we remember it
// in a weak table in the VM (32 bit) or in the header of the object (64
// bit). A new hashCode value is calculated using a random number generator.
// in a weak table in the VM. A new hashCode value is calculated using a
// number generator.
static final _hashCodeRnd = new Random();
static _getHash(obj) native "Object_getHash";
static _setHash(obj, hash) native "Object_setHash";
// Shared static implentation for hashCode and _identityHashCode.
static int _objectHashCode(obj) {
var result = _getHash(obj);
if (result == 0) {
// We want the hash to be a Smi value greater than 0.
do {
result = _hashCodeRnd.nextInt(0x40000000);
while (result == 0) {
result = _hashCodeRnd.nextInt(0x40000000);
} while (result == 0);
}
_setHash(obj, result);
}
return result;

View file

@ -3471,7 +3471,7 @@ void Assembler::TryAllocate(const Class& cls,
ASSERT(instance_size >= kHeapObjectTag);
AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::SizeTag::update(instance_size, tags);
ASSERT(cls.id() != kIllegalCid);
tags = RawObject::ClassIdTag::update(cls.id(), tags);
@ -3520,7 +3520,7 @@ void Assembler::TryAllocateArray(intptr_t cid,
// Initialize the tags.
// instance: new object start as a tagged pointer.
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::ClassIdTag::update(cid, tags);
tags = RawObject::SizeTag::update(instance_size, tags);
LoadImmediate(temp1, tags);

View file

@ -1363,12 +1363,10 @@ void Assembler::TryAllocate(const Class& cls,
AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
NOT_IN_PRODUCT(UpdateAllocationStats(cls.id(), space));
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::SizeTag::update(instance_size, tags);
ASSERT(cls.id() != kIllegalCid);
tags = RawObject::ClassIdTag::update(cls.id(), tags);
// Extends the 32 bit tags with zeros, which is the uninitialized
// hash code.
LoadImmediate(TMP, tags);
StoreFieldToOffset(TMP, instance_reg, Object::tags_offset());
} else {
@ -1412,11 +1410,9 @@ void Assembler::TryAllocateArray(intptr_t cid,
// Initialize the tags.
// instance: new object start as a tagged pointer.
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::ClassIdTag::update(cid, tags);
tags = RawObject::SizeTag::update(instance_size, tags);
// Extends the 32 bit tags with zeros, which is the uninitialized
// hash code.
LoadImmediate(temp2, tags);
str(temp2, FieldAddress(instance, Array::tags_offset())); // Store tags.
} else {

View file

@ -742,19 +742,16 @@ class Assembler : public ValueObject {
EmitLoadStoreRegPair(STP, rt, rt2, a, sz);
}
void ldxr(Register rt, Register rn, OperandSize size = kDoubleWord) {
void ldxr(Register rt, Register rn) {
// rt = value
// rn = address
EmitLoadStoreExclusive(LDXR, R31, rn, rt, size);
EmitLoadStoreExclusive(LDXR, R31, rn, rt, kDoubleWord);
}
void stxr(Register rs,
Register rt,
Register rn,
OperandSize size = kDoubleWord) {
void stxr(Register rs, Register rt, Register rn) {
// rs = status (1 = failure, 0 = success)
// rt = value
// rn = address
EmitLoadStoreExclusive(STXR, rs, rn, rt, size);
EmitLoadStoreExclusive(STXR, rs, rn, rt, kDoubleWord);
}
void clrex() {
const int32_t encoding = static_cast<int32_t>(CLREX);
@ -1704,8 +1701,8 @@ class Assembler : public ValueObject {
Register rn,
Register rt,
OperandSize sz = kDoubleWord) {
ASSERT(sz == kDoubleWord || sz == kWord);
const int32_t size = B31 | (sz == kDoubleWord ? B30 : 0);
ASSERT(sz == kDoubleWord);
const int32_t size = B31 | B30;
ASSERT((rs != kNoRegister) && (rs != ZR));
ASSERT((rn != kNoRegister) && (rn != ZR));

View file

@ -607,68 +607,6 @@ ASSEMBLER_TEST_RUN(FailedSemaphore, test) {
}
ASSEMBLER_TEST_GENERATE(Semaphore32, assembler) {
__ SetupDartSP();
__ movz(R0, Immediate(40), 0);
__ add(R0, R0, Operand(R0, LSL, 32));
__ Push(R0);
__ movz(R0, Immediate(40), 0);
__ movz(R1, Immediate(42), 0);
Label retry;
__ Bind(&retry);
__ ldxr(R0, SP, kWord);
// 32 bit operation should ignore the high word of R0 that was pushed on the
// stack.
__ stxr(TMP, R1, SP, kWord); // IP == 0, success
__ cmp(TMP, Operand(0));
__ b(&retry, NE); // NE if context switch occurred between ldrex and strex.
__ Pop(R0); // 42 + 42 * 2**32
__ RestoreCSP();
__ ret();
}
ASSEMBLER_TEST_RUN(Semaphore32, test) {
EXPECT(test != NULL);
typedef int (*Semaphore32)() DART_UNUSED;
// Lower word has been atomically switched from 40 to 42k, whereas upper word
// is unchanged at 40.
EXPECT_EQ(42 + (40l << 32),
EXECUTE_TEST_CODE_INT64(Semaphore32, test->entry()));
}
ASSEMBLER_TEST_GENERATE(FailedSemaphore32, assembler) {
__ SetupDartSP();
__ movz(R0, Immediate(40), 0);
__ add(R0, R0, Operand(R0, LSL, 32));
__ Push(R0);
__ movz(R0, Immediate(40), 0);
__ movz(R1, Immediate(42), 0);
__ ldxr(R0, SP, kWord);
__ clrex(); // Simulate a context switch.
__ stxr(TMP, R1, SP, kWord); // IP == 1, failure
__ Pop(R0); // 40
__ add(R0, R0, Operand(TMP));
__ RestoreCSP();
__ ret();
}
ASSEMBLER_TEST_RUN(FailedSemaphore32, test) {
EXPECT(test != NULL);
typedef int (*FailedSemaphore32)() DART_UNUSED;
// Lower word has had the failure code (1) added to it. Upper word is
// unchanged at 40.
EXPECT_EQ(41 + (40l << 32),
EXECUTE_TEST_CODE_INT64(FailedSemaphore32, test->entry()));
}
// Logical register operations.
ASSEMBLER_TEST_GENERATE(AndRegs, assembler) {
__ movz(R1, Immediate(43), 0);

View file

@ -2643,7 +2643,7 @@ void Assembler::TryAllocate(const Class& cls,
NOT_IN_PRODUCT(UpdateAllocationStats(cls.id(), temp_reg, space));
ASSERT(instance_size >= kHeapObjectTag);
subl(instance_reg, Immediate(instance_size - kHeapObjectTag));
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::SizeTag::update(instance_size, tags);
ASSERT(cls.id() != kIllegalCid);
tags = RawObject::ClassIdTag::update(cls.id(), tags);
@ -2690,7 +2690,7 @@ void Assembler::TryAllocateArray(intptr_t cid,
UpdateAllocationStatsWithSize(cid, instance_size, temp_reg, space));
// Initialize the tags.
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::ClassIdTag::update(cid, tags);
tags = RawObject::SizeTag::update(instance_size, tags);
movl(FieldAddress(instance, Object::tags_offset()), Immediate(tags));

View file

@ -999,7 +999,7 @@ void Assembler::TryAllocate(const Class& cls,
ASSERT(instance_size >= kHeapObjectTag);
AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
NOT_IN_PRODUCT(UpdateAllocationStats(cls.id(), temp_reg, space));
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::SizeTag::update(instance_size, tags);
ASSERT(cls.id() != kIllegalCid);
tags = RawObject::ClassIdTag::update(cls.id(), tags);
@ -1049,7 +1049,7 @@ void Assembler::TryAllocateArray(intptr_t cid,
// Initialize the tags.
// instance: new object start as a tagged pointer.
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::ClassIdTag::update(cid, tags);
tags = RawObject::SizeTag::update(instance_size, tags);
LoadImmediate(temp1, tags);

View file

@ -3433,12 +3433,10 @@ void Assembler::TryAllocate(const Class& cls,
NOT_IN_PRODUCT(UpdateAllocationStats(cls.id(), space));
ASSERT(instance_size >= kHeapObjectTag);
AddImmediate(instance_reg, Immediate(kHeapObjectTag - instance_size));
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::SizeTag::update(instance_size, tags);
ASSERT(cls.id() != kIllegalCid);
tags = RawObject::ClassIdTag::update(cls.id(), tags);
// Extends the 32 bit tags with zeros, which is the uninitialized
// hash code.
MoveImmediate(FieldAddress(instance_reg, Object::tags_offset()),
Immediate(tags));
} else {
@ -3482,11 +3480,9 @@ void Assembler::TryAllocateArray(intptr_t cid,
// Initialize the tags.
// instance: new object start as a tagged pointer.
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::ClassIdTag::update(cid, tags);
tags = RawObject::SizeTag::update(instance_size, tags);
// Extends the 32 bit tags with zeros, which is the uninitialized
// hash code.
movq(FieldAddress(instance, Array::tags_offset()), Immediate(tags));
} else {
jmp(failure);

View file

@ -690,8 +690,16 @@ class Assembler : public ValueObject {
void lock();
void cmpxchgl(const Address& address, Register reg);
void lock_cmpxchgl(const Address& address, Register reg) {
lock();
cmpxchgl(address, reg);
}
void cmpxchgq(const Address& address, Register reg);
void lock_cmpxchgq(const Address& address, Register reg) {
lock();
cmpxchgq(address, reg);
}
void cpuid();
@ -793,11 +801,6 @@ class Assembler : public ValueObject {
cmpxchgq(address, reg);
}
void LockCmpxchgl(const Address& address, Register reg) {
lock();
cmpxchgl(address, reg);
}
void PushRegisters(intptr_t cpu_register_set, intptr_t xmm_register_set);
void PopRegisters(intptr_t cpu_register_set, intptr_t xmm_register_set);

View file

@ -1749,7 +1749,7 @@ ASSEMBLER_TEST_GENERATE(CompareSwapEQ, assembler) {
__ movq(RAX, Immediate(4));
__ movq(RCX, Immediate(0));
__ movq(Address(RSP, 0), RAX);
__ LockCmpxchgq(Address(RSP, 0), RCX);
__ lock_cmpxchgq(Address(RSP, 0), RCX);
__ popq(RAX);
__ ret();
}
@ -1767,7 +1767,7 @@ ASSEMBLER_TEST_GENERATE(CompareSwapNEQ, assembler) {
__ movq(RAX, Immediate(2));
__ movq(RCX, Immediate(4));
__ movq(Address(RSP, 0), RCX);
__ LockCmpxchgq(Address(RSP, 0), RCX);
__ lock_cmpxchgq(Address(RSP, 0), RCX);
__ popq(RAX);
__ ret();
}
@ -1779,47 +1779,6 @@ ASSEMBLER_TEST_RUN(CompareSwapNEQ, test) {
}
ASSEMBLER_TEST_GENERATE(CompareSwapEQ32, assembler) {
__ movq(RAX, Immediate(0x100000000));
__ pushq(RAX);
__ movq(RAX, Immediate(4));
__ movq(RCX, Immediate(0));
// 32 bit store of 4.
__ movl(Address(RSP, 0), RAX);
// Compare 32 bit memory location with RAX (4) and write 0.
__ LockCmpxchgl(Address(RSP, 0), RCX);
// Pop unchanged high word and zeroed out low word.
__ popq(RAX);
__ ret();
}
ASSEMBLER_TEST_RUN(CompareSwapEQ32, test) {
typedef intptr_t (*CompareSwapEQ32Code)();
EXPECT_EQ(0x100000000,
reinterpret_cast<CompareSwapEQ32Code>(test->entry())());
}
ASSEMBLER_TEST_GENERATE(CompareSwapNEQ32, assembler) {
__ movq(RAX, Immediate(0x100000000));
__ pushq(RAX);
__ movq(RAX, Immediate(2));
__ movq(RCX, Immediate(4));
__ movl(Address(RSP, 0), RCX);
__ LockCmpxchgl(Address(RSP, 0), RCX);
__ popq(RAX);
__ ret();
}
ASSEMBLER_TEST_RUN(CompareSwapNEQ32, test) {
typedef intptr_t (*CompareSwapNEQ32Code)();
EXPECT_EQ(0x100000004l,
reinterpret_cast<CompareSwapNEQ32Code>(test->entry())());
}
ASSEMBLER_TEST_GENERATE(Exchange, assembler) {
__ movq(RAX, Immediate(kLargeConstant));
__ movq(RDX, Immediate(kAnotherLargeConstant));

View file

@ -23,7 +23,7 @@ ForwardingCorpse* ForwardingCorpse::AsForwarder(uword addr, intptr_t size) {
ForwardingCorpse* result = reinterpret_cast<ForwardingCorpse*>(addr);
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::SizeTag::update(size, tags);
tags = RawObject::ClassIdTag::update(kForwardingCorpse, tags);
@ -262,16 +262,12 @@ void Become::ElementsForwardIdentity(const Array& before, const Array& after) {
ForwardObjectTo(before_obj, after_obj);
#if defined(HASH_IN_OBJECT_HEADER)
Object::SetCachedHash(after_obj, Object::GetCachedHash(before_obj));
#else
// Forward the identity hash too if it has one.
intptr_t hash = heap->GetHash(before_obj);
if (hash != 0) {
ASSERT(heap->GetHash(after_obj) == 0);
heap->SetHash(after_obj, hash);
}
#endif
}
{

View file

@ -52,10 +52,7 @@ class ForwardingCorpse {
private:
// This layout mirrors the layout of RawObject.
uint32_t tags_;
#if defined(HASH_IN_OBJECT_HEADER)
uint32_t hash_;
#endif
uword tags_;
RawObject* target_;
// Returns the address of the embedded size.

View file

@ -40,15 +40,12 @@ void Deserializer::InitializeHeader(RawObject* raw,
bool is_vm_isolate,
bool is_canonical) {
ASSERT(Utils::IsAligned(size, kObjectAlignment));
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::ClassIdTag::update(class_id, tags);
tags = RawObject::SizeTag::update(size, tags);
tags = RawObject::VMHeapObjectTag::update(is_vm_isolate, tags);
tags = RawObject::CanonicalObjectTag::update(is_canonical, tags);
raw->ptr()->tags_ = tags;
#if defined(HASH_IN_OBJECT_HEADER)
raw->ptr()->hash_ = 0;
#endif
}

View file

@ -22,18 +22,13 @@ FreeListElement* FreeListElement::AsElement(uword addr, intptr_t size) {
FreeListElement* result = reinterpret_cast<FreeListElement*>(addr);
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::SizeTag::update(size, tags);
tags = RawObject::ClassIdTag::update(kFreeListElement, tags);
// All words in a freelist element header should look like Smis.
ASSERT(!reinterpret_cast<RawObject*>(tags)->IsHeapObject());
result->tags_ = tags;
#if defined(HASH_IN_OBJECT_HEADER)
// Clearing this is mostly for neatness. The identityHashCode
// of free list entries is not used.
result->hash_ = 0;
#endif
if (size > RawObject::SizeTag::kMaxSizeTag) {
*result->SizeAddress() = size;
}

View file

@ -56,10 +56,7 @@ class FreeListElement {
private:
// This layout mirrors the layout of RawObject.
uint32_t tags_;
#if defined(HASH_IN_OBJECT_HEADER)
uint32_t hash_;
#endif
uword tags_;
FreeListElement* next_;
// Returns the address of the embedded size.

View file

@ -653,12 +653,11 @@ int64_t Heap::PeerCount() const {
return new_weak_tables_[kPeers]->count() + old_weak_tables_[kPeers]->count();
}
#if !defined(HASH_IN_OBJECT_HEADER)
int64_t Heap::HashCount() const {
return new_weak_tables_[kHashes]->count() +
old_weak_tables_[kHashes]->count();
}
#endif
int64_t Heap::ObjectIdCount() const {

View file

@ -33,14 +33,7 @@ class Heap {
kCode,
};
enum WeakSelector {
kPeers = 0,
#if !defined(HASH_IN_OBJECT_HEADER)
kHashes,
#endif
kObjectIds,
kNumWeakSelectors
};
enum WeakSelector { kPeers = 0, kHashes, kObjectIds, kNumWeakSelectors };
enum ApiCallbacks { kIgnoreApiCallbacks, kInvokeApiCallbacks };
@ -180,7 +173,6 @@ class Heap {
}
int64_t PeerCount() const;
#if !defined(HASH_IN_OBJECT_HEADER)
// Associate an identity hashCode with an object. An non-existent hashCode
// is equal to 0.
void SetHash(RawObject* raw_obj, intptr_t hash) {
@ -189,7 +181,6 @@ class Heap {
intptr_t GetHash(RawObject* raw_obj) const {
return GetWeakEntry(raw_obj, kHashes);
}
#endif
int64_t HashCount() const;
// Associate an id with an object (used when serializing an object).

View file

@ -1012,7 +1012,7 @@ EMIT_NATIVE_CODE(AllocateObject,
Isolate* isolate = Isolate::Current();
if (Heap::IsAllocatableInNewSpace(instance_size) &&
!cls().TraceAllocation(isolate)) {
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::SizeTag::update(instance_size, tags);
ASSERT(cls().id() != kIllegalCid);
tags = RawObject::ClassIdTag::update(cls().id(), tags);
@ -1046,7 +1046,6 @@ EMIT_NATIVE_CODE(AllocateObject,
tags = RawObject::SizeTag::update(instance_size, tags);
ASSERT(cls().id() != kIllegalCid);
tags = RawObject::ClassIdTag::update(cls().id(), tags);
// tags also has the initial zero hash code on 64 bit.
if (Smi::IsValid(tags)) {
const intptr_t tags_kidx = __ AddConstant(Smi::Handle(Smi::New(tags)));
__ AllocateOpt(locs()->out(0).reg(), tags_kidx);
@ -1658,7 +1657,6 @@ EMIT_NATIVE_CODE(Box, 1, Location::RequiresRegister(), LocationSummary::kCall) {
uword tags = 0;
tags = RawObject::SizeTag::update(instance_size, tags);
tags = RawObject::ClassIdTag::update(compiler->double_class().id(), tags);
// tags also has the initial zero hash code on 64 bit.
if (Smi::IsValid(tags)) {
const intptr_t tags_kidx = __ AddConstant(Smi::Handle(Smi::New(tags)));
__ AllocateOpt(out, tags_kidx);

View file

@ -1832,23 +1832,6 @@ void Intrinsifier::String_getHashCode(Assembler* assembler) {
}
void Intrinsifier::Object_getHash(Assembler* assembler) {
__ ldr(R0, Address(SP, 0 * kWordSize));
__ ldr(R0, FieldAddress(R0, String::hash_offset()), kUnsignedWord);
__ SmiTag(R0);
__ ret();
}
void Intrinsifier::Object_setHash(Assembler* assembler) {
__ ldr(R0, Address(SP, 1 * kWordSize)); // Object.
__ ldr(R1, Address(SP, 0 * kWordSize)); // Value.
__ SmiUntag(R1);
__ str(R1, FieldAddress(R0, String::hash_offset()), kUnsignedWord);
__ ret();
}
void GenerateSubstringMatchesSpecialization(Assembler* assembler,
intptr_t receiver_cid,
intptr_t other_cid,

View file

@ -1754,23 +1754,6 @@ void Intrinsifier::String_getHashCode(Assembler* assembler) {
}
void Intrinsifier::Object_getHash(Assembler* assembler) {
__ movq(RAX, Address(RSP, +1 * kWordSize)); // Object.
__ movl(RAX, FieldAddress(RAX, String::hash_offset()));
__ SmiTag(RAX);
__ ret();
}
void Intrinsifier::Object_setHash(Assembler* assembler) {
__ movq(RAX, Address(RSP, +2 * kWordSize)); // Object.
__ movq(RDX, Address(RSP, +1 * kWordSize)); // Value.
__ SmiUntag(RDX);
__ movl(FieldAddress(RAX, String::hash_offset()), RDX);
__ ret();
}
void GenerateSubstringMatchesSpecialization(Assembler* assembler,
intptr_t receiver_cid,
intptr_t other_cid,

View file

@ -139,7 +139,7 @@ namespace dart {
// List of intrinsics:
// (class-name, function-name, intrinsification method, fingerprint).
#define CORE_LIB_NON_HASH_INTRINSIC_LIST(V) \
#define CORE_LIB_INTRINSIC_LIST(V) \
V(_Smi, ~, Smi_bitNegate, Smi, 0x6574c6b0) \
V(_Smi, get:bitLength, Smi_bitLength, Smi, 0x25b356ab) \
V(_Smi, _bitAndFromSmi, Smi_bitAndFromSmi, Smi, 0x490a4da1) \
@ -190,19 +190,6 @@ namespace dart {
V(_TwoByteString, ==, TwoByteString_equality, Bool, 0x4719e83f) \
#define CORE_LIB_IN_HEADER_HASH_INTRINSIC_LIST(V) \
V(::, _getHash, Object_getHash, Smi, 0x2827856d) \
V(::, _setHash, Object_setHash, Object, 0x302d1fe8) \
#if defined(HASH_IN_OBJECT_HEADER)
#define CORE_LIB_INTRINSIC_LIST(V) \
CORE_LIB_NON_HASH_INTRINSIC_LIST(V) \
CORE_LIB_IN_HEADER_HASH_INTRINSIC_LIST(V)
#else
#define CORE_LIB_INTRINSIC_LIST(V) \
CORE_LIB_NON_HASH_INTRINSIC_LIST(V)
#endif
#define CORE_INTEGER_LIB_INTRINSIC_LIST(V) \
V(_IntegerImplementation, _addFromInteger, Integer_addFromInteger, \
Dynamic, 0x6a10c54a) \

View file

@ -992,17 +992,10 @@ void Object::InitOnce(Isolate* isolate) {
// An object visitor which will mark all visited objects. This is used to
// premark all objects in the vm_isolate_ heap. Also precalculates hash
// codes so that we can get the identity hash code of objects in the read-
// only VM isolate.
class FinalizeVMIsolateVisitor : public ObjectVisitor {
// premark all objects in the vm_isolate_ heap.
class PremarkingVisitor : public ObjectVisitor {
public:
FinalizeVMIsolateVisitor()
#if defined(HASH_IN_OBJECT_HEADER)
: counter_(1337)
#endif
{
}
PremarkingVisitor() {}
void VisitObject(RawObject* obj) {
// Free list elements should never be marked.
@ -1012,35 +1005,8 @@ class FinalizeVMIsolateVisitor : public ObjectVisitor {
if (!obj->IsFreeListElement()) {
ASSERT(obj->IsVMHeapObject());
obj->SetMarkBitUnsynchronized();
if (obj->IsStringInstance()) {
RawString* str = reinterpret_cast<RawString*>(obj);
intptr_t hash = String::Hash(str);
String::SetCachedHash(str, hash);
}
#if defined(HASH_IN_OBJECT_HEADER)
// These objects end up in the read-only VM isolate which is shared
// between isolates, so we have to prepopulate them with identity hash
// codes, since we can't add hash codes later.
if (Object::GetCachedHash(obj) == 0) {
// Some classes have identity hash codes that depend on their contents,
// not per object.
ASSERT(!obj->IsStringInstance());
if (!obj->IsMint() && !obj->IsDouble() && !obj->IsBigint() &&
!obj->IsRawNull() && !obj->IsBool()) {
counter_ += 2011; // The year Dart was announced and a prime.
counter_ &= 0x3fffffff;
if (counter_ == 0) counter_++;
Object::SetCachedHash(obj, counter_);
}
}
#endif
}
}
private:
#if defined(HASH_IN_OBJECT_HEADER)
int counter_;
#endif
};
@ -1120,7 +1086,7 @@ void Object::FinalizeVMIsolate(Isolate* isolate) {
{
ASSERT(isolate == Dart::vm_isolate());
WritableVMIsolateScope scope(Thread::Current());
FinalizeVMIsolateVisitor premarker;
PremarkingVisitor premarker;
ASSERT(isolate->heap()->UsedInWords(Heap::kNew) == 0);
isolate->heap()->IterateOldObjectsNoImagePages(&premarker);
// Make the VM isolate read-only again after setting all objects as marked.
@ -1155,15 +1121,13 @@ void Object::MakeUnusedSpaceTraversable(const Object& obj,
reinterpret_cast<RawTypedData*>(RawObject::FromAddr(addr));
uword new_tags = RawObject::ClassIdTag::update(kTypedDataInt8ArrayCid, 0);
new_tags = RawObject::SizeTag::update(leftover_size, new_tags);
uint32_t tags = raw->ptr()->tags_;
uint32_t old_tags;
uword tags = raw->ptr()->tags_;
uword old_tags;
// TODO(iposva): Investigate whether CompareAndSwapWord is necessary.
do {
old_tags = tags;
// We can't use obj.CompareAndSwapTags here because we don't have a
// handle for the new object.
tags = AtomicOperations::CompareAndSwapUint32(&raw->ptr()->tags_,
old_tags, new_tags);
tags = AtomicOperations::CompareAndSwapWord(&raw->ptr()->tags_,
old_tags, new_tags);
} while (tags != old_tags);
intptr_t leftover_len = (leftover_size - TypedData::InstanceSize(0));
@ -1175,12 +1139,13 @@ void Object::MakeUnusedSpaceTraversable(const Object& obj,
RawObject* raw = reinterpret_cast<RawObject*>(RawObject::FromAddr(addr));
uword new_tags = RawObject::ClassIdTag::update(kInstanceCid, 0);
new_tags = RawObject::SizeTag::update(leftover_size, new_tags);
uint32_t tags = raw->ptr()->tags_;
uint32_t old_tags;
uword tags = raw->ptr()->tags_;
uword old_tags;
// TODO(iposva): Investigate whether CompareAndSwapWord is necessary.
do {
old_tags = tags;
tags = obj.CompareAndSwapTags(old_tags, new_tags);
tags = AtomicOperations::CompareAndSwapWord(&raw->ptr()->tags_,
old_tags, new_tags);
} while (tags != old_tags);
}
}
@ -1902,15 +1867,12 @@ void Object::InitializeObject(uword address,
*reinterpret_cast<uword*>(cur) = initial_value;
cur += kWordSize;
}
uint32_t tags = 0;
uword tags = 0;
ASSERT(class_id != kIllegalCid);
tags = RawObject::ClassIdTag::update(class_id, tags);
tags = RawObject::SizeTag::update(size, tags);
tags = RawObject::VMHeapObjectTag::update(is_vm_object, tags);
reinterpret_cast<RawObject*>(address)->tags_ = tags;
#if defined(HASH_IN_OBJECT_HEADER)
reinterpret_cast<RawObject*>(address)->hash_ = 0;
#endif
ASSERT(is_vm_object == RawObject::IsVMHeapObject(tags));
}
@ -20365,35 +20327,6 @@ static intptr_t HashImpl(const T* characters, intptr_t len) {
}
intptr_t String::Hash(RawString* raw) {
StringHasher hasher;
uword length = Smi::Value(raw->ptr()->length_);
if (raw->IsOneByteString() || raw->IsExternalOneByteString()) {
const uint8_t* data;
if (raw->IsOneByteString()) {
data = reinterpret_cast<RawOneByteString*>(raw)->ptr()->data();
} else {
ASSERT(raw->IsExternalOneByteString());
RawExternalOneByteString* str =
reinterpret_cast<RawExternalOneByteString*>(raw);
data = str->ptr()->external_data_->data();
}
return String::Hash(data, length);
} else {
const uint16_t* data;
if (raw->IsTwoByteString()) {
data = reinterpret_cast<RawTwoByteString*>(raw)->ptr()->data();
} else {
ASSERT(raw->IsExternalTwoByteString());
RawExternalTwoByteString* str =
reinterpret_cast<RawExternalTwoByteString*>(raw);
data = str->ptr()->external_data_->data();
}
return String::Hash(data, length);
}
}
intptr_t String::Hash(const char* characters, intptr_t len) {
return HashImpl(characters, len);
}
@ -21214,11 +21147,11 @@ RawString* String::MakeExternal(void* array,
// Update the class information of the object.
const intptr_t class_id = kExternalOneByteStringCid;
uint32_t tags = raw_ptr()->tags_;
uint32_t old_tags;
uword tags = raw_ptr()->tags_;
uword old_tags;
do {
old_tags = tags;
uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags);
uword new_tags = RawObject::SizeTag::update(used_size, old_tags);
new_tags = RawObject::ClassIdTag::update(class_id, new_tags);
tags = CompareAndSwapTags(old_tags, new_tags);
} while (tags != old_tags);
@ -21251,11 +21184,11 @@ RawString* String::MakeExternal(void* array,
// Update the class information of the object.
const intptr_t class_id = kExternalTwoByteStringCid;
uint32_t tags = raw_ptr()->tags_;
uint32_t old_tags;
uword tags = raw_ptr()->tags_;
uword old_tags;
do {
old_tags = tags;
uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags);
uword new_tags = RawObject::SizeTag::update(used_size, old_tags);
new_tags = RawObject::ClassIdTag::update(class_id, new_tags);
tags = CompareAndSwapTags(old_tags, new_tags);
} while (tags != old_tags);
@ -22143,11 +22076,11 @@ void Array::MakeImmutable() const {
if (IsImmutable()) return;
ASSERT(!IsCanonical());
NoSafepointScope no_safepoint;
uint32_t tags = raw_ptr()->tags_;
uint32_t old_tags;
uword tags = raw_ptr()->tags_;
uword old_tags;
do {
old_tags = tags;
uint32_t new_tags =
uword new_tags =
RawObject::ClassIdTag::update(kImmutableArrayCid, old_tags);
tags = CompareAndSwapTags(old_tags, new_tags);
} while (tags != old_tags);
@ -22189,7 +22122,6 @@ RawArray* Array::Grow(const Array& source,
RawArray* Array::MakeArray(const GrowableObjectArray& growable_array) {
ASSERT(!growable_array.IsNull());
ASSERT(growable_array.IsGrowableObjectArray());
intptr_t used_len = growable_array.Length();
// Get the type arguments and prepare to copy them.
const TypeArguments& type_arguments =
@ -22202,7 +22134,6 @@ RawArray* Array::MakeArray(const GrowableObjectArray& growable_array) {
intptr_t capacity_len = growable_array.Capacity();
Zone* zone = Thread::Current()->zone();
const Array& array = Array::Handle(zone, growable_array.data());
ASSERT(array.IsArray());
array.SetTypeArguments(type_arguments);
intptr_t capacity_size = Array::InstanceSize(capacity_len);
intptr_t used_size = Array::InstanceSize(used_len);
@ -22216,10 +22147,10 @@ RawArray* Array::MakeArray(const GrowableObjectArray& growable_array) {
// Update the size in the header field and length of the array object.
uword tags = array.raw_ptr()->tags_;
ASSERT(kArrayCid == RawObject::ClassIdTag::decode(tags));
uint32_t old_tags;
uword old_tags;
do {
old_tags = tags;
uint32_t new_tags = RawObject::SizeTag::update(used_size, old_tags);
uword new_tags = RawObject::SizeTag::update(used_size, old_tags);
tags = array.CompareAndSwapTags(old_tags, new_tags);
} while (tags != old_tags);
// TODO(22501): For the heap to remain walkable by the sweeper, it must

View file

@ -245,9 +245,9 @@ class Object {
RawObject* raw() const { return raw_; }
void operator=(RawObject* value) { initializeHandle(this, value); }
uint32_t CompareAndSwapTags(uint32_t old_tags, uint32_t new_tags) const {
return AtomicOperations::CompareAndSwapUint32(&raw()->ptr()->tags_,
old_tags, new_tags);
uword CompareAndSwapTags(uword old_tags, uword new_tags) const {
return AtomicOperations::CompareAndSwapWord(&raw()->ptr()->tags_, old_tags,
new_tags);
}
bool IsCanonical() const { return raw()->IsCanonical(); }
void SetCanonical() const { raw()->SetCanonical(); }
@ -434,11 +434,13 @@ class Object {
#if defined(HASH_IN_OBJECT_HEADER)
static uint32_t GetCachedHash(const RawObject* obj) {
return obj->ptr()->hash_;
uword tags = obj->ptr()->tags_;
return tags >> 32;
}
static void SetCachedHash(RawObject* obj, uint32_t hash) {
obj->ptr()->hash_ = hash;
static void SetCachedHash(RawObject* obj, uintptr_t hash) {
ASSERT(hash >> 32 == 0);
obj->ptr()->tags_ |= hash << 32;
}
#endif
@ -6829,14 +6831,16 @@ class String : public Instance {
return result;
}
static intptr_t Hash(RawString* raw);
bool HasHash() const {
ASSERT(Smi::New(0) == NULL);
return GetCachedHash(raw()) != 0;
}
#if defined(HASH_IN_OBJECT_HEADER)
static intptr_t hash_offset() { return kInt32Size; } // Wrong for big-endian?
#else
static intptr_t hash_offset() { return OFFSET_OF(RawString, hash_); }
#endif
static intptr_t Hash(const String& str, intptr_t begin_index, intptr_t len);
static intptr_t Hash(const char* characters, intptr_t len);
static intptr_t Hash(const uint16_t* characters, intptr_t len);

View file

@ -1322,7 +1322,7 @@ class CodeLookupTableBuilder : public ObjectVisitor {
~CodeLookupTableBuilder() {}
void VisitObject(RawObject* raw_obj) {
uint32_t tags = raw_obj->ptr()->tags_;
uword tags = raw_obj->ptr()->tags_;
if (RawObject::ClassIdTag::decode(tags) == kCodeCid) {
RawCode* raw_code = reinterpret_cast<RawCode*>(raw_obj);
const Code& code = Code::Handle(raw_code);

View file

@ -30,10 +30,10 @@ void RawObject::Validate(Isolate* isolate) const {
FATAL("RAW_NULL encountered");
}
// Validate that the tags_ field is sensible.
uint32_t tags = ptr()->tags_;
uword tags = ptr()->tags_;
intptr_t reserved = ReservedBits::decode(tags);
if (reserved != 0) {
FATAL1("Invalid tags field encountered %x\n", tags);
FATAL1("Invalid tags field encountered %#" Px "\n", tags);
}
intptr_t class_id = ClassIdTag::decode(tags);
if (!isolate->class_table()->IsValidIndex(class_id)) {
@ -185,7 +185,7 @@ intptr_t RawObject::SizeFromClass() const {
ClassTable* class_table = isolate->class_table();
if (!class_table->IsValidIndex(class_id) ||
!class_table->HasValidClassAt(class_id)) {
FATAL2("Invalid class id: %" Pd " from tags %x\n", class_id,
FATAL2("Invalid class id: %" Pd " from tags %" Px "\n", class_id,
ptr()->tags_);
}
#endif // DEBUG
@ -196,7 +196,7 @@ intptr_t RawObject::SizeFromClass() const {
}
ASSERT(instance_size != 0);
#if defined(DEBUG)
uint32_t tags = ptr()->tags_;
uword tags = ptr()->tags_;
intptr_t tags_size = SizeTag::decode(tags);
if ((class_id == kArrayCid) && (instance_size > tags_size && tags_size > 0)) {
// TODO(22501): Array::MakeArray could be in the process of shrinking
@ -211,7 +211,7 @@ intptr_t RawObject::SizeFromClass() const {
} while ((instance_size > tags_size) && (--retries_remaining > 0));
}
if ((instance_size != tags_size) && (tags_size != 0)) {
FATAL3("Size mismatch: %" Pd " from class vs %" Pd " from tags %x\n",
FATAL3("Size mismatch: %" Pd " from class vs %" Pd " from tags %" Px "\n",
instance_size, tags_size, tags);
}
#endif // DEBUG
@ -524,7 +524,7 @@ intptr_t RawNamespace::VisitNamespacePointers(RawNamespace* raw_obj,
bool RawCode::ContainsPC(RawObject* raw_obj, uword pc) {
uint32_t tags = raw_obj->ptr()->tags_;
uword tags = raw_obj->ptr()->tags_;
if (RawObject::ClassIdTag::decode(tags) == kCodeCid) {
RawCode* raw_code = reinterpret_cast<RawCode*>(raw_obj);
return RawInstructions::ContainsPC(raw_code->ptr()->instructions_, pc);
@ -737,7 +737,7 @@ intptr_t RawInstance::VisitInstancePointers(RawInstance* raw_obj,
ObjectPointerVisitor* visitor) {
// Make sure that we got here with the tagged pointer as this.
ASSERT(raw_obj->IsHeapObject());
uint32_t tags = raw_obj->ptr()->tags_;
uword tags = raw_obj->ptr()->tags_;
intptr_t instance_size = SizeTag::decode(tags);
if (instance_size == 0) {
RawClass* cls =

View file

@ -271,10 +271,6 @@ class RawObject {
kSizeTagSize = 8,
kClassIdTagPos = kSizeTagPos + kSizeTagSize, // = 16
kClassIdTagSize = 16,
#if defined(HASH_IN_OBJECT_HEADER)
kHashTagPos = kClassIdTagPos + kClassIdTagSize, // = 32
kHashTagSize = 16,
#endif
};
COMPILE_ASSERT(kClassIdTagSize == (sizeof(classid_t) * kBitsPerByte));
@ -300,7 +296,7 @@ class RawObject {
private:
// The actual unscaled bit field used within the tag field.
class SizeBits
: public BitField<uint32_t, intptr_t, kSizeTagPos, kSizeTagSize> {};
: public BitField<uword, intptr_t, kSizeTagPos, kSizeTagSize> {};
static intptr_t SizeToTagValue(intptr_t size) {
ASSERT(Utils::IsAligned(size, kObjectAlignment));
@ -312,7 +308,7 @@ class RawObject {
};
class ClassIdTag
: public BitField<uint32_t, intptr_t, kClassIdTagPos, kClassIdTagSize> {};
: public BitField<uword, intptr_t, kClassIdTagPos, kClassIdTagSize> {};
bool IsWellFormed() const {
uword value = reinterpret_cast<uword>(this);
@ -356,7 +352,7 @@ class RawObject {
}
void SetMarkBitUnsynchronized() {
ASSERT(!IsMarked());
uint32_t tags = ptr()->tags_;
uword tags = ptr()->tags_;
ptr()->tags_ = MarkBit::update(true, tags);
}
void ClearMarkBit() {
@ -382,12 +378,12 @@ class RawObject {
}
void SetRememberedBitUnsynchronized() {
ASSERT(!IsRemembered());
uint32_t tags = ptr()->tags_;
uword tags = ptr()->tags_;
ptr()->tags_ = RememberedBit::update(true, tags);
}
void ClearRememberedBit() { UpdateTagBit<RememberedBit>(false); }
void ClearRememberedBitUnsynchronized() {
uint32_t tags = ptr()->tags_;
uword tags = ptr()->tags_;
ptr()->tags_ = RememberedBit::update(false, tags);
}
// Returns false if the bit was already set.
@ -413,7 +409,6 @@ class RawObject {
#undef DEFINE_IS_CID
bool IsStringInstance() const { return IsStringClassId(GetClassId()); }
bool IsRawNull() const { return GetClassId() == kNullCid; }
bool IsDartInstance() const {
return (!IsHeapObject() || (GetClassId() >= kInstanceCid));
}
@ -428,7 +423,7 @@ class RawObject {
}
intptr_t Size() const {
uint32_t tags = ptr()->tags_;
uword tags = ptr()->tags_;
intptr_t result = SizeTag::decode(tags);
if (result != 0) {
#if defined(DEBUG)
@ -538,25 +533,18 @@ class RawObject {
static intptr_t NumberOfTypedDataClasses();
private:
uint32_t tags_; // Various object tags (bits).
#if defined(HASH_IN_OBJECT_HEADER)
// On 64 bit there is a hash field in the header for the identity hash.
uint32_t hash_;
#endif
uword tags_; // Various object tags (bits).
class MarkBit : public BitField<uint32_t, bool, kMarkBit, 1> {};
class MarkBit : public BitField<uword, bool, kMarkBit, 1> {};
class RememberedBit : public BitField<uint32_t, bool, kRememberedBit, 1> {};
class RememberedBit : public BitField<uword, bool, kRememberedBit, 1> {};
class CanonicalObjectTag : public BitField<uint32_t, bool, kCanonicalBit, 1> {
};
class CanonicalObjectTag : public BitField<uword, bool, kCanonicalBit, 1> {};
class VMHeapObjectTag : public BitField<uint32_t, bool, kVMHeapObjectBit, 1> {
};
class VMHeapObjectTag : public BitField<uword, bool, kVMHeapObjectBit, 1> {};
class ReservedBits
: public BitField<uint32_t, intptr_t, kReservedTagPos, kReservedTagSize> {
};
: public BitField<uword, intptr_t, kReservedTagPos, kReservedTagSize> {};
// TODO(koda): After handling tags_, return const*, like Object::raw_ptr().
RawObject* ptr() const {
@ -571,37 +559,37 @@ class RawObject {
intptr_t SizeFromClass() const;
intptr_t GetClassId() const {
uint32_t tags = ptr()->tags_;
uword tags = ptr()->tags_;
return ClassIdTag::decode(tags);
}
void SetClassId(intptr_t new_cid) {
uint32_t tags = ptr()->tags_;
uword tags = ptr()->tags_;
ptr()->tags_ = ClassIdTag::update(new_cid, tags);
}
template <class TagBitField>
void UpdateTagBit(bool value) {
uint32_t tags = ptr()->tags_;
uint32_t old_tags;
uword tags = ptr()->tags_;
uword old_tags;
do {
old_tags = tags;
uint32_t new_tags = TagBitField::update(value, old_tags);
tags = AtomicOperations::CompareAndSwapUint32(&ptr()->tags_, old_tags,
new_tags);
uword new_tags = TagBitField::update(value, old_tags);
tags = AtomicOperations::CompareAndSwapWord(&ptr()->tags_, old_tags,
new_tags);
} while (tags != old_tags);
}
template <class TagBitField>
bool TryAcquireTagBit() {
uint32_t tags = ptr()->tags_;
uint32_t old_tags;
uword tags = ptr()->tags_;
uword old_tags;
do {
old_tags = tags;
if (TagBitField::decode(tags)) return false;
uint32_t new_tags = TagBitField::update(true, old_tags);
tags = AtomicOperations::CompareAndSwapUint32(&ptr()->tags_, old_tags,
new_tags);
uword new_tags = TagBitField::update(true, old_tags);
tags = AtomicOperations::CompareAndSwapWord(&ptr()->tags_, old_tags,
new_tags);
} while (tags != old_tags);
return true;
}
@ -1330,10 +1318,7 @@ class RawPcDescriptors : public RawObject {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(PcDescriptors);
// Number of descriptors. This only needs to be an int32_t, but we make it a
// uword so that the variable length data is 64 bit aligned on 64 bit
// platforms.
uword length_;
int32_t length_; // Number of descriptors.
// Variable length data follows here.
uint8_t* data() { OPEN_ARRAY_START(uint8_t, intptr_t); }
@ -1349,9 +1334,7 @@ class RawCodeSourceMap : public RawObject {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(CodeSourceMap);
// Length in bytes. This only needs to be an int32_t, but we make it a uword
// so that the variable length data is 64 bit aligned on 64 bit platforms.
uword length_;
int32_t length_; // Length in bytes.
// Variable length data follows here.
uint8_t* data() { OPEN_ARRAY_START(uint8_t, intptr_t); }
@ -1378,9 +1361,8 @@ class RawStackMap : public RawObject {
int32_t slow_path_bit_count_; // Slow path live values, included in length_.
// Offset from code entry point corresponding to this stack map
// representation. This only needs to be an int32_t, but we make it a uword
// so that the variable length data is 64 bit aligned on 64 bit platforms.
uword pc_offset_;
// representation.
uint32_t pc_offset_;
// Variable length data follows here (bitmap of the stack layout).
uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
@ -1434,10 +1416,7 @@ class RawLocalVarDescriptors : public RawObject {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(LocalVarDescriptors);
// Number of descriptors. This only needs to be an int32_t, but we make it a
// uword so that the variable length data is 64 bit aligned on 64 bit
// platforms.
uword num_entries_;
int32_t num_entries_; // Number of descriptors.
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->names()[0]);
@ -1945,9 +1924,8 @@ class RawOneByteString : public RawString {
const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
friend class ApiMessageReader;
friend class RODataSerializationCluster;
friend class SnapshotReader;
friend class String;
friend class RODataSerializationCluster;
};
@ -1958,9 +1936,8 @@ class RawTwoByteString : public RawString {
uint16_t* data() { OPEN_ARRAY_START(uint16_t, uint16_t); }
const uint16_t* data() const { OPEN_ARRAY_START(uint16_t, uint16_t); }
friend class RODataSerializationCluster;
friend class SnapshotReader;
friend class String;
friend class RODataSerializationCluster;
};
@ -1996,7 +1973,6 @@ class RawExternalOneByteString : public RawString {
private:
ExternalData* external_data_;
friend class Api;
friend class String;
};
@ -2009,7 +1985,6 @@ class RawExternalTwoByteString : public RawString {
private:
ExternalData* external_data_;
friend class Api;
friend class String;
};

View file

@ -1225,13 +1225,6 @@ intptr_t Simulator::ReadExclusiveX(uword addr, Instr* instr) {
}
intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) {
MutexLocker ml(exclusive_access_lock_);
SetExclusiveAccess(addr);
return ReadWU(addr, instr);
}
intptr_t Simulator::WriteExclusiveX(uword addr, intptr_t value, Instr* instr) {
MutexLocker ml(exclusive_access_lock_);
bool write_allowed = HasExclusiveAccessAndOpen(addr);
@ -1243,17 +1236,6 @@ intptr_t Simulator::WriteExclusiveX(uword addr, intptr_t value, Instr* instr) {
}
intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) {
MutexLocker ml(exclusive_access_lock_);
bool write_allowed = HasExclusiveAccessAndOpen(addr);
if (write_allowed) {
WriteW(addr, value, instr);
return 0; // Success.
}
return 1; // Failure.
}
uword Simulator::CompareExchange(uword* address,
uword compare_value,
uword new_value) {
@ -2217,37 +2199,25 @@ void Simulator::DecodeLoadStoreExclusive(Instr* instr) {
UNIMPLEMENTED();
}
const int32_t size = instr->Bits(30, 2);
if (size != 3 && size != 2) {
if (size != 3) {
UNIMPLEMENTED();
}
const Register rs = instr->RsField();
const Register rn = instr->RnField();
const Register rt = instr->RtField();
const bool is_load = instr->Bit(22) == 1;
if (is_load) {
// Format(instr, "ldxr 'rt, 'rn");
if (size == 3) {
const int64_t addr = get_register(rn, R31IsSP);
intptr_t value = ReadExclusiveX(addr, instr);
set_register(instr, rt, value, R31IsSP);
} else {
const int64_t addr = get_register(rn, R31IsSP);
intptr_t value = ReadExclusiveW(addr, instr);
set_register(instr, rt, value, R31IsSP);
}
const int64_t addr = get_register(rn, R31IsSP);
intptr_t value = ReadExclusiveX(addr, instr);
set_register(instr, rt, value, R31IsSP);
} else {
// Format(instr, "stxr 'rs, 'rt, 'rn");
if (size == 3) {
uword value = get_register(rt, R31IsSP);
uword addr = get_register(rn, R31IsSP);
intptr_t status = WriteExclusiveX(addr, value, instr);
set_register(instr, rs, status, R31IsSP);
} else {
uint32_t value = get_register(rt, R31IsSP);
uword addr = get_register(rn, R31IsSP);
intptr_t status = WriteExclusiveW(addr, value, instr);
set_register(instr, rs, status, R31IsSP);
}
uword value = get_register(rt, R31IsSP);
uword addr = get_register(rn, R31IsSP);
intptr_t status = WriteExclusiveX(addr, value, instr);
set_register(instr, rs, status, R31IsSP);
}
}

View file

@ -207,9 +207,6 @@ class Simulator {
void ClearExclusive();
intptr_t ReadExclusiveX(uword addr, Instr* instr);
intptr_t WriteExclusiveX(uword addr, intptr_t value, Instr* instr);
// 32 bit versions.
intptr_t ReadExclusiveW(uword addr, Instr* instr);
intptr_t WriteExclusiveW(uword addr, intptr_t value, Instr* instr);
// Set access to given address to 'exclusive state' for current thread.
static void SetExclusiveAccess(uword addr);

View file

@ -322,7 +322,6 @@ class SimulatorHelpers {
uword tags = 0;
tags = RawObject::ClassIdTag::update(kDoubleCid, tags);
tags = RawObject::SizeTag::update(instance_size, tags);
// Also writes zero in the hash_ field.
*reinterpret_cast<uword*>(start + Double::tags_offset()) = tags;
*reinterpret_cast<double*>(start + Double::value_offset()) = value;
return reinterpret_cast<RawObject*>(start + kHeapObjectTag);
@ -2856,10 +2855,9 @@ RawObject* Simulator::Call(const Code& code,
const intptr_t instance_size = Context::InstanceSize(num_context_variables);
const uword start = thread->heap()->new_space()->TryAllocate(instance_size);
if (LIKELY(start != 0)) {
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::ClassIdTag::update(kContextCid, tags);
tags = RawObject::SizeTag::update(instance_size, tags);
// Also writes 0 in the hash_ field of the header.
*reinterpret_cast<uword*>(start + Array::tags_offset()) = tags;
*reinterpret_cast<uword*>(start + Context::num_variables_offset()) =
num_context_variables;
@ -2900,7 +2898,6 @@ RawObject* Simulator::Call(const Code& code,
const intptr_t instance_size = RawObject::SizeTag::decode(tags);
const uword start = thread->heap()->new_space()->TryAllocate(instance_size);
if (LIKELY(start != 0)) {
// Writes both the tags and the initial identity hash on 64 bit platforms.
*reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags;
for (intptr_t current_offset = sizeof(RawInstance);
current_offset < instance_size; current_offset += kWordSize) {
@ -2932,7 +2929,6 @@ RawObject* Simulator::Call(const Code& code,
if (LIKELY(start != 0)) {
RawObject* type_args = SP[0];
const intptr_t type_args_offset = Bytecode::DecodeD(*pc);
// Writes both the tags and the initial identity hash on 64 bit platforms.
*reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags;
for (intptr_t current_offset = sizeof(RawInstance);
current_offset < instance_size; current_offset += kWordSize) {
@ -2976,8 +2972,6 @@ RawObject* Simulator::Call(const Code& code,
tags = RawObject::SizeTag::update(instance_size, tags);
}
tags = RawObject::ClassIdTag::update(cid, tags);
// Writes both the tags and the initial identity hash on 64 bit
// platforms.
*reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags;
*reinterpret_cast<RawObject**>(start + Array::length_offset()) =
FP[rB];

View file

@ -755,9 +755,6 @@ void ImageWriter::WriteROData(WriteStream* stream) {
uword marked_tags = obj.raw()->ptr()->tags_;
marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags);
marked_tags = RawObject::MarkBit::update(true, marked_tags);
#if defined(HASH_IN_OBJECT_HEADER)
marked_tags |= static_cast<uword>(obj.raw()->ptr()->hash_) << 32;
#endif
stream->WriteWord(marked_tags);
start += sizeof(uword);
for (uword* cursor = reinterpret_cast<uword*>(start);
@ -844,11 +841,6 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
uword marked_tags = insns.raw_ptr()->tags_;
marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags);
marked_tags = RawObject::MarkBit::update(true, marked_tags);
#if defined(HASH_IN_OBJECT_HEADER)
// Can't use GetObjectTagsAndHash because the update methods discard the
// high bits.
marked_tags |= static_cast<uword>(insns.raw_ptr()->hash_) << 32;
#endif
WriteWordLiteralText(marked_tags);
beginning += sizeof(uword);
@ -1054,11 +1046,6 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
uword marked_tags = insns.raw_ptr()->tags_;
marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags);
marked_tags = RawObject::MarkBit::update(true, marked_tags);
#if defined(HASH_IN_OBJECT_HEADER)
// Can't use GetObjectTagsAndHash because the update methods discard the
// high bits.
marked_tags |= static_cast<uword>(insns.raw_ptr()->hash_) << 32;
#endif
instructions_blob_stream_.WriteWord(marked_tags);
beginning += sizeof(uword);
@ -1363,20 +1350,11 @@ void SnapshotWriter::WriteObject(RawObject* rawobj) {
}
uint32_t SnapshotWriter::GetObjectTags(RawObject* raw) {
uword SnapshotWriter::GetObjectTags(RawObject* raw) {
return raw->ptr()->tags_;
}
uword SnapshotWriter::GetObjectTagsAndHash(RawObject* raw) {
uword result = raw->ptr()->tags_;
#if defined(HASH_IN_OBJECT_HEADER)
result |= static_cast<uword>(raw->ptr()->hash_) << 32;
#endif
return result;
}
#define VM_OBJECT_CLASS_LIST(V) \
V(OneByteString) \
V(TwoByteString) \
@ -1600,7 +1578,7 @@ void SnapshotWriter::WriteObjectImpl(RawObject* raw, bool as_reference) {
// When we know that we are dealing with leaf or shallow objects we write
// these objects inline even when 'as_reference' is true.
const bool write_as_reference = as_reference && !raw->IsCanonical();
uintptr_t tags = GetObjectTagsAndHash(raw);
intptr_t tags = raw->ptr()->tags_;
// Add object to the forward ref list and mark it so that future references
// to this object in the snapshot will use this object id. Mark the
@ -1677,7 +1655,7 @@ class WriteInlinedObjectVisitor : public ObjectVisitor {
virtual void VisitObject(RawObject* obj) {
intptr_t object_id = writer_->forward_list_->FindObject(obj);
ASSERT(object_id != kInvalidIndex);
intptr_t tags = MessageWriter::GetObjectTagsAndHash(obj);
intptr_t tags = writer_->GetObjectTags(obj);
writer_->WriteMarkedObjectImpl(obj, tags, object_id, kAsInlinedObject);
}
@ -1842,7 +1820,7 @@ RawFunction* SnapshotWriter::IsSerializableClosure(RawClosure* closure) {
RawClass* SnapshotWriter::GetFunctionOwner(RawFunction* func) {
RawObject* owner = func->ptr()->owner_;
uint32_t tags = GetObjectTags(owner);
uword tags = GetObjectTags(owner);
intptr_t class_id = RawObject::ClassIdTag::decode(tags);
if (class_id == kClassCid) {
return reinterpret_cast<RawClass*>(owner);

View file

@ -842,8 +842,7 @@ class SnapshotWriter : public BaseWriter {
// Serialize an object into the buffer.
void WriteObject(RawObject* raw);
static uint32_t GetObjectTags(RawObject* raw);
static uword GetObjectTagsAndHash(RawObject* raw);
uword GetObjectTags(RawObject* raw);
Exceptions::ExceptionType exception_type() const { return exception_type_; }
void set_exception_type(Exceptions::ExceptionType type) {

View file

@ -1152,7 +1152,7 @@ void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
// R1: next object start.
// R9: allocation stats table.
// Set the tags.
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::SizeTag::update(instance_size, tags);
ASSERT(cls.id() != kIllegalCid);
tags = RawObject::ClassIdTag::update(cls.id(), tags);

View file

@ -1090,7 +1090,7 @@ void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) {
Label add_to_buffer;
// Check whether this object has already been remembered. Skip adding to the
// store buffer if the object is in the store buffer already.
__ LoadFieldFromOffset(TMP, R0, Object::tags_offset(), kWord);
__ LoadFieldFromOffset(TMP, R0, Object::tags_offset());
__ tsti(TMP, Immediate(1 << RawObject::kRememberedBit));
__ b(&add_to_buffer, EQ);
__ ret();
@ -1105,13 +1105,11 @@ void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) {
ASSERT(Object::tags_offset() == 0);
__ sub(R3, R0, Operand(kHeapObjectTag));
// R3: Untagged address of header word (ldxr/stxr do not support offsets).
// Note that we use 32 bit operations here to match the size of the
// background sweeper which is also manipulating this 32 bit word.
Label retry;
__ Bind(&retry);
__ ldxr(R2, R3, kWord);
__ ldxr(R2, R3);
__ orri(R2, R2, Immediate(1 << RawObject::kRememberedBit));
__ stxr(R1, R2, R3, kWord);
__ stxr(R1, R2, R3);
__ cmp(R1, Operand(1));
__ b(&retry, EQ);
@ -1198,12 +1196,11 @@ void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
// R3: next object start.
// R1: new object type arguments (if is_cls_parameterized).
// Set the tags.
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::SizeTag::update(instance_size, tags);
ASSERT(cls.id() != kIllegalCid);
tags = RawObject::ClassIdTag::update(cls.id(), tags);
__ LoadImmediate(R0, tags);
// 64 bit store also zeros the hash_field.
__ StoreToOffset(R0, R2, Instance::tags_offset());
// Initialize the remaining words of the object.

View file

@ -1078,7 +1078,7 @@ void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
// EBX: next object start.
// EDX: new object type arguments (if is_cls_parameterized).
// Set the tags.
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::SizeTag::update(instance_size, tags);
ASSERT(cls.id() != kIllegalCid);
tags = RawObject::ClassIdTag::update(cls.id(), tags);

View file

@ -1215,7 +1215,7 @@ void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
// T3: next object start.
// T1: new object type arguments (if is_cls_parameterized).
// Set the tags.
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::SizeTag::update(instance_size, tags);
ASSERT(cls.id() != kIllegalCid);
tags = RawObject::ClassIdTag::update(cls.id(), tags);

View file

@ -1034,23 +1034,21 @@ void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) {
// RDX: Address being stored
Label reload;
__ Bind(&reload);
__ movl(RAX, FieldAddress(RDX, Object::tags_offset()));
__ testl(RAX, Immediate(1 << RawObject::kRememberedBit));
__ movq(RAX, FieldAddress(RDX, Object::tags_offset()));
__ testq(RAX, Immediate(1 << RawObject::kRememberedBit));
__ j(EQUAL, &add_to_buffer, Assembler::kNearJump);
__ popq(RCX);
__ popq(RAX);
__ ret();
// Update the tags that this object has been remembered.
// Note that we use 32 bit operations here to match the size of the
// background sweeper which is also manipulating this 32 bit word.
// RDX: Address being stored
// RAX: Current tag value
__ Bind(&add_to_buffer);
__ movl(RCX, RAX);
__ orl(RCX, Immediate(1 << RawObject::kRememberedBit));
__ movq(RCX, RAX);
__ orq(RCX, Immediate(1 << RawObject::kRememberedBit));
// Compare the tag word with RAX, update to RCX if unchanged.
__ LockCmpxchgl(FieldAddress(RDX, Object::tags_offset()), RCX);
__ LockCmpxchgq(FieldAddress(RDX, Object::tags_offset()), RCX);
__ j(NOT_EQUAL, &reload);
// Load the StoreBuffer block out of the thread. Then load top_ out of the
@ -1134,11 +1132,10 @@ void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
// RBX: next object start.
// RDX: new object type arguments (if is_cls_parameterized).
// Set the tags.
uint32_t tags = 0;
uword tags = 0;
tags = RawObject::SizeTag::update(instance_size, tags);
ASSERT(cls.id() != kIllegalCid);
tags = RawObject::ClassIdTag::update(cls.id(), tags);
// 64 bit store also zeros the identity hash field.
__ movq(Address(RAX, Instance::tags_offset()), Immediate(tags));
__ addq(RAX, Immediate(kHeapObjectTag));