diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h index f56c0205e43..148343e229a 100644 --- a/runtime/platform/globals.h +++ b/runtime/platform/globals.h @@ -448,13 +448,7 @@ typedef intptr_t word; typedef uintptr_t uword; // Size of a class id. -#if defined(ARCH_IS_32_BIT) typedef uint16_t classid_t; -#elif defined(ARCH_IS_64_BIT) -typedef uint32_t classid_t; -#else -#error Unexpected architecture word size -#endif // Byte sizes. const int kWordSize = sizeof(word); diff --git a/runtime/vm/assembler_arm64.cc b/runtime/vm/assembler_arm64.cc index 973e704a279..52dc66b2e03 100644 --- a/runtime/vm/assembler_arm64.cc +++ b/runtime/vm/assembler_arm64.cc @@ -973,12 +973,12 @@ void Assembler::StoreIntoObjectOffsetNoBarrier(Register object, void Assembler::LoadClassId(Register result, Register object) { - ASSERT(RawObject::kClassIdTagPos == kBitsPerInt32); - ASSERT(RawObject::kClassIdTagSize == kBitsPerInt32); + ASSERT(RawObject::kClassIdTagPos == 16); + ASSERT(RawObject::kClassIdTagSize == 16); const intptr_t class_id_offset = Object::tags_offset() + RawObject::kClassIdTagPos / kBitsPerByte; LoadFromOffset(result, object, class_id_offset - kHeapObjectTag, - kUnsignedWord); + kUnsignedHalfword); } diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc index da4021a02e3..24ffd1c5cab 100644 --- a/runtime/vm/assembler_x64.cc +++ b/runtime/vm/assembler_x64.cc @@ -3624,12 +3624,12 @@ void Assembler::EmitGenericShift(bool wide, void Assembler::LoadClassId(Register result, Register object) { - ASSERT(RawObject::kClassIdTagPos == kBitsPerInt32); - ASSERT(RawObject::kClassIdTagSize == kBitsPerInt32); - ASSERT(sizeof(classid_t) == sizeof(uint32_t)); + ASSERT(RawObject::kClassIdTagPos == 16); + ASSERT(RawObject::kClassIdTagSize == 16); + ASSERT(sizeof(classid_t) == sizeof(uint16_t)); const intptr_t class_id_offset = Object::tags_offset() + RawObject::kClassIdTagPos / kBitsPerByte; - movl(result, FieldAddress(object, class_id_offset)); + movzxw(result, FieldAddress(object, class_id_offset)); } @@ -3659,9 +3659,9 @@ void Assembler::SmiUntagOrCheckClass(Register object, intptr_t class_id, Label* is_smi) { ASSERT(kSmiTagShift == 1); - ASSERT(RawObject::kClassIdTagPos == kBitsPerInt32); - ASSERT(RawObject::kClassIdTagSize == kBitsPerInt32); - ASSERT(sizeof(classid_t) == sizeof(uint32_t)); + ASSERT(RawObject::kClassIdTagPos == 16); + ASSERT(RawObject::kClassIdTagSize == 16); + ASSERT(sizeof(classid_t) == sizeof(uint16_t)); const intptr_t class_id_offset = Object::tags_offset() + RawObject::kClassIdTagPos / kBitsPerByte; @@ -3670,7 +3670,7 @@ void Assembler::SmiUntagOrCheckClass(Register object, j(NOT_CARRY, is_smi, kNearJump); // Load cid: can't use LoadClassId, object is untagged. Use TIMES_2 scale // factor in the addressing mode to compensate for this. - movl(TMP, Address(object, TIMES_2, class_id_offset)); + movzxw(TMP, Address(object, TIMES_2, class_id_offset)); cmpl(TMP, Immediate(class_id)); } diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc index 5c911c71474..3439477ad41 100644 --- a/runtime/vm/clustered_snapshot.cc +++ b/runtime/vm/clustered_snapshot.cc @@ -1911,20 +1911,20 @@ class RODataSerializationCluster : public SerializationCluster { // will be loaded into read-only memory. if (cid_ == kOneByteStringCid) { RawOneByteString* str = static_cast(object); - if (str->ptr()->hash_ == Smi::New(0)) { + if (String::GetCachedHash(str) == 0) { intptr_t hash = String::Hash(str->ptr()->data(), Smi::Value(str->ptr()->length_)); - str->ptr()->hash_ = Smi::New(hash); + String::SetCachedHash(str, hash); } - ASSERT(str->ptr()->hash_ != Smi::New(0)); + ASSERT(String::GetCachedHash(str) != 0); } else if (cid_ == kTwoByteStringCid) { RawTwoByteString* str = static_cast(object); - if (str->ptr()->hash_ == Smi::New(0)) { + if (String::GetCachedHash(str) == 0) { intptr_t hash = String::Hash(str->ptr()->data(), Smi::Value(str->ptr()->length_) * 2); - str->ptr()->hash_ = Smi::New(hash); + String::SetCachedHash(str, hash); } - ASSERT(str->ptr()->hash_ != Smi::New(0)); + ASSERT(String::GetCachedHash(str) != 0); } } @@ -4359,7 +4359,7 @@ class OneByteStringSerializationCluster : public SerializationCluster { intptr_t length = Smi::Value(str->ptr()->length_); s->Write(length); s->Write(str->IsCanonical()); - intptr_t hash = Smi::Value(str->ptr()->hash_); + intptr_t hash = String::GetCachedHash(str); s->Write(hash); s->WriteBytes(str->ptr()->data(), length); } @@ -4399,7 +4399,7 @@ class OneByteStringDeserializationCluster : public DeserializationCluster { OneByteString::InstanceSize(length), is_vm_object, is_canonical); str->ptr()->length_ = Smi::New(length); - str->ptr()->hash_ = Smi::New(d->Read()); + String::SetCachedHash(str, d->Read()); for (intptr_t j = 0; j < length; j++) { str->ptr()->data()[j] = d->Read(); } @@ -4438,7 +4438,7 @@ class TwoByteStringSerializationCluster : public SerializationCluster { intptr_t length = Smi::Value(str->ptr()->length_); s->Write(length); s->Write(str->IsCanonical()); - intptr_t hash = Smi::Value(str->ptr()->hash_); + intptr_t hash = String::GetCachedHash(str); s->Write(hash); s->WriteBytes(reinterpret_cast(str->ptr()->data()), length * 2); } @@ -4478,7 +4478,7 @@ class TwoByteStringDeserializationCluster : public DeserializationCluster { TwoByteString::InstanceSize(length), is_vm_object, is_canonical); str->ptr()->length_ = Smi::New(length); - str->ptr()->hash_ = Smi::New(d->Read()); + String::SetCachedHash(str, d->Read()); uint8_t* cdata = reinterpret_cast(str->ptr()->data()); d->ReadBytes(cdata, length * 2); } diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc index 7a61983d341..47b4221fda2 100644 --- a/runtime/vm/dart.cc +++ b/runtime/vm/dart.cc @@ -113,7 +113,7 @@ static void CheckOffsets() { CHECK_OFFSET(Heap::TopOffset(Heap::kNew), 8); CHECK_OFFSET(Thread::stack_limit_offset(), 8); CHECK_OFFSET(Thread::object_null_offset(), 80); - CHECK_OFFSET(SingleTargetCache::upper_limit_offset(), 28); + CHECK_OFFSET(SingleTargetCache::upper_limit_offset(), 26); CHECK_OFFSET(Isolate::object_store_offset(), 56); NOT_IN_PRODUCT(CHECK_OFFSET(sizeof(ClassHeapStats), 208)); #endif diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h index 94805f8b56d..16c0df193a8 100644 --- a/runtime/vm/globals.h +++ b/runtime/vm/globals.h @@ -44,6 +44,10 @@ const intptr_t kSmiMin32 = -(static_cast(1) << kSmiBits32); static_cast(!(sizeof(array) % sizeof(*(array))))) // NOLINT +#if defined(ARCH_IS_64_BIT) +#define HASH_IN_OBJECT_HEADER 1 +#endif + // The expression OFFSET_OF(type, field) computes the byte-offset of // the specified field relative to the containing type. // diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc index 5c5b274c139..52cf903bcb7 100644 --- a/runtime/vm/intermediate_language_arm64.cc +++ b/runtime/vm/intermediate_language_arm64.cc @@ -1547,7 +1547,7 @@ LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - ASSERT(sizeof(classid_t) == kInt32Size); + ASSERT(sizeof(classid_t) == kInt16Size); const intptr_t value_cid = value()->Type()->ToCid(); const intptr_t field_cid = field().guarded_cid(); const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; @@ -1593,24 +1593,24 @@ void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset(), - kUnsignedWord); + kUnsignedHalfword); FieldAddress field_nullability_operand( - field_reg, Field::is_nullable_offset(), kUnsignedWord); + field_reg, Field::is_nullable_offset(), kUnsignedHalfword); if (value_cid == kDynamicCid) { LoadValueCid(compiler, value_cid_reg, value_reg); Label skip_length_check; - __ ldr(TMP, field_cid_operand, kUnsignedWord); + __ ldr(TMP, field_cid_operand, kUnsignedHalfword); __ CompareRegisters(value_cid_reg, TMP); __ b(&ok, EQ); - __ ldr(TMP, field_nullability_operand, kUnsignedWord); + __ ldr(TMP, field_nullability_operand, kUnsignedHalfword); __ CompareRegisters(value_cid_reg, TMP); } else if (value_cid == kNullCid) { - __ ldr(value_cid_reg, field_nullability_operand, kUnsignedWord); + __ ldr(value_cid_reg, field_nullability_operand, kUnsignedHalfword); __ CompareImmediate(value_cid_reg, value_cid); } else { Label skip_length_check; - __ ldr(value_cid_reg, field_cid_operand, kUnsignedWord); + __ ldr(value_cid_reg, field_cid_operand, kUnsignedHalfword); __ CompareImmediate(value_cid_reg, value_cid); } __ b(&ok, EQ); @@ -1624,17 +1624,17 @@ void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { if (!field().needs_length_check()) { // Uninitialized field can be handled inline. Check if the // field is still unitialized. - __ ldr(TMP, field_cid_operand, kUnsignedWord); + __ ldr(TMP, field_cid_operand, kUnsignedHalfword); __ CompareImmediate(TMP, kIllegalCid); __ b(fail, NE); if (value_cid == kDynamicCid) { - __ str(value_cid_reg, field_cid_operand, kUnsignedWord); - __ str(value_cid_reg, field_nullability_operand, kUnsignedWord); + __ str(value_cid_reg, field_cid_operand, kUnsignedHalfword); + __ str(value_cid_reg, field_nullability_operand, kUnsignedHalfword); } else { __ LoadImmediate(TMP, value_cid); - __ str(TMP, field_cid_operand, kUnsignedWord); - __ str(TMP, field_nullability_operand, kUnsignedWord); + __ str(TMP, field_cid_operand, kUnsignedHalfword); + __ str(TMP, field_nullability_operand, kUnsignedHalfword); } if (deopt == NULL) { @@ -1648,7 +1648,7 @@ void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ Bind(fail); __ LoadFieldFromOffset(TMP, field_reg, Field::guarded_cid_offset(), - kUnsignedWord); + kUnsignedHalfword); __ CompareImmediate(TMP, kDynamicCid); __ b(&ok, EQ); @@ -1887,7 +1887,7 @@ LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - ASSERT(sizeof(classid_t) == kInt32Size); + ASSERT(sizeof(classid_t) == kInt16Size); Label skip_store; const Register instance_reg = locs()->in(0).reg(); @@ -1959,7 +1959,7 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(), - kUnsignedWord); + kUnsignedHalfword); __ CompareImmediate(temp2, kNullCid); __ b(&store_pointer, EQ); @@ -1969,17 +1969,17 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ b(&store_pointer, EQ); __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), - kUnsignedWord); + kUnsignedHalfword); __ CompareImmediate(temp2, kDoubleCid); __ b(&store_double, EQ); __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), - kUnsignedWord); + kUnsignedHalfword); __ CompareImmediate(temp2, kFloat32x4Cid); __ b(&store_float32x4, EQ); __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), - kUnsignedWord); + kUnsignedHalfword); __ CompareImmediate(temp2, kFloat64x2Cid); __ b(&store_float64x2, EQ); @@ -2243,7 +2243,7 @@ LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - ASSERT(sizeof(classid_t) == kInt32Size); + ASSERT(sizeof(classid_t) == kInt16Size); const Register instance_reg = locs()->in(0).reg(); if (IsUnboxedLoad() && compiler->is_optimizing()) { const VRegister result = locs()->out(0).fpu_reg(); @@ -2280,23 +2280,23 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ LoadObject(result_reg, Field::ZoneHandle(field()->Original())); FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset(), - kUnsignedWord); + kUnsignedHalfword); FieldAddress field_nullability_operand( - result_reg, Field::is_nullable_offset(), kUnsignedWord); + result_reg, Field::is_nullable_offset(), kUnsignedHalfword); - __ ldr(temp, field_nullability_operand, kUnsignedWord); + __ ldr(temp, field_nullability_operand, kUnsignedHalfword); __ CompareImmediate(temp, kNullCid); __ b(&load_pointer, EQ); - __ ldr(temp, field_cid_operand, kUnsignedWord); + __ ldr(temp, field_cid_operand, kUnsignedHalfword); __ CompareImmediate(temp, kDoubleCid); __ b(&load_double, EQ); - __ ldr(temp, field_cid_operand, kUnsignedWord); + __ ldr(temp, field_cid_operand, kUnsignedHalfword); __ CompareImmediate(temp, kFloat32x4Cid); __ b(&load_float32x4, EQ); - __ ldr(temp, field_cid_operand, kUnsignedWord); + __ ldr(temp, field_cid_operand, kUnsignedHalfword); __ CompareImmediate(temp, kFloat64x2Cid); __ b(&load_float64x2, EQ); diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc index 930ace149f1..a43db626df7 100644 --- a/runtime/vm/intermediate_language_x64.cc +++ b/runtime/vm/intermediate_language_x64.cc @@ -1498,7 +1498,7 @@ LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - ASSERT(sizeof(classid_t) == kInt32Size); + ASSERT(sizeof(classid_t) == kInt16Size); const intptr_t value_cid = value()->Type()->ToCid(); const intptr_t field_cid = field().guarded_cid(); const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; @@ -1550,13 +1550,13 @@ void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { if (value_cid == kDynamicCid) { LoadValueCid(compiler, value_cid_reg, value_reg); - __ cmpl(value_cid_reg, field_cid_operand); + __ cmpw(value_cid_reg, field_cid_operand); __ j(EQUAL, &ok); - __ cmpl(value_cid_reg, field_nullability_operand); + __ cmpw(value_cid_reg, field_nullability_operand); } else if (value_cid == kNullCid) { - __ cmpl(field_nullability_operand, Immediate(value_cid)); + __ cmpw(field_nullability_operand, Immediate(value_cid)); } else { - __ cmpl(field_cid_operand, Immediate(value_cid)); + __ cmpw(field_cid_operand, Immediate(value_cid)); } __ j(EQUAL, &ok); @@ -1567,16 +1567,16 @@ void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { if (!field().needs_length_check()) { // Uninitialized field can be handled inline. Check if the // field is still unitialized. - __ cmpl(field_cid_operand, Immediate(kIllegalCid)); + __ cmpw(field_cid_operand, Immediate(kIllegalCid)); __ j(NOT_EQUAL, fail); if (value_cid == kDynamicCid) { - __ movl(field_cid_operand, value_cid_reg); - __ movl(field_nullability_operand, value_cid_reg); + __ movw(field_cid_operand, value_cid_reg); + __ movw(field_nullability_operand, value_cid_reg); } else { ASSERT(field_reg != kNoRegister); - __ movl(field_cid_operand, Immediate(value_cid)); - __ movl(field_nullability_operand, Immediate(value_cid)); + __ movw(field_cid_operand, Immediate(value_cid)); + __ movw(field_nullability_operand, Immediate(value_cid)); } if (deopt == NULL) { @@ -1589,7 +1589,7 @@ void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { ASSERT(!compiler->is_optimizing()); __ Bind(fail); - __ cmpl(FieldAddress(field_reg, Field::guarded_cid_offset()), + __ cmpw(FieldAddress(field_reg, Field::guarded_cid_offset()), Immediate(kDynamicCid)); __ j(EQUAL, &ok); @@ -1832,7 +1832,7 @@ static void EnsureMutableBox(FlowGraphCompiler* compiler, void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - ASSERT(sizeof(classid_t) == kInt32Size); + ASSERT(sizeof(classid_t) == kInt16Size); Label skip_store; Register instance_reg = locs()->in(0).reg(); @@ -1904,7 +1904,7 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); - __ cmpl(FieldAddress(temp, Field::is_nullable_offset()), + __ cmpw(FieldAddress(temp, Field::is_nullable_offset()), Immediate(kNullCid)); __ j(EQUAL, &store_pointer); @@ -1912,15 +1912,15 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ testq(temp2, Immediate(1 << Field::kUnboxingCandidateBit)); __ j(ZERO, &store_pointer); - __ cmpl(FieldAddress(temp, Field::guarded_cid_offset()), + __ cmpw(FieldAddress(temp, Field::guarded_cid_offset()), Immediate(kDoubleCid)); __ j(EQUAL, &store_double); - __ cmpl(FieldAddress(temp, Field::guarded_cid_offset()), + __ cmpw(FieldAddress(temp, Field::guarded_cid_offset()), Immediate(kFloat32x4Cid)); __ j(EQUAL, &store_float32x4); - __ cmpl(FieldAddress(temp, Field::guarded_cid_offset()), + __ cmpw(FieldAddress(temp, Field::guarded_cid_offset()), Immediate(kFloat64x2Cid)); __ j(EQUAL, &store_float64x2); @@ -2190,7 +2190,7 @@ LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { - ASSERT(sizeof(classid_t) == kInt32Size); + ASSERT(sizeof(classid_t) == kInt16Size); Register instance_reg = locs()->in(0).reg(); if (IsUnboxedLoad() && compiler->is_optimizing()) { XmmRegister result = locs()->out(0).fpu_reg(); @@ -2229,20 +2229,19 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ LoadObject(result, Field::ZoneHandle(field()->Original())); - __ cmpl(FieldAddress(result, Field::is_nullable_offset()), - Immediate(kNullCid)); + FieldAddress field_cid_operand(result, Field::guarded_cid_offset()); + FieldAddress field_nullability_operand(result, Field::is_nullable_offset()); + + __ cmpw(field_nullability_operand, Immediate(kNullCid)); __ j(EQUAL, &load_pointer); - __ cmpl(FieldAddress(result, Field::guarded_cid_offset()), - Immediate(kDoubleCid)); + __ cmpw(field_cid_operand, Immediate(kDoubleCid)); __ j(EQUAL, &load_double); - __ cmpl(FieldAddress(result, Field::guarded_cid_offset()), - Immediate(kFloat32x4Cid)); + __ cmpw(field_cid_operand, Immediate(kFloat32x4Cid)); __ j(EQUAL, &load_float32x4); - __ cmpl(FieldAddress(result, Field::guarded_cid_offset()), - Immediate(kFloat64x2Cid)); + __ cmpw(field_cid_operand, Immediate(kFloat64x2Cid)); __ j(EQUAL, &load_float64x2); // Fall through. diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc index 1898445573c..365be150f9e 100644 --- a/runtime/vm/intrinsifier_arm.cc +++ b/runtime/vm/intrinsifier_arm.cc @@ -176,8 +176,9 @@ void Intrinsifier::GrowableArray_add(Assembler* assembler) { __ CompareImmediate(R2, max_len); \ __ b(&fall_through, GT); \ __ mov(R2, Operand(R2, LSL, scale_shift)); \ - const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ - __ AddImmediate(R2, fixed_size); \ + const intptr_t fixed_size_plus_alignment_padding = \ + sizeof(Raw##type_name) + kObjectAlignment - 1; \ + __ AddImmediate(R2, fixed_size_plus_alignment_padding); \ __ bic(R2, R2, Operand(kObjectAlignment - 1)); \ Heap::Space space = Heap::kNew; \ __ ldr(R3, Address(THR, Thread::heap_offset())); \ @@ -1997,8 +1998,9 @@ static void TryAllocateOnebyteString(Assembler* assembler, __ mov(R8, Operand(length_reg)); // Save the length register. // TODO(koda): Protect against negative length and overflow here. __ SmiUntag(length_reg); - const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; - __ AddImmediate(length_reg, fixed_size); + const intptr_t fixed_size_plus_alignment_padding = + sizeof(RawString) + kObjectAlignment - 1; + __ AddImmediate(length_reg, fixed_size_plus_alignment_padding); __ bic(length_reg, length_reg, Operand(kObjectAlignment - 1)); const intptr_t cid = kOneByteStringCid; diff --git a/runtime/vm/intrinsifier_arm64.cc b/runtime/vm/intrinsifier_arm64.cc index f400c02a1fb..80d51eb3e4c 100644 --- a/runtime/vm/intrinsifier_arm64.cc +++ b/runtime/vm/intrinsifier_arm64.cc @@ -196,8 +196,9 @@ static int GetScaleFactor(intptr_t size) { __ CompareImmediate(R2, max_len); \ __ b(&fall_through, GT); \ __ LslImmediate(R2, R2, scale_shift); \ - const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ - __ AddImmediate(R2, fixed_size); \ + const intptr_t fixed_size_plus_alignment_padding = \ + sizeof(Raw##type_name) + kObjectAlignment - 1; \ + __ AddImmediate(R2, fixed_size_plus_alignment_padding); \ __ andi(R2, R2, Immediate(~(kObjectAlignment - 1))); \ Heap::Space space = Heap::kNew; \ __ ldr(R3, Address(THR, Thread::heap_offset())); \ @@ -1822,8 +1823,8 @@ void Intrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler) { void Intrinsifier::String_getHashCode(Assembler* assembler) { Label fall_through; __ ldr(R0, Address(SP, 0 * kWordSize)); - __ ldr(R0, FieldAddress(R0, String::hash_offset())); - __ CompareRegisters(R0, ZR); + __ ldr(R0, FieldAddress(R0, String::hash_offset()), kUnsignedWord); + __ adds(R0, R0, Operand(R0)); // Smi tag the hash code, setting Z flag. __ b(&fall_through, EQ); __ ret(); // Hash not yet computed. @@ -1995,8 +1996,8 @@ void Intrinsifier::StringBaseIsEmpty(Assembler* assembler) { void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { Label compute_hash; __ ldr(R1, Address(SP, 0 * kWordSize)); // OneByteString object. - __ ldr(R0, FieldAddress(R1, String::hash_offset())); - __ CompareRegisters(R0, ZR); + __ ldr(R0, FieldAddress(R1, String::hash_offset()), kUnsignedWord); + __ adds(R0, R0, Operand(R0)); // Smi tag the hash code, setting Z flag. __ b(&compute_hash, EQ); __ ret(); // Return if already computed. @@ -2046,8 +2047,8 @@ void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { // return hash_ == 0 ? 1 : hash_; __ Bind(&done); __ csinc(R0, R0, ZR, NE); // R0 <- (R0 != 0) ? R0 : (ZR + 1). + __ str(R0, FieldAddress(R1, String::hash_offset()), kUnsignedWord); __ SmiTag(R0); - __ str(R0, FieldAddress(R1, String::hash_offset())); __ ret(); } @@ -2064,9 +2065,16 @@ static void TryAllocateOnebyteString(Assembler* assembler, NOT_IN_PRODUCT(__ MaybeTraceAllocation(kOneByteStringCid, R0, failure)); __ mov(R6, length_reg); // Save the length register. // TODO(koda): Protect against negative length and overflow here. - __ SmiUntag(length_reg); - const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; - __ AddImmediate(length_reg, fixed_size); + __ adds(length_reg, ZR, Operand(length_reg, ASR, kSmiTagSize)); // Smi untag. + // If the length is 0 then we have to make the allocated size a bit bigger, + // otherwise the string takes up less space than an ExternalOneByteString, + // and cannot be externalized. TODO(erikcorry): We should probably just + // return a static zero length string here instead. + // length <- (length != 0) ? length : (ZR + 1). + __ csinc(length_reg, length_reg, ZR, NE); + const intptr_t fixed_size_plus_alignment_padding = + sizeof(RawString) + kObjectAlignment - 1; + __ AddImmediate(length_reg, fixed_size_plus_alignment_padding); __ andi(length_reg, length_reg, Immediate(~(kObjectAlignment - 1))); const intptr_t cid = kOneByteStringCid; @@ -2106,6 +2114,7 @@ static void TryAllocateOnebyteString(Assembler* assembler, // Get the class index and insert it into the tags. // R2: size and bit tags. + // This also clears the hash, which is in the high word of the tags. __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); __ orr(R2, R2, Operand(TMP)); __ str(R2, FieldAddress(R0, String::tags_offset())); // Store tags. @@ -2114,9 +2123,6 @@ static void TryAllocateOnebyteString(Assembler* assembler, // Set the length field using the saved length (R6). __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, String::length_offset()), R6); - // Clear hash. - __ mov(TMP, ZR); - __ str(TMP, FieldAddress(R0, String::hash_offset())); __ b(ok); __ Bind(&fail); diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc index 13e47bdd0c2..16d5209cef3 100644 --- a/runtime/vm/intrinsifier_ia32.cc +++ b/runtime/vm/intrinsifier_ia32.cc @@ -212,8 +212,9 @@ void Intrinsifier::GrowableArray_add(Assembler* assembler) { /* only scale by 8. */ \ scale_factor = TIMES_8; \ } \ - const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ - __ leal(EDI, Address(EDI, scale_factor, fixed_size)); \ + const intptr_t fixed_size_plus_alignment_padding = \ + sizeof(Raw##type_name) + kObjectAlignment - 1; \ + __ leal(EDI, Address(EDI, scale_factor, fixed_size_plus_alignment_padding)); \ __ andl(EDI, Immediate(-kObjectAlignment)); \ Heap::Space space = Heap::kNew; \ __ movl(ECX, Address(THR, Thread::heap_offset())); \ @@ -2027,8 +2028,10 @@ static void TryAllocateOnebyteString(Assembler* assembler, Label pop_and_fail; __ pushl(EDI); // Preserve length. __ SmiUntag(EDI); - const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; - __ leal(EDI, Address(EDI, TIMES_1, fixed_size)); // EDI is untagged. + const intptr_t fixed_size_plus_alignment_padding = + sizeof(RawString) + kObjectAlignment - 1; + __ leal(EDI, Address(EDI, TIMES_1, + fixed_size_plus_alignment_padding)); // EDI is untagged. __ andl(EDI, Immediate(-kObjectAlignment)); const intptr_t cid = kOneByteStringCid; diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc index ca95bb57822..1dca1af5810 100644 --- a/runtime/vm/intrinsifier_mips.cc +++ b/runtime/vm/intrinsifier_mips.cc @@ -167,8 +167,9 @@ void Intrinsifier::GrowableArray_add(Assembler* assembler) { /* T2: untagged array length. */ \ __ BranchSignedGreater(T2, Immediate(max_len), &fall_through); \ __ sll(T2, T2, scale_shift); \ - const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ - __ AddImmediate(T2, fixed_size); \ + const intptr_t fixed_size_plus_alignment_padding = \ + sizeof(Raw##type_name) + kObjectAlignment - 1; \ + __ AddImmediate(T2, fixed_size_plus_alignment_padding); \ __ LoadImmediate(TMP, -kObjectAlignment); \ __ and_(T2, T2, TMP); \ Heap::Space space = Heap::kNew; \ @@ -2131,8 +2132,9 @@ static void TryAllocateOnebyteString(Assembler* assembler, __ mov(T6, length_reg); // Save the length register. // TODO(koda): Protect against negative length and overflow here. __ SmiUntag(length_reg); - const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; - __ AddImmediate(length_reg, fixed_size); + const intptr_t fixed_size_plus_alignment_padding = + sizeof(RawString) + kObjectAlignment - 1; + __ AddImmediate(length_reg, fixed_size_plus_alignment_padding); __ LoadImmediate(TMP, ~(kObjectAlignment - 1)); __ and_(length_reg, length_reg, TMP); diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc index 47deca12fa9..f0ca5913f91 100644 --- a/runtime/vm/intrinsifier_x64.cc +++ b/runtime/vm/intrinsifier_x64.cc @@ -170,8 +170,9 @@ void Intrinsifier::GrowableArray_add(Assembler* assembler) { /* only scale by 8. */ \ scale_factor = TIMES_8; \ } \ - const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ - __ leaq(RDI, Address(RDI, scale_factor, fixed_size)); \ + const intptr_t fixed_size_plus_alignment_padding = \ + sizeof(Raw##type_name) + kObjectAlignment - 1; \ + __ leaq(RDI, Address(RDI, scale_factor, fixed_size_plus_alignment_padding)); \ __ andq(RDI, Immediate(-kObjectAlignment)); \ Heap::Space space = Heap::kNew; \ __ movq(R13, Address(THR, Thread::heap_offset())); \ @@ -1742,9 +1743,11 @@ void Intrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler) { void Intrinsifier::String_getHashCode(Assembler* assembler) { Label fall_through; __ movq(RAX, Address(RSP, +1 * kWordSize)); // String object. - __ movq(RAX, FieldAddress(RAX, String::hash_offset())); - __ cmpq(RAX, Immediate(0)); - __ j(EQUAL, &fall_through, Assembler::kNearJump); + __ movl(RAX, FieldAddress(RAX, String::hash_offset())); + ASSERT(kSmiTag == 0); + ASSERT(kSmiTagShift == 1); + __ addq(RAX, RAX); // Smi tag RAX, setting Z flag. + __ j(ZERO, &fall_through, Assembler::kNearJump); __ ret(); __ Bind(&fall_through); // Hash not yet computed. @@ -1911,9 +1914,10 @@ void Intrinsifier::StringBaseIsEmpty(Assembler* assembler) { void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { Label compute_hash; __ movq(RBX, Address(RSP, +1 * kWordSize)); // OneByteString object. - __ movq(RAX, FieldAddress(RBX, String::hash_offset())); + __ movl(RAX, FieldAddress(RBX, String::hash_offset())); __ cmpq(RAX, Immediate(0)); __ j(EQUAL, &compute_hash, Assembler::kNearJump); + __ SmiTag(RAX); __ ret(); __ Bind(&compute_hash); @@ -1971,8 +1975,8 @@ void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { __ j(NOT_EQUAL, &set_hash_code, Assembler::kNearJump); __ incq(RAX); __ Bind(&set_hash_code); + __ movl(FieldAddress(RBX, String::hash_offset()), RAX); __ SmiTag(RAX); - __ StoreIntoSmiField(FieldAddress(RBX, String::hash_offset()), RAX); __ ret(); } @@ -1988,11 +1992,19 @@ static void TryAllocateOnebyteString(Assembler* assembler, if (length_reg != RDI) { __ movq(RDI, length_reg); } - Label pop_and_fail; + Label pop_and_fail, not_zero_length; __ pushq(RDI); // Preserve length. - __ SmiUntag(RDI); - const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; - __ leaq(RDI, Address(RDI, TIMES_1, fixed_size)); // RDI is a Smi. + __ sarq(RDI, Immediate(kSmiTagShift)); // Untag length. + // If the length is 0 then we have to make the allocated size a bit bigger, + // otherwise the string takes up less space than an ExternalOneByteString, + // and cannot be externalized. TODO(erikcorry): We should probably just + // return a static zero length string here instead. + __ j(NOT_ZERO, ¬_zero_length); + __ addq(RDI, Immediate(1)); + __ Bind(¬_zero_length); + const intptr_t fixed_size_plus_alignment_padding = + sizeof(RawString) + kObjectAlignment - 1; + __ addq(RDI, Immediate(fixed_size_plus_alignment_padding)); __ andq(RDI, Immediate(-kObjectAlignment)); const intptr_t cid = kOneByteStringCid; @@ -2034,6 +2046,7 @@ static void TryAllocateOnebyteString(Assembler* assembler, __ Bind(&done); // Get the class index and insert it into the tags. + // This also clears the hash, which is in the high bits of the tags. __ orq(RDI, Immediate(RawObject::ClassIdTag::encode(cid))); __ movq(FieldAddress(RAX, String::tags_offset()), RDI); // Tags. } @@ -2042,8 +2055,6 @@ static void TryAllocateOnebyteString(Assembler* assembler, __ popq(RDI); __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, String::length_offset()), RDI); - // Clear hash. - __ ZeroInitSmiField(FieldAddress(RAX, String::hash_offset())); __ jmp(ok, Assembler::kNearJump); __ Bind(&pop_and_fail); diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index a6ba79ffd30..950c03e5621 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -21337,7 +21337,9 @@ RawOneByteString* OneByteString::New(intptr_t len, Heap::Space space) { NoSafepointScope no_safepoint; RawOneByteString* result = reinterpret_cast(raw); result->StoreSmi(&(result->ptr()->length_), Smi::New(len)); +#if !defined(HASH_IN_OBJECT_HEADER) result->StoreSmi(&(result->ptr()->hash_), Smi::New(0)); +#endif return result; } } diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 603467775b9..954db0401dc 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -432,6 +432,18 @@ class Object { return *transition_sentinel_; } +#if defined(HASH_IN_OBJECT_HEADER) + static uint32_t GetCachedHash(const RawObject* obj) { + uword tags = obj->ptr()->tags_; + return tags >> 32; + } + + static void SetCachedHash(RawObject* obj, uintptr_t hash) { + ASSERT(hash >> 32 == 0); + obj->ptr()->tags_ |= hash << 32; + } +#endif + // Compiler's constant propagation constants. static const Instance& unknown_constant() { ASSERT(unknown_constant_ != NULL); @@ -6752,8 +6764,11 @@ class String : public Instance { // All strings share the same maximum element count to keep things // simple. We choose a value that will prevent integer overflow for // 2 byte strings, since it is the worst case. - static const intptr_t kSizeofRawString = - sizeof(RawInstance) + (2 * kWordSize); +#if defined(HASH_IN_OBJECT_HEADER) + static const intptr_t kSizeofRawString = sizeof(RawInstance) + kWordSize; +#else + static const intptr_t kSizeofRawString = sizeof(RawInstance) + 2 * kWordSize; +#endif static const intptr_t kMaxElements = kSmiMax / kTwoByteChar; class CodePointIterator : public ValueObject { @@ -6789,28 +6804,32 @@ class String : public Instance { static intptr_t length_offset() { return OFFSET_OF(RawString, length_); } intptr_t Hash() const { - intptr_t result = Smi::Value(raw_ptr()->hash_); + intptr_t result = GetCachedHash(raw()); if (result != 0) { return result; } result = String::Hash(*this, 0, this->Length()); - this->SetHash(result); + SetCachedHash(raw(), result); return result; } bool HasHash() const { ASSERT(Smi::New(0) == NULL); - return (raw_ptr()->hash_ != 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); static intptr_t Hash(const int32_t* characters, intptr_t len); static intptr_t HashRawSymbol(const RawString* symbol) { ASSERT(symbol->IsCanonical()); - intptr_t result = Smi::Value(symbol->ptr()->hash_); + intptr_t result = GetCachedHash(symbol); ASSERT(result != 0); return result; } @@ -7029,6 +7048,16 @@ class String : public Instance { intptr_t end, double* result); +#if !defined(HASH_IN_OBJECT_HEADER) + static uint32_t GetCachedHash(const RawString* obj) { + return Smi::Value(obj->ptr()->hash_); + } + + static void SetCachedHash(RawString* obj, uintptr_t hash) { + obj->ptr()->hash_ = Smi::New(hash); + } +#endif + protected: // These two operate on an array of Latin-1 encoded characters. // They are protected to avoid mistaking Latin-1 for UTF-8, but used @@ -7042,11 +7071,7 @@ class String : public Instance { StoreSmi(&raw_ptr()->length_, Smi::New(value)); } - void SetHash(intptr_t value) const { - // This is only safe because we create a new Smi, which does not cause - // heap allocation. - StoreSmi(&raw_ptr()->hash_, Smi::New(value)); - } + void SetHash(intptr_t value) const { SetCachedHash(raw(), value); } template static void ReadFromImpl(SnapshotReader* reader, @@ -7105,6 +7130,12 @@ class OneByteString : public AllStatic { static intptr_t InstanceSize(intptr_t len) { ASSERT(sizeof(RawOneByteString) == String::kSizeofRawString); ASSERT(0 <= len && len <= kMaxElements); +#if defined(HASH_IN_OBJECT_HEADER) + // We have to pad zero-length raw strings so that they can be externalized. + // If we don't pad, then the external string object does not fit in the + // memory allocated for the raw string. + if (len == 0) return InstanceSize(1); +#endif return String::RoundedAllocationSize(sizeof(RawOneByteString) + (len * kBytesPerElement)); } @@ -7238,6 +7269,10 @@ class TwoByteString : public AllStatic { static intptr_t InstanceSize(intptr_t len) { ASSERT(sizeof(RawTwoByteString) == String::kSizeofRawString); ASSERT(0 <= len && len <= kMaxElements); + // We have to pad zero-length raw strings so that they can be externalized. + // If we don't pad, then the external string object does not fit in the + // memory allocated for the raw string. + if (len == 0) return InstanceSize(1); return String::RoundedAllocationSize(sizeof(RawTwoByteString) + (len * kBytesPerElement)); } @@ -8931,7 +8966,7 @@ bool String::Equals(const String& str) const { intptr_t Library::UrlHash() const { - intptr_t result = Smi::Value(url()->ptr()->hash_); + intptr_t result = String::GetCachedHash(url()); ASSERT(result != 0); return result; } diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc index f4a1bc17618..66fee3e09bd 100644 --- a/runtime/vm/raw_object.cc +++ b/runtime/vm/raw_object.cc @@ -821,7 +821,9 @@ intptr_t RawOneByteString::VisitOneByteStringPointers( RawOneByteString* raw_obj, ObjectPointerVisitor* visitor) { ASSERT(!raw_obj->ptr()->length_->IsHeapObject()); +#if !defined(HASH_IN_OBJECT_HEADER) ASSERT(!raw_obj->ptr()->hash_->IsHeapObject()); +#endif intptr_t length = Smi::Value(raw_obj->ptr()->length_); return OneByteString::InstanceSize(length); } @@ -831,7 +833,9 @@ intptr_t RawTwoByteString::VisitTwoByteStringPointers( RawTwoByteString* raw_obj, ObjectPointerVisitor* visitor) { ASSERT(!raw_obj->ptr()->length_->IsHeapObject()); +#if !defined(HASH_IN_OBJECT_HEADER) ASSERT(!raw_obj->ptr()->hash_->IsHeapObject()); +#endif intptr_t length = Smi::Value(raw_obj->ptr()->length_); return TwoByteString::InstanceSize(length); } diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 95288b1e140..488739cfbf2 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -266,21 +266,11 @@ class RawObject { kVMHeapObjectBit = 2, kRememberedBit = 3, kReservedTagPos = 4, // kReservedBit{100K,1M,10M} -#if defined(ARCH_IS_32_BIT) kReservedTagSize = 4, kSizeTagPos = kReservedTagPos + kReservedTagSize, // = 8 kSizeTagSize = 8, kClassIdTagPos = kSizeTagPos + kSizeTagSize, // = 16 kClassIdTagSize = 16, -#elif defined(ARCH_IS_64_BIT) - kReservedTagSize = 12, - kSizeTagPos = kReservedTagPos + kReservedTagSize, // = 16 - kSizeTagSize = 16, - kClassIdTagPos = kSizeTagPos + kSizeTagSize, // = 32 - kClassIdTagSize = 32, -#else -#error Unexpected architecture word size -#endif }; COMPILE_ASSERT(kClassIdTagSize == (sizeof(classid_t) * kBitsPerByte)); @@ -614,6 +604,7 @@ class RawObject { friend class RawExternalTypedData; friend class RawInstructions; friend class RawInstance; + friend class RawString; friend class RawTypedData; friend class Scavenger; friend class ScavengerVisitor; @@ -1863,10 +1854,20 @@ class RawString : public RawInstance { protected: RawObject** from() { return reinterpret_cast(&ptr()->length_); } RawSmi* length_; +#if !defined(HASH_IN_OBJECT_HEADER) RawSmi* hash_; RawObject** to() { return reinterpret_cast(&ptr()->hash_); } +#else + RawObject** to() { return reinterpret_cast(&ptr()->length_); } +#endif + private: friend class Library; + friend class OneByteStringSerializationCluster; + friend class TwoByteStringSerializationCluster; + friend class OneByteStringDeserializationCluster; + friend class TwoByteStringDeserializationCluster; + friend class RODataSerializationCluster; }; @@ -2453,6 +2454,7 @@ inline intptr_t RawObject::NumberOfTypedDataClasses() { return (kNullCid - kTypedDataInt8ArrayCid); } + } // namespace dart #endif // RUNTIME_VM_RAW_OBJECT_H_ diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc index a85f26d7cf5..988fb9972da 100644 --- a/runtime/vm/simulator_dbc.cc +++ b/runtime/vm/simulator_dbc.cc @@ -2957,9 +2957,11 @@ RawObject* Simulator::Call(const Code& code, BYTECODE(CreateArrayOpt, A_B_C); const intptr_t length = Smi::Value(RAW_CAST(Smi, FP[rB])); if (LIKELY(static_cast(length) <= Array::kMaxElements)) { - const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; + const intptr_t fixed_size_plus_alignment_padding = + sizeof(RawArray) + kObjectAlignment - 1; const intptr_t instance_size = - (fixed_size + length * kWordSize) & ~(kObjectAlignment - 1); + (fixed_size_plus_alignment_padding + length * kWordSize) & + ~(kObjectAlignment - 1); const uword start = thread->heap()->new_space()->TryAllocate(instance_size); if (LIKELY(start != 0)) { diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc index 31f70e1928c..fb9aa26db96 100644 --- a/runtime/vm/stub_code_arm.cc +++ b/runtime/vm/stub_code_arm.cc @@ -688,9 +688,10 @@ void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { const intptr_t cid = kArrayCid; NOT_IN_PRODUCT(__ MaybeTraceAllocation(cid, R4, &slow_case)); - const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; - __ LoadImmediate(R9, fixed_size); - __ add(R9, R9, Operand(R3, LSL, 1)); // R3 is a Smi. + const intptr_t fixed_size_plus_alignment_padding = + sizeof(RawArray) + kObjectAlignment - 1; + __ LoadImmediate(R9, fixed_size_plus_alignment_padding); + __ add(R9, R9, Operand(R3, LSL, 1)); // R3 is a Smi. ASSERT(kSmiTagShift == 1); __ bic(R9, R9, Operand(kObjectAlignment - 1)); @@ -909,8 +910,9 @@ void StubCode::GenerateAllocateContextStub(Assembler* assembler) { Label slow_case; // First compute the rounded instance size. // R1: number of context variables. - intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1; - __ LoadImmediate(R2, fixed_size); + intptr_t fixed_size_plus_alignment_padding = + sizeof(RawContext) + kObjectAlignment - 1; + __ LoadImmediate(R2, fixed_size_plus_alignment_padding); __ add(R2, R2, Operand(R1, LSL, 2)); ASSERT(kSmiTagShift == 1); __ bic(R2, R2, Operand(kObjectAlignment - 1)); diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc index 53ee64b428a..43732de9f9d 100644 --- a/runtime/vm/stub_code_arm64.cc +++ b/runtime/vm/stub_code_arm64.cc @@ -723,8 +723,9 @@ void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { // R2: array length as Smi. // R8: heap. __ LoadFromOffset(R0, R8, Heap::TopOffset(space)); - intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; - __ LoadImmediate(R3, fixed_size); + intptr_t fixed_size_plus_alignment_padding = + sizeof(RawArray) + kObjectAlignment - 1; + __ LoadImmediate(R3, fixed_size_plus_alignment_padding); __ add(R3, R3, Operand(R2, LSL, 2)); // R2 is Smi. ASSERT(kSmiTagShift == 1); __ andi(R3, R3, Immediate(~(kObjectAlignment - 1))); @@ -969,8 +970,9 @@ void StubCode::GenerateAllocateContextStub(Assembler* assembler) { Label slow_case; // First compute the rounded instance size. // R1: number of context variables. - intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1; - __ LoadImmediate(R2, fixed_size); + intptr_t fixed_size_plus_alignment_padding = + sizeof(RawContext) + kObjectAlignment - 1; + __ LoadImmediate(R2, fixed_size_plus_alignment_padding); __ add(R2, R2, Operand(R1, LSL, 3)); ASSERT(kSmiTagShift == 1); __ andi(R2, R2, Immediate(~(kObjectAlignment - 1))); @@ -2302,9 +2304,9 @@ void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) { Label miss; __ LoadClassIdMayBeSmi(R1, R0); __ ldr(R2, FieldAddress(R5, SingleTargetCache::lower_limit_offset()), - kUnsignedWord); + kUnsignedHalfword); __ ldr(R3, FieldAddress(R5, SingleTargetCache::upper_limit_offset()), - kUnsignedWord); + kUnsignedHalfword); __ cmp(R1, Operand(R2)); __ b(&miss, LT); diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc index a0cc04a252f..f33c9d13f88 100644 --- a/runtime/vm/stub_code_ia32.cc +++ b/runtime/vm/stub_code_ia32.cc @@ -599,8 +599,10 @@ void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { NOT_IN_PRODUCT( __ MaybeTraceAllocation(kArrayCid, EAX, &slow_case, Assembler::kFarJump)); - const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; - __ leal(EBX, Address(EDX, TIMES_2, fixed_size)); // EDX is Smi. + const intptr_t fixed_size_plus_alignment_padding = + sizeof(RawArray) + kObjectAlignment - 1; + // EDX is Smi. + __ leal(EBX, Address(EDX, TIMES_2, fixed_size_plus_alignment_padding)); ASSERT(kSmiTagShift == 1); __ andl(EBX, Immediate(-kObjectAlignment)); @@ -824,8 +826,9 @@ void StubCode::GenerateAllocateContextStub(Assembler* assembler) { Label slow_case; // First compute the rounded instance size. // EDX: number of context variables. - intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); - __ leal(EBX, Address(EDX, TIMES_4, fixed_size)); + intptr_t fixed_size_plus_alignment_padding = + (sizeof(RawContext) + kObjectAlignment - 1); + __ leal(EBX, Address(EDX, TIMES_4, fixed_size_plus_alignment_padding)); __ andl(EBX, Immediate(-kObjectAlignment)); NOT_IN_PRODUCT(__ MaybeTraceAllocation(kContextCid, EAX, &slow_case, @@ -871,7 +874,7 @@ void StubCode::GenerateAllocateContextStub(Assembler* assembler) { // EDX: number of context variables. { Label size_tag_overflow, done; - __ leal(EBX, Address(EDX, TIMES_4, fixed_size)); + __ leal(EBX, Address(EDX, TIMES_4, fixed_size_plus_alignment_padding)); __ andl(EBX, Immediate(-kObjectAlignment)); __ cmpl(EBX, Immediate(RawObject::SizeTag::kMaxSizeTag)); __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc index f94b884192a..b00f72b45bc 100644 --- a/runtime/vm/stub_code_mips.cc +++ b/runtime/vm/stub_code_mips.cc @@ -711,8 +711,9 @@ void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { const intptr_t cid = kArrayCid; NOT_IN_PRODUCT(__ MaybeTraceAllocation(kArrayCid, T4, &slow_case)); - const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; - __ LoadImmediate(T2, fixed_size); + const intptr_t fixed_size_plus_alignment_padding = + sizeof(RawArray) + kObjectAlignment - 1; + __ LoadImmediate(T2, fixed_size_plus_alignment_padding); __ sll(T3, T3, 1); // T3 is a Smi. __ addu(T2, T2, T3); ASSERT(kSmiTagShift == 1); @@ -973,8 +974,9 @@ void StubCode::GenerateAllocateContextStub(Assembler* assembler) { Label slow_case; // First compute the rounded instance size. // T1: number of context variables. - intptr_t fixed_size = sizeof(RawContext) + kObjectAlignment - 1; - __ LoadImmediate(T2, fixed_size); + intptr_t fixed_size_plus_alignment_padding = + sizeof(RawContext) + kObjectAlignment - 1; + __ LoadImmediate(T2, fixed_size_plus_alignment_padding); __ sll(T0, T1, 2); __ addu(T2, T2, T0); ASSERT(kSmiTagShift == 1); diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc index 53f153e2c25..8c7150bd263 100644 --- a/runtime/vm/stub_code_x64.cc +++ b/runtime/vm/stub_code_x64.cc @@ -646,8 +646,10 @@ void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { NOT_IN_PRODUCT( __ MaybeTraceAllocation(kArrayCid, &slow_case, Assembler::kFarJump)); - const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; - __ leaq(RDI, Address(RDI, TIMES_4, fixed_size)); // RDI is a Smi. + const intptr_t fixed_size_plus_alignment_padding = + sizeof(RawArray) + kObjectAlignment - 1; + // RDI is a Smi. + __ leaq(RDI, Address(RDI, TIMES_4, fixed_size_plus_alignment_padding)); ASSERT(kSmiTagShift == 1); __ andq(RDI, Immediate(-kObjectAlignment)); @@ -888,8 +890,9 @@ void StubCode::GenerateAllocateContextStub(Assembler* assembler) { Label slow_case; // First compute the rounded instance size. // R10: number of context variables. - intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); - __ leaq(R13, Address(R10, TIMES_8, fixed_size)); + intptr_t fixed_size_plus_alignment_padding = + (sizeof(RawContext) + kObjectAlignment - 1); + __ leaq(R13, Address(R10, TIMES_8, fixed_size_plus_alignment_padding)); __ andq(R13, Immediate(-kObjectAlignment)); // Check for allocation tracing. @@ -933,7 +936,7 @@ void StubCode::GenerateAllocateContextStub(Assembler* assembler) { // R10: number of context variables. { Label size_tag_overflow, done; - __ leaq(R13, Address(R10, TIMES_8, fixed_size)); + __ leaq(R13, Address(R10, TIMES_8, fixed_size_plus_alignment_padding)); __ andq(R13, Immediate(-kObjectAlignment)); __ cmpq(R13, Immediate(RawObject::SizeTag::kMaxSizeTag)); __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); @@ -2242,8 +2245,8 @@ void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) { void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) { Label miss; __ LoadClassIdMayBeSmi(RAX, RDI); - __ movl(R9, FieldAddress(RBX, SingleTargetCache::lower_limit_offset())); - __ movl(R10, FieldAddress(RBX, SingleTargetCache::upper_limit_offset())); + __ movzxw(R9, FieldAddress(RBX, SingleTargetCache::lower_limit_offset())); + __ movzxw(R10, FieldAddress(RBX, SingleTargetCache::upper_limit_offset())); __ cmpq(RAX, R9); __ j(LESS, &miss, Assembler::kNearJump); __ cmpq(RAX, R10);