Reland "Introduce MutableHeapNumber class."

This is a reland of 40ac6b187a, which
was incorrect due to a bad merge.

Original change's description:
> Introduce MutableHeapNumber class.
>
> V8 knows heap numbers and mutable heap numbers. They have
> difference instance types, but in C++ code we've used the
> same class for both (HeapNumber). Confusingly, however,
> IsHeapNumber would return false for mutable heap numbers,
> while HeapNumber::cast would succeed.
>
> This CL adds a separate class MutableHeapNumber and
> eliminates the confusing behavior.
>
> TBR=bmeurer@chromium.org
>
> Change-Id: Id894d177c7fe8cc3f451be80c273b50daee91378
> Reviewed-on: https://chromium-review.googlesource.com/1113544
> Commit-Queue: Georg Neis <neis@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#54012}

TBR=bmeurer@chromium.org
TBR=ulanchromium.org

Change-Id: I3af1014c949821dfac0754a3e48c65ce1bad1ad1
Reviewed-on: https://chromium-review.googlesource.com/1114539
Reviewed-by: Georg Neis <neis@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54022}
This commit is contained in:
Georg Neis 2018-06-26 10:58:45 +02:00 committed by Commit Bot
parent 4769681cd3
commit f0bcbc90c1
31 changed files with 201 additions and 144 deletions

View File

