123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770 |
- From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
- From: Cheng Zhao <[email protected]>
- Date: Thu, 4 Oct 2018 14:57:02 -0700
- Subject: fix: object materialization
- [1084820] [High] [CVE-2020-6512]: DCHECK failure in value.IsHeapObject() in objects-debug.cc
- Backport https://chromium.googlesource.com/v8/v8.git/+/c16f62d6e943756d8b4170a36f61e666ced82e6d
- diff --git a/src/deoptimizer/deoptimizer.cc b/src/deoptimizer/deoptimizer.cc
- index 9fcccd483c6a10a42a217c61d7ef60f50b3e4f07..44c92f557046dbb4268b218d0753367356ee9cd3 100644
- --- a/src/deoptimizer/deoptimizer.cc
- +++ b/src/deoptimizer/deoptimizer.cc
- @@ -48,7 +48,6 @@ class FrameWriter {
-
- void PushRawValue(intptr_t value, const char* debug_hint) {
- PushValue(value);
- -
- if (trace_scope_ != nullptr) {
- DebugPrintOutputValue(value, debug_hint);
- }
- @@ -83,13 +82,10 @@ class FrameWriter {
- void PushTranslatedValue(const TranslatedFrame::iterator& iterator,
- const char* debug_hint = "") {
- Object obj = iterator->GetRawValue();
- -
- PushRawObject(obj, debug_hint);
- -
- if (trace_scope_) {
- PrintF(trace_scope_->file(), " (input #%d)\n", iterator.input_index());
- }
- -
- deoptimizer_->QueueValueForMaterialization(output_address(top_offset_), obj,
- iterator);
- }
- @@ -2428,6 +2424,11 @@ int TranslatedValue::object_index() const {
- Object TranslatedValue::GetRawValue() const {
- // If we have a value, return it.
- if (materialization_state() == kFinished) {
- + int smi;
- + if (storage_->IsHeapNumber() &&
- + DoubleToSmiInteger(storage_->Number(), &smi)) {
- + return Smi::FromInt(smi);
- + }
- return *storage_;
- }
-
- @@ -2470,6 +2471,22 @@ Object TranslatedValue::GetRawValue() const {
- }
- }
-
- + case kFloat: {
- + int smi;
- + if (DoubleToSmiInteger(float_value().get_scalar(), &smi)) {
- + return Smi::FromInt(smi);
- + }
- + break;
- + }
- +
- + case kDouble: {
- + int smi;
- + if (DoubleToSmiInteger(double_value().get_scalar(), &smi)) {
- + return Smi::FromInt(smi);
- + }
- + break;
- + }
- +
- default:
- break;
- }
- @@ -2479,106 +2496,76 @@ Object TranslatedValue::GetRawValue() const {
- return ReadOnlyRoots(isolate()).arguments_marker();
- }
-
- -void TranslatedValue::set_initialized_storage(Handle<Object> storage) {
- +void TranslatedValue::set_initialized_storage(Handle<HeapObject> storage) {
- DCHECK_EQ(kUninitialized, materialization_state());
- storage_ = storage;
- materialization_state_ = kFinished;
- }
-
- Handle<Object> TranslatedValue::GetValue() {
- - // If we already have a value, then get it.
- - if (materialization_state() == kFinished) return storage_;
- -
- - // Otherwise we have to materialize.
- - switch (kind()) {
- - case TranslatedValue::kTagged:
- - case TranslatedValue::kInt32:
- - case TranslatedValue::kInt64:
- - case TranslatedValue::kUInt32:
- - case TranslatedValue::kBoolBit:
- - case TranslatedValue::kFloat:
- - case TranslatedValue::kDouble: {
- - MaterializeSimple();
- - return storage_;
- - }
- -
- - case TranslatedValue::kCapturedObject:
- - case TranslatedValue::kDuplicatedObject: {
- - // We need to materialize the object (or possibly even object graphs).
- - // To make the object verifier happy, we materialize in two steps.
- -
- - // 1. Allocate storage for reachable objects. This makes sure that for
- - // each object we have allocated space on heap. The space will be
- - // a byte array that will be later initialized, or a fully
- - // initialized object if it is safe to allocate one that will
- - // pass the verifier.
- - container_->EnsureObjectAllocatedAt(this);
- -
- - // 2. Initialize the objects. If we have allocated only byte arrays
- - // for some objects, we now overwrite the byte arrays with the
- - // correct object fields. Note that this phase does not allocate
- - // any new objects, so it does not trigger the object verifier.
- - return container_->InitializeObjectAt(this);
- - }
- -
- - case TranslatedValue::kInvalid:
- - FATAL("unexpected case");
- - return Handle<Object>::null();
- + Handle<Object> value(GetRawValue(), isolate());
- + if (materialization_state() == kFinished) return value;
- +
- + if (value->IsSmi()) {
- + // Even though stored as a Smi, this number might instead be needed as a
- + // HeapNumber when materializing a JSObject with a field of HeapObject
- + // representation. Since we don't have this information available here, we
- + // just always allocate a HeapNumber and later extract the Smi again if we
- + // don't need a HeapObject.
- + set_initialized_storage(
- + isolate()->factory()->NewHeapNumber(value->Number()));
- + return value;
- }
-
- - FATAL("internal error: value missing");
- - return Handle<Object>::null();
- -}
- -
- -void TranslatedValue::MaterializeSimple() {
- - // If we already have materialized, return.
- - if (materialization_state() == kFinished) return;
- -
- - Object raw_value = GetRawValue();
- - if (raw_value != ReadOnlyRoots(isolate()).arguments_marker()) {
- - // We can get the value without allocation, just return it here.
- - set_initialized_storage(Handle<Object>(raw_value, isolate()));
- - return;
- + if (*value != ReadOnlyRoots(isolate()).arguments_marker()) {
- + set_initialized_storage(Handle<HeapObject>::cast(value));
- + return storage_;
- }
-
- - switch (kind()) {
- - case kInt32:
- - set_initialized_storage(
- - Handle<Object>(isolate()->factory()->NewNumber(int32_value())));
- - return;
- + // Otherwise we have to materialize.
-
- - case kInt64:
- - set_initialized_storage(Handle<Object>(
- - isolate()->factory()->NewNumber(static_cast<double>(int64_value()))));
- - return;
- + if (kind() == TranslatedValue::kCapturedObject ||
- + kind() == TranslatedValue::kDuplicatedObject) {
- + // We need to materialize the object (or possibly even object graphs).
- + // To make the object verifier happy, we materialize in two steps.
-
- - case kUInt32:
- - set_initialized_storage(
- - Handle<Object>(isolate()->factory()->NewNumber(uint32_value())));
- - return;
- + // 1. Allocate storage for reachable objects. This makes sure that for
- + // each object we have allocated space on heap. The space will be
- + // a byte array that will be later initialized, or a fully
- + // initialized object if it is safe to allocate one that will
- + // pass the verifier.
- + container_->EnsureObjectAllocatedAt(this);
-
- - case kFloat: {
- - double scalar_value = float_value().get_scalar();
- - set_initialized_storage(
- - Handle<Object>(isolate()->factory()->NewNumber(scalar_value)));
- - return;
- - }
- -
- - case kDouble: {
- - double scalar_value = double_value().get_scalar();
- - set_initialized_storage(
- - Handle<Object>(isolate()->factory()->NewNumber(scalar_value)));
- - return;
- - }
- + // 2. Initialize the objects. If we have allocated only byte arrays
- + // for some objects, we now overwrite the byte arrays with the
- + // correct object fields. Note that this phase does not allocate
- + // any new objects, so it does not trigger the object verifier.
- + return container_->InitializeObjectAt(this);
- + }
-
- - case kCapturedObject:
- - case kDuplicatedObject:
- - case kInvalid:
- - case kTagged:
- - case kBoolBit:
- - FATAL("internal error: unexpected materialization.");
- + double number;
- + switch (kind()) {
- + case TranslatedValue::kInt32:
- + number = int32_value();
- + break;
- + case TranslatedValue::kInt64:
- + number = int64_value();
- + break;
- + case TranslatedValue::kUInt32:
- + number = uint32_value();
- + break;
- + case TranslatedValue::kFloat:
- + number = float_value().get_scalar();
- break;
- + case TranslatedValue::kDouble:
- + number = double_value().get_scalar();
- + break;
- + default:
- + UNREACHABLE();
- }
- + DCHECK(!IsSmiDouble(number));
- + set_initialized_storage(isolate()->factory()->NewHeapNumber(number));
- + return storage_;
- }
-
- bool TranslatedValue::IsMaterializedObject() const {
- @@ -2634,8 +2621,9 @@ Float64 TranslatedState::GetDoubleSlot(Address fp, int slot_offset) {
- }
-
- void TranslatedValue::Handlify() {
- - if (kind() == kTagged) {
- - set_initialized_storage(Handle<Object>(raw_literal(), isolate()));
- + if (kind() == kTagged && raw_literal().IsHeapObject()) {
- + set_initialized_storage(
- + Handle<HeapObject>(HeapObject::cast(raw_literal()), isolate()));
- raw_literal_ = Object();
- }
- }
- @@ -3386,7 +3374,7 @@ TranslatedValue* TranslatedState::GetValueByObjectIndex(int object_index) {
- return &(frames_[pos.frame_index_].values_[pos.value_index_]);
- }
-
- -Handle<Object> TranslatedState::InitializeObjectAt(TranslatedValue* slot) {
- +Handle<HeapObject> TranslatedState::InitializeObjectAt(TranslatedValue* slot) {
- slot = ResolveCapturedObject(slot);
-
- DisallowHeapAllocation no_allocation;
- @@ -3401,7 +3389,7 @@ Handle<Object> TranslatedState::InitializeObjectAt(TranslatedValue* slot) {
- InitializeCapturedObjectAt(index, &worklist, no_allocation);
- }
- }
- - return slot->GetStorage();
- + return slot->storage();
- }
-
- void TranslatedState::InitializeCapturedObjectAt(
- @@ -3501,11 +3489,17 @@ void TranslatedState::EnsureObjectAllocatedAt(TranslatedValue* slot) {
- }
- }
-
- +int TranslatedValue::GetSmiValue() const {
- + Object value = GetRawValue();
- + CHECK(value.IsSmi());
- + return Smi::cast(value).value();
- +}
- +
- void TranslatedState::MaterializeFixedDoubleArray(TranslatedFrame* frame,
- int* value_index,
- TranslatedValue* slot,
- Handle<Map> map) {
- - int length = Smi::cast(frame->values_[*value_index].GetRawValue()).value();
- + int length = frame->values_[*value_index].GetSmiValue();
- (*value_index)++;
- Handle<FixedDoubleArray> array = Handle<FixedDoubleArray>::cast(
- isolate()->factory()->NewFixedDoubleArray(length));
- @@ -3539,10 +3533,10 @@ void TranslatedState::MaterializeHeapNumber(TranslatedFrame* frame,
-
- namespace {
-
- -enum DoubleStorageKind : uint8_t {
- +enum StorageKind : uint8_t {
- kStoreTagged,
- kStoreUnboxedDouble,
- - kStoreMutableHeapNumber,
- + kStoreHeapObject
- };
-
- } // namespace
- @@ -3614,9 +3608,7 @@ void TranslatedState::EnsureCapturedObjectAllocatedAt(
- case SIMPLE_NUMBER_DICTIONARY_TYPE:
- case STRING_TABLE_TYPE: {
- // Check we have the right size.
- - int array_length =
- - Smi::cast(frame->values_[value_index].GetRawValue()).value();
- -
- + int array_length = frame->values_[value_index].GetSmiValue();
- int instance_size = FixedArray::SizeFor(array_length);
- CHECK_EQ(instance_size, slot->GetChildrenCount() * kTaggedSize);
-
- @@ -3635,13 +3627,13 @@ void TranslatedState::EnsureCapturedObjectAllocatedAt(
-
- case PROPERTY_ARRAY_TYPE: {
- // Check we have the right size.
- - int length_or_hash =
- - Smi::cast(frame->values_[value_index].GetRawValue()).value();
- + int length_or_hash = frame->values_[value_index].GetSmiValue();
- int array_length = PropertyArray::LengthField::decode(length_or_hash);
- int instance_size = PropertyArray::SizeFor(array_length);
- CHECK_EQ(instance_size, slot->GetChildrenCount() * kTaggedSize);
-
- slot->set_storage(AllocateStorageFor(slot));
- +
- // Make sure all the remaining children (after the map) are allocated.
- return EnsureChildrenAllocated(slot->GetChildrenCount() - 1, frame,
- &value_index, worklist);
- @@ -3686,7 +3678,7 @@ void TranslatedState::EnsureChildrenAllocated(int count, TranslatedFrame* frame,
- } else {
- // Make sure the simple values (heap numbers, etc.) are properly
- // initialized.
- - child_slot->MaterializeSimple();
- + child_slot->GetValue();
- }
- SkipSlots(1, frame, value_index);
- }
- @@ -3701,16 +3693,17 @@ void TranslatedState::EnsurePropertiesAllocatedAndMarked(
- properties_slot->mark_allocated();
- properties_slot->set_storage(object_storage);
-
- - // Set markers for the double properties.
- + // Set markers for out-of-object properties.
- Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate());
- for (InternalIndex i : map->IterateOwnDescriptors()) {
- FieldIndex index = FieldIndex::ForDescriptor(*map, i);
- - if (descriptors->GetDetails(i).representation().IsDouble() &&
- - !index.is_inobject()) {
- + Representation representation = descriptors->GetDetails(i).representation();
- + if (!index.is_inobject() &&
- + (representation.IsDouble() || representation.IsHeapObject())) {
- CHECK(!map->IsUnboxedDoubleField(index));
- int outobject_index = index.outobject_array_index();
- int array_index = outobject_index * kTaggedSize;
- - object_storage->set(array_index, kStoreMutableHeapNumber);
- + object_storage->set(array_index, kStoreHeapObject);
- }
- }
- }
- @@ -3736,31 +3729,44 @@ void TranslatedState::EnsureJSObjectAllocated(TranslatedValue* slot,
- // Now we handle the interesting (JSObject) case.
- Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate());
-
- - // Set markers for the double properties.
- + // Set markers for in-object properties.
- for (InternalIndex i : map->IterateOwnDescriptors()) {
- FieldIndex index = FieldIndex::ForDescriptor(*map, i);
- - if (descriptors->GetDetails(i).representation().IsDouble() &&
- - index.is_inobject()) {
- + Representation representation = descriptors->GetDetails(i).representation();
- + if (index.is_inobject() &&
- + (representation.IsDouble() || representation.IsHeapObject())) {
- CHECK_GE(index.index(), FixedArray::kHeaderSize / kTaggedSize);
- int array_index = index.index() * kTaggedSize - FixedArray::kHeaderSize;
- - uint8_t marker = map->IsUnboxedDoubleField(index)
- - ? kStoreUnboxedDouble
- - : kStoreMutableHeapNumber;
- + uint8_t marker = map->IsUnboxedDoubleField(index) ? kStoreUnboxedDouble
- + : kStoreHeapObject;
- object_storage->set(array_index, marker);
- }
- }
- slot->set_storage(object_storage);
- }
-
- -Handle<Object> TranslatedState::GetValueAndAdvance(TranslatedFrame* frame,
- - int* value_index) {
- - TranslatedValue* slot = frame->ValueAt(*value_index);
- - SkipSlots(1, frame, value_index);
- +TranslatedValue* TranslatedState::GetResolvedSlot(TranslatedFrame* frame,
- + int value_index) {
- + TranslatedValue* slot = frame->ValueAt(value_index);
- if (slot->kind() == TranslatedValue::kDuplicatedObject) {
- slot = ResolveCapturedObject(slot);
- }
- - CHECK_NE(TranslatedValue::kUninitialized, slot->materialization_state());
- - return slot->GetStorage();
- + CHECK_NE(slot->materialization_state(), TranslatedValue::kUninitialized);
- + return slot;
- +}
- +
- +TranslatedValue* TranslatedState::GetResolvedSlotAndAdvance(
- + TranslatedFrame* frame, int* value_index) {
- + TranslatedValue* slot = GetResolvedSlot(frame, *value_index);
- + SkipSlots(1, frame, value_index);
- + return slot;
- +}
- +
- +Handle<Object> TranslatedState::GetValueAndAdvance(TranslatedFrame* frame,
- + int* value_index) {
- + TranslatedValue* slot = GetResolvedSlot(frame, *value_index);
- + SkipSlots(1, frame, value_index);
- + return slot->GetValue();
- }
-
- void TranslatedState::InitializeJSObjectAt(
- @@ -3788,29 +3794,25 @@ void TranslatedState::InitializeJSObjectAt(
- // marker to see if we store an unboxed double.
- DCHECK_EQ(kTaggedSize, JSObject::kPropertiesOrHashOffset);
- for (int i = 2; i < slot->GetChildrenCount(); i++) {
- - // Initialize and extract the value from its slot.
- - Handle<Object> field_value = GetValueAndAdvance(frame, value_index);
- -
- + TranslatedValue* slot = GetResolvedSlotAndAdvance(frame, value_index);
- // Read out the marker and ensure the field is consistent with
- // what the markers in the storage say (note that all heap numbers
- // should be fully initialized by now).
- int offset = i * kTaggedSize;
- uint8_t marker = object_storage->ReadField<uint8_t>(offset);
- if (marker == kStoreUnboxedDouble) {
- - double double_field_value;
- - if (field_value->IsSmi()) {
- - double_field_value = Smi::cast(*field_value).value();
- - } else {
- - CHECK(field_value->IsHeapNumber());
- - double_field_value = HeapNumber::cast(*field_value).value();
- - }
- - object_storage->WriteField<double>(offset, double_field_value);
- - } else if (marker == kStoreMutableHeapNumber) {
- + Handle<HeapObject> field_value = slot->storage();
- CHECK(field_value->IsHeapNumber());
- + object_storage->WriteField<double>(offset, field_value->Number());
- + } else if (marker == kStoreHeapObject) {
- + Handle<HeapObject> field_value = slot->storage();
- WRITE_FIELD(*object_storage, offset, *field_value);
- WRITE_BARRIER(*object_storage, offset, *field_value);
- } else {
- CHECK_EQ(kStoreTagged, marker);
- + Handle<Object> field_value = slot->GetValue();
- + DCHECK_IMPLIES(field_value->IsHeapNumber(),
- + !IsSmiDouble(field_value->Number()));
- WRITE_FIELD(*object_storage, offset, *field_value);
- WRITE_BARRIER(*object_storage, offset, *field_value);
- }
- @@ -3836,15 +3838,18 @@ void TranslatedState::InitializeObjectWithTaggedFieldsAt(
-
- // Write the fields to the object.
- for (int i = 1; i < slot->GetChildrenCount(); i++) {
- - Handle<Object> field_value = GetValueAndAdvance(frame, value_index);
- + TranslatedValue* slot = GetResolvedSlotAndAdvance(frame, value_index);
- int offset = i * kTaggedSize;
- uint8_t marker = object_storage->ReadField<uint8_t>(offset);
- - if (i > 1 && marker == kStoreMutableHeapNumber) {
- - CHECK(field_value->IsHeapNumber());
- + Handle<Object> field_value;
- + if (i > 1 && marker == kStoreHeapObject) {
- + field_value = slot->storage();
- } else {
- CHECK(marker == kStoreTagged || i == 1);
- + field_value = slot->GetValue();
- + DCHECK_IMPLIES(field_value->IsHeapNumber(),
- + !IsSmiDouble(field_value->Number()));
- }
- -
- WRITE_FIELD(*object_storage, offset, *field_value);
- WRITE_BARRIER(*object_storage, offset, *field_value);
- }
- @@ -3911,10 +3916,7 @@ TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex(
- // argument (the receiver).
- static constexpr int kTheContext = 1;
- const int height = frames_[i].height() + kTheContext;
- - Object argc_object = frames_[i].ValueAt(height - 1)->GetRawValue();
- - CHECK(argc_object.IsSmi());
- - *args_count = Smi::ToInt(argc_object);
- -
- + *args_count = frames_[i].ValueAt(height - 1)->GetSmiValue();
- DCHECK_EQ(*args_count, 1);
- } else {
- *args_count = InternalFormalParameterCountWithReceiver(
- @@ -3956,21 +3958,30 @@ void TranslatedState::StoreMaterializedValuesAndDeopt(JavaScriptFrame* frame) {
-
- CHECK(value_info->IsMaterializedObject());
-
- - // Skip duplicate objects (i.e., those that point to some
- - // other object id).
- + // Skip duplicate objects (i.e., those that point to some other object id).
- if (value_info->object_index() != i) continue;
-
- + Handle<Object> previous_value(previously_materialized_objects->get(i),
- + isolate_);
- Handle<Object> value(value_info->GetRawValue(), isolate_);
-
- - if (!value.is_identical_to(marker)) {
- - if (previously_materialized_objects->get(i) == *marker) {
- + if (value.is_identical_to(marker)) {
- + DCHECK_EQ(*previous_value, *marker);
- + } else {
- + if (*previous_value == *marker) {
- + if (value->IsSmi()) {
- + value = isolate()->factory()->NewHeapNumber(value->Number());
- + }
- previously_materialized_objects->set(i, *value);
- value_changed = true;
- } else {
- - CHECK(previously_materialized_objects->get(i) == *value);
- + CHECK(*previous_value == *value ||
- + (previous_value->IsHeapNumber() && value->IsSmi() &&
- + previous_value->Number() == value->Number()));
- }
- }
- }
- +
- if (new_store && value_changed) {
- materialized_store->Set(stack_frame_pointer_,
- previously_materialized_objects);
- @@ -4004,8 +4015,10 @@ void TranslatedState::UpdateFromPreviouslyMaterializedObjects() {
- CHECK(value_info->IsMaterializedObject());
-
- if (value_info->kind() == TranslatedValue::kCapturedObject) {
- - value_info->set_initialized_storage(
- - Handle<Object>(previously_materialized_objects->get(i), isolate_));
- + Handle<Object> object(previously_materialized_objects->get(i),
- + isolate_);
- + CHECK(object->IsHeapObject());
- + value_info->set_initialized_storage(Handle<HeapObject>::cast(object));
- }
- }
- }
- @@ -4019,7 +4032,7 @@ void TranslatedState::VerifyMaterializedObjects() {
- if (slot->kind() == TranslatedValue::kCapturedObject) {
- CHECK_EQ(slot, GetValueByObjectIndex(slot->object_index()));
- if (slot->materialization_state() == TranslatedValue::kFinished) {
- - slot->GetStorage()->ObjectVerify(isolate());
- + slot->storage()->ObjectVerify(isolate());
- } else {
- CHECK_EQ(slot->materialization_state(),
- TranslatedValue::kUninitialized);
- diff --git a/src/deoptimizer/deoptimizer.h b/src/deoptimizer/deoptimizer.h
- index 2766ed7c6381a279d6161c058ea33fffe9860426..6c68ea1f96f00df51008a14d3ca7c7e672c47f0f 100644
- --- a/src/deoptimizer/deoptimizer.h
- +++ b/src/deoptimizer/deoptimizer.h
- @@ -39,13 +39,17 @@ enum class BuiltinContinuationMode;
-
- class TranslatedValue {
- public:
- - // Allocation-less getter of the value.
- + // Allocation-free getter of the value.
- // Returns ReadOnlyRoots::arguments_marker() if allocation would be necessary
- - // to get the value.
- + // to get the value. In the case of numbers, returns a Smi if possible.
- Object GetRawValue() const;
-
- - // Getter for the value, takes care of materializing the subgraph
- - // reachable from this value.
- + // Convenience wrapper around GetRawValue (checked).
- + int GetSmiValue() const;
- +
- + // Returns the value, possibly materializing it first (and the whole subgraph
- + // reachable from this value). In the case of numbers, returns a Smi if
- + // possible.
- Handle<Object> GetValue();
-
- bool IsMaterializedObject() const;
- @@ -102,15 +106,14 @@ class TranslatedValue {
- static TranslatedValue NewInvalid(TranslatedState* container);
-
- Isolate* isolate() const;
- - void MaterializeSimple();
-
- void set_storage(Handle<HeapObject> storage) { storage_ = storage; }
- - void set_initialized_storage(Handle<Object> storage);
- + void set_initialized_storage(Handle<HeapObject> storage);
- void mark_finished() { materialization_state_ = kFinished; }
- void mark_allocated() { materialization_state_ = kAllocated; }
-
- - Handle<Object> GetStorage() {
- - DCHECK_NE(kUninitialized, materialization_state());
- + Handle<HeapObject> storage() {
- + DCHECK_NE(materialization_state(), kUninitialized);
- return storage_;
- }
-
- @@ -120,9 +123,9 @@ class TranslatedValue {
- // objects and constructing handles (to get
- // to the isolate).
-
- - Handle<Object> storage_; // Contains the materialized value or the
- - // byte-array that will be later morphed into
- - // the materialized object.
- + Handle<HeapObject> storage_; // Contains the materialized value or the
- + // byte-array that will be later morphed into
- + // the materialized object.
-
- struct MaterializedObjectInfo {
- int id_;
- @@ -376,7 +379,7 @@ class TranslatedState {
- int* value_index, std::stack<int>* worklist);
- void EnsureCapturedObjectAllocatedAt(int object_index,
- std::stack<int>* worklist);
- - Handle<Object> InitializeObjectAt(TranslatedValue* slot);
- + Handle<HeapObject> InitializeObjectAt(TranslatedValue* slot);
- void InitializeCapturedObjectAt(int object_index, std::stack<int>* worklist,
- const DisallowHeapAllocation& no_allocation);
- void InitializeJSObjectAt(TranslatedFrame* frame, int* value_index,
- @@ -392,6 +395,9 @@ class TranslatedState {
- TranslatedValue* ResolveCapturedObject(TranslatedValue* slot);
- TranslatedValue* GetValueByObjectIndex(int object_index);
- Handle<Object> GetValueAndAdvance(TranslatedFrame* frame, int* value_index);
- + TranslatedValue* GetResolvedSlot(TranslatedFrame* frame, int value_index);
- + TranslatedValue* GetResolvedSlotAndAdvance(TranslatedFrame* frame,
- + int* value_index);
-
- static uint32_t GetUInt32Slot(Address fp, int slot_index);
- static uint64_t GetUInt64Slot(Address fp, int slot_index);
- @@ -773,7 +779,7 @@ class FrameDescription {
- intptr_t continuation_;
-
- // This must be at the end of the object as the object is allocated larger
- - // than it's definition indicate to extend this array.
- + // than its definition indicates to extend this array.
- intptr_t frame_content_[1];
-
- intptr_t* GetFrameSlotPointer(unsigned offset) {
- diff --git a/test/mjsunit/compiler/regress-1084820.js b/test/mjsunit/compiler/regress-1084820.js
- new file mode 100644
- index 0000000000000000000000000000000000000000..beb168b413ff045c5aff8e68d2e6da32b27800d6
- --- /dev/null
- +++ b/test/mjsunit/compiler/regress-1084820.js
- @@ -0,0 +1,27 @@
- +// Copyright 2020 the V8 project authors. All rights reserved.
- +// Use of this source code is governed by a BSD-style license that can be
- +// found in the LICENSE file.
- +
- +// Flags: --allow-natives-syntax
- +
- +// Create a map where 'my_property' has HeapObject representation.
- +const dummy_obj = {};
- +dummy_obj.my_property = 'some HeapObject';
- +dummy_obj.my_property = 'some other HeapObject';
- +
- +function gaga() {
- + const obj = {};
- + // Store a HeapNumber and then a Smi.
- + // This must happen in a loop, even if it's only 2 iterations:
- + for (let j = -3_000_000_000; j <= -1_000_000_000; j += 2_000_000_000) {
- + obj.my_property = j;
- + }
- + // Trigger (soft) deopt.
- + if (!%IsBeingInterpreted()) obj + obj;
- +}
- +
- +%PrepareFunctionForOptimization(gaga);
- +gaga();
- +gaga();
- +%OptimizeFunctionOnNextCall(gaga);
- +gaga();
- diff --git a/test/mjsunit/compiler/regress-1092650.js b/test/mjsunit/compiler/regress-1092650.js
- new file mode 100644
- index 0000000000000000000000000000000000000000..ba94375aeb8262536e28d5d409d69115e385c3b3
- --- /dev/null
- +++ b/test/mjsunit/compiler/regress-1092650.js
- @@ -0,0 +1,23 @@
- +// Copyright 2020 the V8 project authors. All rights reserved.
- +// Use of this source code is governed by a BSD-style license that can be
- +// found in the LICENSE file.
- +
- +// Flags: --allow-natives-syntax
- +
- +// Create map with HeapNumber in field 'a'
- +({a: 2**30});
- +
- +function foo() {
- + return foo.arguments[0];
- +}
- +
- +function main() {
- + foo({a: 42});
- +}
- +
- +%PrepareFunctionForOptimization(foo);
- +%PrepareFunctionForOptimization(main);
- +main();
- +main();
- +%OptimizeFunctionOnNextCall(main);
- +main();
- diff --git a/test/mjsunit/compiler/regress-1094132.js b/test/mjsunit/compiler/regress-1094132.js
- new file mode 100644
- index 0000000000000000000000000000000000000000..418637d86f8c363b9c0c41c450914e758ff73e9c
- --- /dev/null
- +++ b/test/mjsunit/compiler/regress-1094132.js
- @@ -0,0 +1,78 @@
- +// Copyright 2020 the V8 project authors. All rights reserved.
- +// Use of this source code is governed by a BSD-style license that can be
- +// found in the LICENSE file.
- +
- +// Flags: --allow-natives-syntax
- +
- +function prettyPrinted() {}
- +
- +function formatFailureText() {
- + if (expectedText.length <= 40 && foundText.length <= 40) {
- + message += ": expected <" + expectedText + "> found <" + foundText + ">";
- + message += ":\nexpected:\n" + expectedText + "\nfound:\n" + foundText;
- + }
- +}
- +
- +function fail(expectedText, found, name_opt) {
- + formatFailureText(expectedText, found, name_opt);
- + if (!a[aProps[i]][aProps[i]]) { }
- +}
- +
- +function deepEquals(a, b) {
- + if (a === 0) return 1 / a === 1 / b;
- + if (typeof a !== typeof a) return false;
- + if (typeof a !== "object" && typeof a !== "function") return false;
- + if (objectClass !== classOf()) return false;
- + if (objectClass === "RegExp") { }
- +}
- +
- +function assertEquals() {
- + if (!deepEquals()) {
- + fail(prettyPrinted(), undefined, undefined);
- + }
- +}
- +
- +({y: {}, x: 0.42});
- +
- +function gaga() {
- + return {gx: bar.arguments[0], hx: baz.arguments[0]};
- +}
- +
- +function baz() {
- + return gaga();
- +}
- +
- +function bar(obj) {
- + return baz(obj.y);
- +}
- +
- +function foo() {
- + bar({y: {}, x: 42});
- + try { assertEquals() } catch (e) {}
- + try { assertEquals() } catch (e) {}
- + assertEquals();
- +}
- +
- +%PrepareFunctionForOptimization(prettyPrinted);
- +%PrepareFunctionForOptimization(formatFailureText);
- +%PrepareFunctionForOptimization(fail);
- +%PrepareFunctionForOptimization(deepEquals);
- +%PrepareFunctionForOptimization(assertEquals);
- +%PrepareFunctionForOptimization(gaga);
- +%PrepareFunctionForOptimization(baz);
- +%PrepareFunctionForOptimization(bar);
- +%PrepareFunctionForOptimization(foo);
- +try { foo() } catch (e) {}
- +%OptimizeFunctionOnNextCall(foo);
- +try { foo() } catch (e) {}
- +%PrepareFunctionForOptimization(prettyPrinted);
- +%PrepareFunctionForOptimization(formatFailureText);
- +%PrepareFunctionForOptimization(fail);
- +%PrepareFunctionForOptimization(deepEquals);
- +%PrepareFunctionForOptimization(assertEquals);
- +%PrepareFunctionForOptimization(gaga);
- +%PrepareFunctionForOptimization(baz);
- +%PrepareFunctionForOptimization(bar);
- +%PrepareFunctionForOptimization(foo);
- +%OptimizeFunctionOnNextCall(foo);
- +try { foo() } catch (e) {}
|