@ -477,8 +477,8 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
Handle<HeapObject> object;
switch (request.kind()) {
case HeapObjectRequest::kHeapNumber:
object = isolate->factory()->NewHeapNumber(request.heap_number(),
IMMUTABLE, TENURED);
object =
isolate->factory()->NewHeapNumber(request.heap_number(), TENURED);
break;
case HeapObjectRequest::kCodeStub:
request.code_stub()->set_isolate(isolate);

View File

@ -591,8 +591,8 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
Address pc = reinterpret_cast<Address>(buffer_) + request.offset();
switch (request.kind()) {
case HeapObjectRequest::kHeapNumber: {
Handle<HeapObject> object = isolate->factory()->NewHeapNumber(
request.heap_number(), IMMUTABLE, TENURED);
Handle<HeapObject> object =
isolate->factory()->NewHeapNumber(request.heap_number(), TENURED);
set_target_address_at(pc, 0 /* unused */, object.address());
break;
}

View File

@ -577,7 +577,7 @@ Node* ConstructorBuiltinsAssembler::EmitCreateShallowObjectLiteral(
{
Node* double_value = LoadHeapNumberValue(field);
Node* mutable_heap_number =
AllocateHeapNumberWithValue(double_value, MUTABLE);
AllocateMutableHeapNumberWithValue(double_value);
StoreObjectField(copy, offset, mutable_heap_number);
Goto(&continue_loop);
}

View File

@ -2439,6 +2439,12 @@ void CodeStubAssembler::StoreHeapNumberValue(SloppyTNode<HeapNumber> object,
MachineRepresentation::kFloat64);
}
void CodeStubAssembler::StoreMutableHeapNumberValue(
SloppyTNode<MutableHeapNumber> object, SloppyTNode<Float64T> value) {
StoreObjectFieldNoWriteBarrier(object, MutableHeapNumber::kValueOffset, value,
MachineRepresentation::kFloat64);
}
Node* CodeStubAssembler::StoreObjectField(
Node* object, int offset, Node* value) {
DCHECK_NE(HeapObject::kMapOffset, offset); // Use StoreMap instead.
@ -2777,22 +2783,34 @@ Node* CodeStubAssembler::StoreCellValue(Node* cell, Node* value,
}
}
TNode<HeapNumber> CodeStubAssembler::AllocateHeapNumber(MutableMode mode) {
TNode<HeapNumber> CodeStubAssembler::AllocateHeapNumber() {
Node* result = Allocate(HeapNumber::kSize, kNone);
Heap::RootListIndex heap_map_index =
mode == IMMUTABLE ? Heap::kHeapNumberMapRootIndex
: Heap::kMutableHeapNumberMapRootIndex;
Heap::RootListIndex heap_map_index = Heap::kHeapNumberMapRootIndex;
StoreMapNoWriteBarrier(result, heap_map_index);
return UncheckedCast<HeapNumber>(result);
}
TNode<HeapNumber> CodeStubAssembler::AllocateHeapNumberWithValue(
SloppyTNode<Float64T> value, MutableMode mode) {
TNode<HeapNumber> result = AllocateHeapNumber(mode);
SloppyTNode<Float64T> value) {
TNode<HeapNumber> result = AllocateHeapNumber();
StoreHeapNumberValue(result, value);
return result;
}
TNode<MutableHeapNumber> CodeStubAssembler::AllocateMutableHeapNumber() {
Node* result = Allocate(MutableHeapNumber::kSize, kNone);
Heap::RootListIndex heap_map_index = Heap::kMutableHeapNumberMapRootIndex;
StoreMapNoWriteBarrier(result, heap_map_index);
return UncheckedCast<MutableHeapNumber>(result);
}
TNode<MutableHeapNumber> CodeStubAssembler::AllocateMutableHeapNumberWithValue(
SloppyTNode<Float64T> value) {
TNode<MutableHeapNumber> result = AllocateMutableHeapNumber();
StoreMutableHeapNumberValue(result, value);
return result;
}
TNode<BigInt> CodeStubAssembler::AllocateBigInt(TNode<IntPtrT> length) {
TNode<BigInt> result = AllocateRawBigInt(length);
StoreBigIntBitfield(result, WordShl(length, BigInt::LengthBits::kShift));

View File

@ -1075,6 +1075,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Store the floating point value of a HeapNumber.
void StoreHeapNumberValue(SloppyTNode<HeapNumber> object,
SloppyTNode<Float64T> value);
void StoreMutableHeapNumberValue(SloppyTNode<MutableHeapNumber> object,
SloppyTNode<Float64T> value);
// Store a field to an object on the heap.
Node* StoreObjectField(Node* object, int offset, Node* value);
Node* StoreObjectField(Node* object, Node* offset, Node* value);
@ -1160,10 +1162,16 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Allocate a HeapNumber without initializing its value.
TNode<HeapNumber> AllocateHeapNumber(MutableMode mode = IMMUTABLE);
TNode<HeapNumber> AllocateHeapNumber();
// Allocate a HeapNumber with a specific value.
TNode<HeapNumber> AllocateHeapNumberWithValue(SloppyTNode<Float64T> value,
MutableMode mode = IMMUTABLE);
TNode<HeapNumber> AllocateHeapNumberWithValue(SloppyTNode<Float64T> value);
TNode<HeapNumber> AllocateHeapNumberWithValue(double value) {
return AllocateHeapNumberWithValue(Float64Constant(value));
}
// Allocate a MutableHeapNumber with a specific value.
TNode<MutableHeapNumber> AllocateMutableHeapNumberWithValue(
SloppyTNode<Float64T> value);
// Allocate a BigInt with {length} digits. Sets the sign bit to {false}.
// Does not initialize the digits.
@ -1176,11 +1184,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
TNode<WordT> LoadBigIntBitfield(TNode<BigInt> bigint);
TNode<UintPtrT> LoadBigIntDigit(TNode<BigInt> bigint, int digit_index);
TNode<HeapNumber> AllocateHeapNumberWithValue(double value,
MutableMode mode = IMMUTABLE) {
return AllocateHeapNumberWithValue(Float64Constant(value), mode);
}
// Allocate a SeqOneByteString with the given length.
TNode<String> AllocateSeqOneByteString(int length,
AllocationFlags flags = kNone);
@ -2740,6 +2743,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
TNode<Smi> length, TNode<String> first,
TNode<String> second, AllocationFlags flags);
// Allocate a MutableHeapNumber without initializing its value.
TNode<MutableHeapNumber> AllocateMutableHeapNumber();
Node* SelectImpl(TNode<BoolT> condition, const NodeGenerator& true_body,
const NodeGenerator& false_body, MachineRepresentation rep);

View File

@ -266,8 +266,8 @@ TNode<Number> CodeAssembler::NumberConstant(double value) {
// deferring allocation to code generation
// (see AllocateAndInstallRequestedHeapObjects) since that makes it easier
// to generate constant lookups for embedded builtins.
return UncheckedCast<Number>(HeapConstant(
isolate()->factory()->NewHeapNumber(value, IMMUTABLE, TENURED)));
return UncheckedCast<Number>(
HeapConstant(isolate()->factory()->NewHeapNumber(value, TENURED)));
}
}

View File

@ -42,7 +42,7 @@ double HeapNumberRef::value() const {
double MutableHeapNumberRef::value() const {
AllowHandleDereference allow_handle_dereference;
return object<HeapNumber>()->value();
return object<MutableHeapNumber>()->value();
}
ContextRef::ContextRef(Handle<Object> object) : HeapObjectRef(object) {

View File

@ -3464,9 +3464,9 @@ void TranslatedState::MaterializeMutableHeapNumber(TranslatedFrame* frame,
CHECK_NE(TranslatedValue::kCapturedObject,
frame->values_[*value_index].kind());
Handle<Object> value = frame->values_[*value_index].GetValue();
Handle<HeapNumber> box;
CHECK(value->IsNumber());
box = isolate()->factory()->NewHeapNumber(value->Number(), MUTABLE);
Handle<MutableHeapNumber> box =
isolate()->factory()->NewMutableHeapNumber(value->Number());
(*value_index)++;
slot->set_storage(box);
}

View File

@ -117,23 +117,37 @@ Handle<Object> Factory::NewNumberFromInt64(int64_t value,
return NewNumber(static_cast<double>(value), pretenure);
}
Handle<HeapNumber> Factory::NewHeapNumber(double value, MutableMode mode,
Handle<HeapNumber> Factory::NewHeapNumber(double value,
PretenureFlag pretenure) {
Handle<HeapNumber> heap_number = NewHeapNumber(mode, pretenure);
Handle<HeapNumber> heap_number = NewHeapNumber(pretenure);
heap_number->set_value(value);
return heap_number;
}
Handle<MutableHeapNumber> Factory::NewMutableHeapNumber(
double value, PretenureFlag pretenure) {
Handle<MutableHeapNumber> number = NewMutableHeapNumber(pretenure);
number->set_value(value);
return number;
}
Handle<HeapNumber> Factory::NewHeapNumberFromBits(uint64_t bits,
MutableMode mode,
PretenureFlag pretenure) {
Handle<HeapNumber> heap_number = NewHeapNumber(mode, pretenure);
Handle<HeapNumber> heap_number = NewHeapNumber(pretenure);
heap_number->set_value_as_bits(bits);
return heap_number;
}
Handle<HeapNumber> Factory::NewMutableHeapNumber(PretenureFlag pretenure) {
return NewHeapNumberFromBits(kHoleNanInt64, MUTABLE, pretenure);
Handle<MutableHeapNumber> Factory::NewMutableHeapNumberFromBits(
uint64_t bits, PretenureFlag pretenure) {
Handle<MutableHeapNumber> number = NewMutableHeapNumber(pretenure);
number->set_value_as_bits(bits);
return number;
}
Handle<MutableHeapNumber> Factory::NewMutableHeapNumberWithHoleNaN(
PretenureFlag pretenure) {
return NewMutableHeapNumberFromBits(kHoleNanInt64, pretenure);
}
Handle<JSArray> Factory::NewJSArrayWithElements(Handle<FixedArrayBase> elements,

View File

@ -2112,16 +2112,14 @@ Handle<Object> Factory::NewNumber(double value, PretenureFlag pretenure) {
if (DoubleToSmiInteger(value, &int_value)) {
return handle(Smi::FromInt(int_value), isolate());
}
// Materialize the value in the heap.
return NewHeapNumber(value, IMMUTABLE, pretenure);
return NewHeapNumber(value, pretenure);
}
Handle<Object> Factory::NewNumberFromInt(int32_t value,
PretenureFlag pretenure) {
if (Smi::IsValid(value)) return handle(Smi::FromInt(value), isolate());
// Bypass NewNumber to avoid various redundant checks.
return NewHeapNumber(FastI2D(value), IMMUTABLE, pretenure);
return NewHeapNumber(FastI2D(value), pretenure);
}
Handle<Object> Factory::NewNumberFromUint(uint32_t value,
@ -2130,18 +2128,26 @@ Handle<Object> Factory::NewNumberFromUint(uint32_t value,
if (int32v >= 0 && Smi::IsValid(int32v)) {
return handle(Smi::FromInt(int32v), isolate());
}
return NewHeapNumber(FastUI2D(value), IMMUTABLE, pretenure);
return NewHeapNumber(FastUI2D(value), pretenure);
}
Handle<HeapNumber> Factory::NewHeapNumber(MutableMode mode,
PretenureFlag pretenure) {
Handle<HeapNumber> Factory::NewHeapNumber(PretenureFlag pretenure) {
STATIC_ASSERT(HeapNumber::kSize <= kMaxRegularHeapObjectSize);
Map* map = mode == MUTABLE ? *mutable_heap_number_map() : *heap_number_map();
Map* map = *heap_number_map();
HeapObject* result = AllocateRawWithImmortalMap(HeapNumber::kSize, pretenure,
map, kDoubleUnaligned);
return handle(HeapNumber::cast(result), isolate());
}
Handle<MutableHeapNumber> Factory::NewMutableHeapNumber(
PretenureFlag pretenure) {
STATIC_ASSERT(HeapNumber::kSize <= kMaxRegularHeapObjectSize);
Map* map = *mutable_heap_number_map();
HeapObject* result = AllocateRawWithImmortalMap(
MutableHeapNumber::kSize, pretenure, map, kDoubleUnaligned);
return handle(MutableHeapNumber::cast(result), isolate());
}
Handle<FreshlyAllocatedBigInt> Factory::NewBigInt(int length,
PretenureFlag pretenure) {
if (length < 0 || length > BigInt::kMaxLength) {

View File

@ -527,18 +527,21 @@ class V8_EXPORT_PRIVATE Factory {
inline Handle<Object> NewNumberFromInt64(
int64_t value, PretenureFlag pretenure = NOT_TENURED);
inline Handle<HeapNumber> NewHeapNumber(
double value, MutableMode mode = IMMUTABLE,
PretenureFlag pretenure = NOT_TENURED);
double value, PretenureFlag pretenure = NOT_TENURED);
inline Handle<HeapNumber> NewHeapNumberFromBits(
uint64_t bits, MutableMode mode = IMMUTABLE,
PretenureFlag pretenure = NOT_TENURED);
// Creates mutable heap number object with value field set to hole NaN.
inline Handle<HeapNumber> NewMutableHeapNumber(
PretenureFlag pretenure = NOT_TENURED);
uint64_t bits, PretenureFlag pretenure = NOT_TENURED);
// Creates heap number object with not yet set value field.
Handle<HeapNumber> NewHeapNumber(MutableMode mode,
PretenureFlag pretenure = NOT_TENURED);
Handle<HeapNumber> NewHeapNumber(PretenureFlag pretenure = NOT_TENURED);
Handle<MutableHeapNumber> NewMutableHeapNumber(
PretenureFlag pretenure = NOT_TENURED);
inline Handle<MutableHeapNumber> NewMutableHeapNumber(
double value, PretenureFlag pretenure = NOT_TENURED);
inline Handle<MutableHeapNumber> NewMutableHeapNumberFromBits(
uint64_t bits, PretenureFlag pretenure = NOT_TENURED);
inline Handle<MutableHeapNumber> NewMutableHeapNumberWithHoleNaN(
PretenureFlag pretenure = NOT_TENURED);
// Allocates a new BigInt with {length} digits. Only to be used by
// MutableBigInt::New*.

View File

@ -368,7 +368,7 @@ bool Heap::CreateInitialMaps() {
ALLOCATE_VARSIZE_MAP(FEEDBACK_VECTOR_TYPE, feedback_vector)
ALLOCATE_PRIMITIVE_MAP(HEAP_NUMBER_TYPE, HeapNumber::kSize, heap_number,
Context::NUMBER_FUNCTION_INDEX)
ALLOCATE_MAP(MUTABLE_HEAP_NUMBER_TYPE, HeapNumber::kSize,
ALLOCATE_MAP(MUTABLE_HEAP_NUMBER_TYPE, MutableHeapNumber::kSize,
mutable_heap_number)
ALLOCATE_PRIMITIVE_MAP(SYMBOL_TYPE, Symbol::kSize, symbol,
Context::SYMBOL_FUNCTION_INDEX)
@ -586,18 +586,16 @@ void Heap::CreateInitialObjects() {
Factory* factory = isolate()->factory();
// The -0 value must be set before NewNumber works.
set_minus_zero_value(
*factory->NewHeapNumber(-0.0, IMMUTABLE, TENURED_READ_ONLY));
set_minus_zero_value(*factory->NewHeapNumber(-0.0, TENURED_READ_ONLY));
DCHECK(std::signbit(minus_zero_value()->Number()));
set_nan_value(*factory->NewHeapNumber(
std::numeric_limits<double>::quiet_NaN(), IMMUTABLE, TENURED_READ_ONLY));
set_hole_nan_value(*factory->NewHeapNumberFromBits(kHoleNanInt64, IMMUTABLE,
TENURED_READ_ONLY));
set_infinity_value(
*factory->NewHeapNumber(V8_INFINITY, IMMUTABLE, TENURED_READ_ONLY));
std::numeric_limits<double>::quiet_NaN(), TENURED_READ_ONLY));
set_hole_nan_value(
*factory->NewHeapNumberFromBits(kHoleNanInt64, TENURED_READ_ONLY));
set_infinity_value(*factory->NewHeapNumber(V8_INFINITY, TENURED_READ_ONLY));
set_minus_infinity_value(
*factory->NewHeapNumber(-V8_INFINITY, IMMUTABLE, TENURED_READ_ONLY));
*factory->NewHeapNumber(-V8_INFINITY, TENURED_READ_ONLY));
// Allocate cache for single character one byte strings.
set_single_character_string_cache(

View File

@ -303,8 +303,8 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
Handle<HeapObject> object;
switch (request.kind()) {
case HeapObjectRequest::kHeapNumber:
object = isolate->factory()->NewHeapNumber(request.heap_number(),
IMMUTABLE, TENURED);
object =
isolate->factory()->NewHeapNumber(request.heap_number(), TENURED);
break;
case HeapObjectRequest::kCodeStub:
request.code_stub()->set_isolate(isolate);

View File

@ -1091,7 +1091,7 @@ void AccessorAssembler::OverwriteExistingFastDataProperty(
} else {
if (do_transitioning_store) {
Node* mutable_heap_number =
AllocateHeapNumberWithValue(double_value, MUTABLE);
AllocateMutableHeapNumberWithValue(double_value);
StoreMap(object, object_map);
StoreObjectField(object, field_offset, mutable_heap_number);
} else {
@ -1130,7 +1130,7 @@ void AccessorAssembler::OverwriteExistingFastDataProperty(
{
Node* double_value = ChangeNumberToFloat64(value);
Node* mutable_heap_number =
AllocateHeapNumberWithValue(double_value, MUTABLE);
AllocateMutableHeapNumberWithValue(double_value);
var_value.Bind(mutable_heap_number);
Goto(&cont);
}

View File

@ -262,8 +262,8 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
Handle<HeapObject> object;
switch (request.kind()) {
case HeapObjectRequest::kHeapNumber:
object = isolate->factory()->NewHeapNumber(request.heap_number(),
IMMUTABLE, TENURED);
object =
isolate->factory()->NewHeapNumber(request.heap_number(), TENURED);
break;
case HeapObjectRequest::kCodeStub:
request.code_stub()->set_isolate(isolate);

View File

@ -241,8 +241,8 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
Handle<HeapObject> object;
switch (request.kind()) {
case HeapObjectRequest::kHeapNumber:
object = isolate->factory()->NewHeapNumber(request.heap_number(),
IMMUTABLE, TENURED);
object =
isolate->factory()->NewHeapNumber(request.heap_number(), TENURED);
break;
case HeapObjectRequest::kCodeStub:
request.code_stub()->set_isolate(isolate);

View File

@ -110,10 +110,8 @@ void Smi::SmiVerify(Isolate* isolate) {
void HeapObject::HeapObjectVerify(Isolate* isolate) {
VerifyHeapPointer(map());
CHECK(map()->IsMap());
InstanceType instance_type = map()->instance_type();
switch (instance_type) {
switch (map()->instance_type()) {
#define STRING_TYPE_CASE(TYPE, size, name, camel_name) case TYPE:
STRING_TYPE_LIST(STRING_TYPE_CASE)
#undef STRING_TYPE_CASE
@ -126,8 +124,10 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
Map::cast(this)->MapVerify(isolate);
break;
case HEAP_NUMBER_TYPE:
CHECK(IsHeapNumber());
break;
case MUTABLE_HEAP_NUMBER_TYPE:
HeapNumber::cast(this)->HeapNumberVerify(isolate);
CHECK(IsMutableHeapNumber());
break;
case BIGINT_TYPE:
BigInt::cast(this)->BigIntVerify(isolate);
@ -372,10 +372,6 @@ void Symbol::SymbolVerify(Isolate* isolate) {
CHECK_IMPLIES(IsPrivateField(), IsPrivate());
}
void HeapNumber::HeapNumberVerify(Isolate* isolate) {
CHECK(IsHeapNumber() || IsMutableHeapNumber());
}
void ByteArray::ByteArrayVerify(Isolate* isolate) { CHECK(IsByteArray()); }
void BytecodeArray::BytecodeArrayVerify(Isolate* isolate) {

View File

@ -640,7 +640,9 @@ CAST_ACCESSOR(JSProxy)
CAST_ACCESSOR(JSReceiver)
CAST_ACCESSOR(JSStringIterator)
CAST_ACCESSOR(JSValue)
CAST_ACCESSOR(HeapNumber)
CAST_ACCESSOR(LayoutDescriptor)
CAST_ACCESSOR(MutableHeapNumber)
CAST_ACCESSOR(NameDictionary)
CAST_ACCESSOR(NormalizedMapCache)
CAST_ACCESSOR(NumberDictionary)
@ -705,12 +707,13 @@ bool Object::FilterKey(PropertyFilter filter) {
Handle<Object> Object::NewStorageFor(Isolate* isolate, Handle<Object> object,
Representation representation) {
if (!representation.IsDouble()) return object;
Handle<HeapNumber> result = isolate->factory()->NewHeapNumber(MUTABLE);
auto result = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
if (object->IsUninitialized(isolate)) {
result->set_value_as_bits(kHoleNanInt64);
} else if (object->IsMutableHeapNumber()) {
// Ensure that all bits of the double value are preserved.
result->set_value_as_bits(HeapNumber::cast(*object)->value_as_bits());
result->set_value_as_bits(
MutableHeapNumber::cast(*object)->value_as_bits());
} else {
result->set_value(object->Number());
}
@ -724,7 +727,8 @@ Handle<Object> Object::WrapForRead(Isolate* isolate, Handle<Object> object,
DCHECK(object->FitsRepresentation(representation));
return object;
}
return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value());
return isolate->factory()->NewHeapNumber(
MutableHeapNumber::cast(*object)->value());
}
Representation Object::OptimalRepresentation() {
@ -1118,30 +1122,28 @@ void HeapObject::synchronized_set_map_word(MapWord map_word) {
int HeapObject::Size() const { return SizeFromMap(map()); }
double HeapNumber::value() const {
double HeapNumberBase::value() const {
return READ_DOUBLE_FIELD(this, kValueOffset);
}
void HeapNumber::set_value(double value) {
void HeapNumberBase::set_value(double value) {
WRITE_DOUBLE_FIELD(this, kValueOffset, value);
}
uint64_t HeapNumber::value_as_bits() const {
uint64_t HeapNumberBase::value_as_bits() const {
return READ_UINT64_FIELD(this, kValueOffset);
}
void HeapNumber::set_value_as_bits(uint64_t bits) {
void HeapNumberBase::set_value_as_bits(uint64_t bits) {
WRITE_UINT64_FIELD(this, kValueOffset, bits);
}
int HeapNumber::get_exponent() {
int HeapNumberBase::get_exponent() {
return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
kExponentShift) - kExponentBias;
}
int HeapNumber::get_sign() {
int HeapNumberBase::get_sign() {
return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
}
@ -1624,8 +1626,8 @@ void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) {
if (IsUnboxedDoubleField(index)) {
DCHECK(value->IsMutableHeapNumber());
// Ensure that all bits of the double value are preserved.
RawFastDoublePropertyAsBitsAtPut(index,
HeapNumber::cast(value)->value_as_bits());
RawFastDoublePropertyAsBitsAtPut(
index, MutableHeapNumber::cast(value)->value_as_bits());
} else {
RawFastPropertyAtPut(index, value);
}
@ -1656,8 +1658,7 @@ void JSObject::WriteToField(int descriptor, PropertyDetails details,
if (IsUnboxedDoubleField(index)) {
RawFastDoublePropertyAsBitsAtPut(index, bits);
} else {
HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index));
DCHECK(box->IsMutableHeapNumber());
auto box = MutableHeapNumber::cast(RawFastPropertyAt(index));
box->set_value_as_bits(bits);
}
} else {
@ -2730,18 +2731,6 @@ SMI_ACCESSORS(JSAsyncGeneratorObject, is_awaiting, kIsAwaitingOffset)
ACCESSORS(JSValue, value, Object, kValueOffset)
HeapNumber* HeapNumber::cast(Object* object) {
SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber());
return reinterpret_cast<HeapNumber*>(object);
}
const HeapNumber* HeapNumber::cast(const Object* object) {
SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber());
return reinterpret_cast<const HeapNumber*>(object);
}
ACCESSORS(JSDate, value, Object, kValueOffset)
ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset)
ACCESSORS(JSDate, year, Object, kYearOffset)

View File

@ -89,7 +89,7 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
break;
case MUTABLE_HEAP_NUMBER_TYPE:
os << "<mutable ";
HeapNumber::cast(this)->HeapNumberPrint(os);
MutableHeapNumber::cast(this)->MutableHeapNumberPrint(os);
os << ">\n";
break;
case BIGINT_TYPE:
@ -2144,6 +2144,12 @@ void MaybeObject::Print(std::ostream& os) {
#endif // OBJECT_PRINT
void HeapNumber::HeapNumberPrint(std::ostream& os) { os << value(); }
void MutableHeapNumber::MutableHeapNumberPrint(std::ostream& os) {
os << value();
}
// TODO(cbruni): remove once the new maptracer is in place.
void Name::NameShortPrint() {
if (this->IsString()) {

View File

@ -3449,14 +3449,14 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
break;
}
case HEAP_NUMBER_TYPE: {
os << "<Number ";
os << "<HeapNumber ";
HeapNumber::cast(this)->HeapNumberPrint(os);
os << ">";
break;
}
case MUTABLE_HEAP_NUMBER_TYPE: {
os << "<MutableNumber ";
HeapNumber::cast(this)->HeapNumberPrint(os);
os << "<MutableHeapNumber ";
MutableHeapNumber::cast(this)->MutableHeapNumberPrint(os);
os << '>';
break;
}
@ -3562,10 +3562,6 @@ bool HeapObject::IsValidSlot(Map* map, int offset) {
this, offset, 0);
}
void HeapNumber::HeapNumberPrint(std::ostream& os) { // NOLINT
os << value();
}
String* JSReceiver::class_name() {
if (IsFunction()) return GetHeap()->Function_string();
if (IsJSArgumentsObject()) return GetHeap()->Arguments_string();
@ -4003,7 +3999,7 @@ void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
DCHECK(details.representation().IsDouble());
DCHECK(!new_map->IsUnboxedDoubleField(index));
Handle<Object> value = isolate->factory()->NewMutableHeapNumber();
auto value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
object->RawFastPropertyAtPut(index, *value);
object->synchronized_set_map(*new_map);
return;
@ -4019,7 +4015,7 @@ void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
// Properly initialize newly added property.
Handle<Object> value;
if (details.representation().IsDouble()) {
value = isolate->factory()->NewMutableHeapNumber();
value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
} else {
value = isolate->factory()->uninitialized_value();
}
@ -4083,7 +4079,7 @@ void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
// must already be prepared for data of certain type.
DCHECK(!details.representation().IsNone());
if (details.representation().IsDouble()) {
value = isolate->factory()->NewMutableHeapNumber();
value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
} else {
value = isolate->factory()->uninitialized_value();
}
@ -4097,9 +4093,11 @@ void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
if (object->IsUnboxedDoubleField(index)) {
uint64_t old_bits = object->RawFastDoublePropertyAsBitsAt(index);
value = isolate->factory()->NewHeapNumberFromBits(
old_bits, representation.IsDouble() ? MUTABLE : IMMUTABLE);
if (representation.IsDouble()) {
value = isolate->factory()->NewMutableHeapNumberFromBits(old_bits);
} else {
value = isolate->factory()->NewHeapNumberFromBits(old_bits);
}
} else {
value = handle(object->RawFastPropertyAt(index), isolate);
if (!old_representation.IsDouble() && representation.IsDouble()) {
@ -4127,7 +4125,7 @@ void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
DCHECK_EQ(kData, details.kind());
Handle<Object> value;
if (details.representation().IsDouble()) {
value = isolate->factory()->NewMutableHeapNumber();
value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
} else {
value = isolate->factory()->uninitialized_value();
}
@ -4160,7 +4158,7 @@ void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
DCHECK(value->IsMutableHeapNumber());
// Ensure that all bits of the double value are preserved.
object->RawFastDoublePropertyAsBitsAtPut(
index, HeapNumber::cast(value)->value_as_bits());
index, MutableHeapNumber::cast(value)->value_as_bits());
if (i < old_number_of_fields && !old_map->IsUnboxedDoubleField(index)) {
// Transition from tagged to untagged slot.
heap->ClearRecordedSlot(*object,
@ -4233,8 +4231,8 @@ void MigrateFastToSlow(Handle<JSObject> object, Handle<Map> new_map,
value = handle(object->RawFastPropertyAt(index), isolate);
if (details.representation().IsDouble()) {
DCHECK(value->IsMutableHeapNumber());
Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
value = isolate->factory()->NewHeapNumber(old->value());
double old_value = Handle<MutableHeapNumber>::cast(value)->value();
value = isolate->factory()->NewHeapNumber(old_value);
}
}
} else {
@ -5976,7 +5974,7 @@ void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
if (!representation.IsDouble()) continue;
FieldIndex index = FieldIndex::ForDescriptor(*map, i);
if (map->IsUnboxedDoubleField(index)) continue;
Handle<HeapNumber> box = isolate->factory()->NewMutableHeapNumber();
auto box = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
if (index.is_inobject()) {
storage->set(index.property_index(), *box);
} else {

View File

@ -1981,10 +1981,11 @@ class FixedBodyDescriptor;
template <int start_offset>
class FlexibleBodyDescriptor;
// The HeapNumber class describes heap allocated numbers that cannot be
// represented in a Smi (small integer)
class HeapNumber: public HeapObject {
// represented in a Smi (small integer). MutableHeapNumber is the same, but its
// number value can change over time (it is used only as property storage).
// HeapNumberBase merely exists to avoid code duplication.
class HeapNumberBase : public HeapObject {
public:
// [value]: number value.
inline double value() const;
@ -1993,11 +1994,6 @@ class HeapNumber: public HeapObject {
inline uint64_t value_as_bits() const;
inline void set_value_as_bits(uint64_t bits);
DECL_CAST(HeapNumber)
V8_EXPORT_PRIVATE void HeapNumberPrint(std::ostream& os); // NOLINT
DECL_VERIFIER(HeapNumber)
inline int get_exponent();
inline int get_sign();
@ -2031,7 +2027,25 @@ class HeapNumber: public HeapObject {
static const int kNonMantissaBitsInTopWord = 12;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber);
DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumberBase)
};
class HeapNumber : public HeapNumberBase {
public:
DECL_CAST(HeapNumber)
V8_EXPORT_PRIVATE void HeapNumberPrint(std::ostream& os);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber)
};
class MutableHeapNumber : public HeapNumberBase {
public:
DECL_CAST(MutableHeapNumber)
V8_EXPORT_PRIVATE void MutableHeapNumberPrint(std::ostream& os);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(MutableHeapNumber)
};
enum EnsureElementsMode {

View File

@ -222,8 +222,8 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
Handle<HeapObject> object;
switch (request.kind()) {
case HeapObjectRequest::kHeapNumber:
object = isolate->factory()->NewHeapNumber(request.heap_number(),
IMMUTABLE, TENURED);
object =
isolate->factory()->NewHeapNumber(request.heap_number(), TENURED);
break;
case HeapObjectRequest::kCodeStub:
request.code_stub()->set_isolate(isolate);

View File

@ -122,9 +122,9 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
if (copying) copy->FastPropertyAtPut(index, *value);
} else if (copying && raw->IsMutableHeapNumber()) {
DCHECK(descriptors->GetDetails(i).representation().IsDouble());
uint64_t double_value = HeapNumber::cast(raw)->value_as_bits();
Handle<HeapNumber> value = isolate->factory()->NewHeapNumber(MUTABLE);
value->set_value_as_bits(double_value);
uint64_t double_value = MutableHeapNumber::cast(raw)->value_as_bits();
auto value =
isolate->factory()->NewMutableHeapNumberFromBits(double_value);
copy->FastPropertyAtPut(index, *value);
}
}

View File

@ -327,8 +327,8 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
Address pc = reinterpret_cast<Address>(buffer_ + request.offset());
switch (request.kind()) {
case HeapObjectRequest::kHeapNumber:
object = isolate->factory()->NewHeapNumber(request.heap_number(),
IMMUTABLE, TENURED);
object =
isolate->factory()->NewHeapNumber(request.heap_number(), TENURED);
set_target_address_at(pc, kNullAddress,
reinterpret_cast<Address>(object.location()),
SKIP_ICACHE_FLUSH);

View File

@ -356,9 +356,11 @@ Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) {
WriteOddball(Oddball::cast(*object));
return ThrowIfOutOfMemory();
case HEAP_NUMBER_TYPE:
case MUTABLE_HEAP_NUMBER_TYPE:
WriteHeapNumber(HeapNumber::cast(*object));
return ThrowIfOutOfMemory();
case MUTABLE_HEAP_NUMBER_TYPE:
WriteMutableHeapNumber(MutableHeapNumber::cast(*object));
return ThrowIfOutOfMemory();
case BIGINT_TYPE:
WriteBigInt(BigInt::cast(*object));
return ThrowIfOutOfMemory();
@ -425,6 +427,11 @@ void ValueSerializer::WriteHeapNumber(HeapNumber* number) {
WriteDouble(number->value());
}
void ValueSerializer::WriteMutableHeapNumber(MutableHeapNumber* number) {
WriteTag(SerializationTag::kDouble);
WriteDouble(number->value());
}
void ValueSerializer::WriteBigInt(BigInt* bigint) {
WriteTag(SerializationTag::kBigInt);
WriteBigIntContents(bigint);

View File

@ -29,6 +29,7 @@ class JSMap;
class JSRegExp;
class JSSet;
class JSValue;
class MutableHeapNumber;
class Object;
class Oddball;
class Smi;
@ -115,6 +116,7 @@ class ValueSerializer {
void WriteOddball(Oddball* oddball);
void WriteSmi(Smi* smi);
void WriteHeapNumber(HeapNumber* number);
void WriteMutableHeapNumber(MutableHeapNumber* number);
void WriteBigInt(BigInt* bigint);
void WriteString(Handle<String> string);
Maybe<bool> WriteJSReceiver(Handle<JSReceiver> receiver)

View File

@ -339,8 +339,8 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
Address pc = reinterpret_cast<Address>(buffer_) + request.offset();
switch (request.kind()) {
case HeapObjectRequest::kHeapNumber: {
Handle<HeapNumber> object = isolate->factory()->NewHeapNumber(
request.heap_number(), IMMUTABLE, TENURED);
Handle<HeapNumber> object =
isolate->factory()->NewHeapNumber(request.heap_number(), TENURED);
Memory::Object_Handle_at(pc) = object;
break;
}

View File

@ -3293,7 +3293,7 @@ TEST(jump_tables3) {
Handle<Object> values[kNumCases];
for (int i = 0; i < kNumCases; ++i) {
double value = isolate->random_number_generator()->NextDouble();
values[i] = isolate->factory()->NewHeapNumber(value, IMMUTABLE, TENURED);
values[i] = isolate->factory()->NewHeapNumber(value, TENURED);
}
Label labels[kNumCases];
Object* obj;

View File

@ -3423,7 +3423,7 @@ TEST(jump_tables3) {
Handle<Object> values[kNumCases];
for (int i = 0; i < kNumCases; ++i) {
double value = isolate->random_number_generator()->NextDouble();
values[i] = isolate->factory()->NewHeapNumber(value, IMMUTABLE, TENURED);
values[i] = isolate->factory()->NewHeapNumber(value, TENURED);
}
Label labels[kNumCases];
Object* obj;

View File

@ -2777,10 +2777,10 @@ TEST(HoleyMutableHeapNumber) {
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<HeapNumber> mhn = isolate->factory()->NewMutableHeapNumber();
auto mhn = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
CHECK_EQ(kHoleNanInt64, mhn->value_as_bits());
mhn = isolate->factory()->NewHeapNumber(0.0, MUTABLE);
mhn = isolate->factory()->NewMutableHeapNumber(0.0);
CHECK_EQ(uint64_t{0}, mhn->value_as_bits());
mhn->set_value_as_bits(kHoleNanInt64);
@ -2793,11 +2793,11 @@ TEST(HoleyMutableHeapNumber) {
Object::NewStorageFor(isolate, isolate->factory()->uninitialized_value(),
Representation::Double());
CHECK(obj->IsMutableHeapNumber());
CHECK_EQ(kHoleNanInt64, HeapNumber::cast(*obj)->value_as_bits());
CHECK_EQ(kHoleNanInt64, MutableHeapNumber::cast(*obj)->value_as_bits());
obj = Object::NewStorageFor(isolate, mhn, Representation::Double());
CHECK(obj->IsMutableHeapNumber());
CHECK_EQ(kHoleNanInt64, HeapNumber::cast(*obj)->value_as_bits());
CHECK_EQ(kHoleNanInt64, MutableHeapNumber::cast(*obj)->value_as_bits());
}
} // namespace test_field_type_tracking

View File

@ -1100,7 +1100,7 @@ TEST(DoScavenge) {
double boom_value = bit_cast<double>(fake_object);
FieldIndex field_index = FieldIndex::ForDescriptor(obj->map(), 0);
Handle<HeapNumber> boom_number = factory->NewHeapNumber(boom_value, MUTABLE);
auto boom_number = factory->NewMutableHeapNumber(boom_value);
obj->FastPropertyAtPut(field_index, *boom_number);
// Now |obj| moves to old gen and it has a double field that looks like