backport_1084820.patch 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
  2. From: Cheng Zhao <[email protected]>
  3. Date: Thu, 4 Oct 2018 14:57:02 -0700
  4. Subject: fix: object materialization
  5. [1084820] [High] [CVE-2020-6512]: DCHECK failure in value.IsHeapObject() in objects
  6. debug.cc
  7. Backport https://chromium.googlesource.com/v8/v8.git/+/c16f62d6e943756d8b4170a36f61e666ced82e6d
  8. diff --git a/src/deoptimizer/deoptimizer.cc b/src/deoptimizer/deoptimizer.cc
  9. index 5655d045c0bca8166aac6176bd6468e55ff0decc..ce6e5ff214313c4298322b74f909631a5ba2ccdc 100644
  10. --- a/src/deoptimizer/deoptimizer.cc
  11. +++ b/src/deoptimizer/deoptimizer.cc
  12. @@ -47,7 +47,6 @@ class FrameWriter {
  13. void PushRawValue(intptr_t value, const char* debug_hint) {
  14. PushValue(value);
  15. -
  16. if (trace_scope_ != nullptr) {
  17. DebugPrintOutputValue(value, debug_hint);
  18. }
  19. @@ -82,13 +81,10 @@ class FrameWriter {
  20. void PushTranslatedValue(const TranslatedFrame::iterator& iterator,
  21. const char* debug_hint = "") {
  22. Object obj = iterator->GetRawValue();
  23. -
  24. PushRawObject(obj, debug_hint);
  25. -
  26. if (trace_scope_) {
  27. PrintF(trace_scope_->file(), " (input #%d)\n", iterator.input_index());
  28. }
  29. -
  30. deoptimizer_->QueueValueForMaterialization(output_address(top_offset_), obj,
  31. iterator);
  32. }
  33. @@ -2394,6 +2390,11 @@ int TranslatedValue::object_index() const {
  34. Object TranslatedValue::GetRawValue() const {
  35. // If we have a value, return it.
  36. if (materialization_state() == kFinished) {
  37. + int smi;
  38. + if (storage_->IsHeapNumber() &&
  39. + DoubleToSmiInteger(storage_->Number(), &smi)) {
  40. + return Smi::FromInt(smi);
  41. + }
  42. return *storage_;
  43. }
  44. @@ -2436,6 +2437,22 @@ Object TranslatedValue::GetRawValue() const {
  45. }
  46. }
  47. + case kFloat: {
  48. + int smi;
  49. + if (DoubleToSmiInteger(float_value().get_scalar(), &smi)) {
  50. + return Smi::FromInt(smi);
  51. + }
  52. + break;
  53. + }
  54. +
  55. + case kDouble: {
  56. + int smi;
  57. + if (DoubleToSmiInteger(double_value().get_scalar(), &smi)) {
  58. + return Smi::FromInt(smi);
  59. + }
  60. + break;
  61. + }
  62. +
  63. default:
  64. break;
  65. }
  66. @@ -2445,106 +2462,76 @@ Object TranslatedValue::GetRawValue() const {
  67. return ReadOnlyRoots(isolate()).arguments_marker();
  68. }
  69. -void TranslatedValue::set_initialized_storage(Handle<Object> storage) {
  70. +void TranslatedValue::set_initialized_storage(Handle<HeapObject> storage) {
  71. DCHECK_EQ(kUninitialized, materialization_state());
  72. storage_ = storage;
  73. materialization_state_ = kFinished;
  74. }
  75. Handle<Object> TranslatedValue::GetValue() {
  76. - // If we already have a value, then get it.
  77. - if (materialization_state() == kFinished) return storage_;
  78. -
  79. - // Otherwise we have to materialize.
  80. - switch (kind()) {
  81. - case TranslatedValue::kTagged:
  82. - case TranslatedValue::kInt32:
  83. - case TranslatedValue::kInt64:
  84. - case TranslatedValue::kUInt32:
  85. - case TranslatedValue::kBoolBit:
  86. - case TranslatedValue::kFloat:
  87. - case TranslatedValue::kDouble: {
  88. - MaterializeSimple();
  89. - return storage_;
  90. - }
  91. -
  92. - case TranslatedValue::kCapturedObject:
  93. - case TranslatedValue::kDuplicatedObject: {
  94. - // We need to materialize the object (or possibly even object graphs).
  95. - // To make the object verifier happy, we materialize in two steps.
  96. -
  97. - // 1. Allocate storage for reachable objects. This makes sure that for
  98. - // each object we have allocated space on heap. The space will be
  99. - // a byte array that will be later initialized, or a fully
  100. - // initialized object if it is safe to allocate one that will
  101. - // pass the verifier.
  102. - container_->EnsureObjectAllocatedAt(this);
  103. -
  104. - // 2. Initialize the objects. If we have allocated only byte arrays
  105. - // for some objects, we now overwrite the byte arrays with the
  106. - // correct object fields. Note that this phase does not allocate
  107. - // any new objects, so it does not trigger the object verifier.
  108. - return container_->InitializeObjectAt(this);
  109. - }
  110. -
  111. - case TranslatedValue::kInvalid:
  112. - FATAL("unexpected case");
  113. - return Handle<Object>::null();
  114. + Handle<Object> value(GetRawValue(), isolate());
  115. + if (materialization_state() == kFinished) return value;
  116. +
  117. + if (value->IsSmi()) {
  118. + // Even though stored as a Smi, this number might instead be needed as a
  119. + // HeapNumber when materializing a JSObject with a field of HeapObject
  120. + // representation. Since we don't have this information available here, we
  121. + // just always allocate a HeapNumber and later extract the Smi again if we
  122. + // don't need a HeapObject.
  123. + set_initialized_storage(
  124. + isolate()->factory()->NewHeapNumber(value->Number()));
  125. + return value;
  126. }
  127. - FATAL("internal error: value missing");
  128. - return Handle<Object>::null();
  129. -}
  130. -
  131. -void TranslatedValue::MaterializeSimple() {
  132. - // If we already have materialized, return.
  133. - if (materialization_state() == kFinished) return;
  134. -
  135. - Object raw_value = GetRawValue();
  136. - if (raw_value != ReadOnlyRoots(isolate()).arguments_marker()) {
  137. - // We can get the value without allocation, just return it here.
  138. - set_initialized_storage(Handle<Object>(raw_value, isolate()));
  139. - return;
  140. + if (*value != ReadOnlyRoots(isolate()).arguments_marker()) {
  141. + set_initialized_storage(Handle<HeapObject>::cast(value));
  142. + return storage_;
  143. }
  144. - switch (kind()) {
  145. - case kInt32:
  146. - set_initialized_storage(
  147. - Handle<Object>(isolate()->factory()->NewNumber(int32_value())));
  148. - return;
  149. + // Otherwise we have to materialize.
  150. - case kInt64:
  151. - set_initialized_storage(Handle<Object>(
  152. - isolate()->factory()->NewNumber(static_cast<double>(int64_value()))));
  153. - return;
  154. + if (kind() == TranslatedValue::kCapturedObject ||
  155. + kind() == TranslatedValue::kDuplicatedObject) {
  156. + // We need to materialize the object (or possibly even object graphs).
  157. + // To make the object verifier happy, we materialize in two steps.
  158. - case kUInt32:
  159. - set_initialized_storage(
  160. - Handle<Object>(isolate()->factory()->NewNumber(uint32_value())));
  161. - return;
  162. + // 1. Allocate storage for reachable objects. This makes sure that for
  163. + // each object we have allocated space on heap. The space will be
  164. + // a byte array that will be later initialized, or a fully
  165. + // initialized object if it is safe to allocate one that will
  166. + // pass the verifier.
  167. + container_->EnsureObjectAllocatedAt(this);
  168. - case kFloat: {
  169. - double scalar_value = float_value().get_scalar();
  170. - set_initialized_storage(
  171. - Handle<Object>(isolate()->factory()->NewNumber(scalar_value)));
  172. - return;
  173. - }
  174. -
  175. - case kDouble: {
  176. - double scalar_value = double_value().get_scalar();
  177. - set_initialized_storage(
  178. - Handle<Object>(isolate()->factory()->NewNumber(scalar_value)));
  179. - return;
  180. - }
  181. + // 2. Initialize the objects. If we have allocated only byte arrays
  182. + // for some objects, we now overwrite the byte arrays with the
  183. + // correct object fields. Note that this phase does not allocate
  184. + // any new objects, so it does not trigger the object verifier.
  185. + return container_->InitializeObjectAt(this);
  186. + }
  187. - case kCapturedObject:
  188. - case kDuplicatedObject:
  189. - case kInvalid:
  190. - case kTagged:
  191. - case kBoolBit:
  192. - FATAL("internal error: unexpected materialization.");
  193. + double number;
  194. + switch (kind()) {
  195. + case TranslatedValue::kInt32:
  196. + number = int32_value();
  197. + break;
  198. + case TranslatedValue::kInt64:
  199. + number = int64_value();
  200. + break;
  201. + case TranslatedValue::kUInt32:
  202. + number = uint32_value();
  203. + break;
  204. + case TranslatedValue::kFloat:
  205. + number = float_value().get_scalar();
  206. break;
  207. + case TranslatedValue::kDouble:
  208. + number = double_value().get_scalar();
  209. + break;
  210. + default:
  211. + UNREACHABLE();
  212. }
  213. + DCHECK(!IsSmiDouble(number));
  214. + set_initialized_storage(isolate()->factory()->NewHeapNumber(number));
  215. + return storage_;
  216. }
  217. bool TranslatedValue::IsMaterializedObject() const {
  218. @@ -2600,8 +2587,9 @@ Float64 TranslatedState::GetDoubleSlot(Address fp, int slot_offset) {
  219. }
  220. void TranslatedValue::Handlify() {
  221. - if (kind() == kTagged) {
  222. - set_initialized_storage(Handle<Object>(raw_literal(), isolate()));
  223. + if (kind() == kTagged && raw_literal().IsHeapObject()) {
  224. + set_initialized_storage(
  225. + Handle<HeapObject>(HeapObject::cast(raw_literal()), isolate()));
  226. raw_literal_ = Object();
  227. }
  228. }
  229. @@ -3352,7 +3340,7 @@ TranslatedValue* TranslatedState::GetValueByObjectIndex(int object_index) {
  230. return &(frames_[pos.frame_index_].values_[pos.value_index_]);
  231. }
  232. -Handle<Object> TranslatedState::InitializeObjectAt(TranslatedValue* slot) {
  233. +Handle<HeapObject> TranslatedState::InitializeObjectAt(TranslatedValue* slot) {
  234. slot = ResolveCapturedObject(slot);
  235. DisallowHeapAllocation no_allocation;
  236. @@ -3367,7 +3355,7 @@ Handle<Object> TranslatedState::InitializeObjectAt(TranslatedValue* slot) {
  237. InitializeCapturedObjectAt(index, &worklist, no_allocation);
  238. }
  239. }
  240. - return slot->GetStorage();
  241. + return slot->storage();
  242. }
  243. void TranslatedState::InitializeCapturedObjectAt(
  244. @@ -3467,11 +3455,17 @@ void TranslatedState::EnsureObjectAllocatedAt(TranslatedValue* slot) {
  245. }
  246. }
  247. +int TranslatedValue::GetSmiValue() const {
  248. + Object value = GetRawValue();
  249. + CHECK(value.IsSmi());
  250. + return Smi::cast(value).value();
  251. +}
  252. +
  253. void TranslatedState::MaterializeFixedDoubleArray(TranslatedFrame* frame,
  254. int* value_index,
  255. TranslatedValue* slot,
  256. Handle<Map> map) {
  257. - int length = Smi::cast(frame->values_[*value_index].GetRawValue()).value();
  258. + int length = frame->values_[*value_index].GetSmiValue();
  259. (*value_index)++;
  260. Handle<FixedDoubleArray> array = Handle<FixedDoubleArray>::cast(
  261. isolate()->factory()->NewFixedDoubleArray(length));
  262. @@ -3505,10 +3499,10 @@ void TranslatedState::MaterializeHeapNumber(TranslatedFrame* frame,
  263. namespace {
  264. -enum DoubleStorageKind : uint8_t {
  265. +enum StorageKind : uint8_t {
  266. kStoreTagged,
  267. kStoreUnboxedDouble,
  268. - kStoreMutableHeapNumber,
  269. + kStoreHeapObject
  270. };
  271. } // namespace
  272. @@ -3580,9 +3574,7 @@ void TranslatedState::EnsureCapturedObjectAllocatedAt(
  273. case SIMPLE_NUMBER_DICTIONARY_TYPE:
  274. case STRING_TABLE_TYPE: {
  275. // Check we have the right size.
  276. - int array_length =
  277. - Smi::cast(frame->values_[value_index].GetRawValue()).value();
  278. -
  279. + int array_length = frame->values_[value_index].GetSmiValue();
  280. int instance_size = FixedArray::SizeFor(array_length);
  281. CHECK_EQ(instance_size, slot->GetChildrenCount() * kTaggedSize);
  282. @@ -3601,13 +3593,13 @@ void TranslatedState::EnsureCapturedObjectAllocatedAt(
  283. case PROPERTY_ARRAY_TYPE: {
  284. // Check we have the right size.
  285. - int length_or_hash =
  286. - Smi::cast(frame->values_[value_index].GetRawValue()).value();
  287. + int length_or_hash = frame->values_[value_index].GetSmiValue();
  288. int array_length = PropertyArray::LengthField::decode(length_or_hash);
  289. int instance_size = PropertyArray::SizeFor(array_length);
  290. CHECK_EQ(instance_size, slot->GetChildrenCount() * kTaggedSize);
  291. slot->set_storage(AllocateStorageFor(slot));
  292. +
  293. // Make sure all the remaining children (after the map) are allocated.
  294. return EnsureChildrenAllocated(slot->GetChildrenCount() - 1, frame,
  295. &value_index, worklist);
  296. @@ -3652,7 +3644,7 @@ void TranslatedState::EnsureChildrenAllocated(int count, TranslatedFrame* frame,
  297. } else {
  298. // Make sure the simple values (heap numbers, etc.) are properly
  299. // initialized.
  300. - child_slot->MaterializeSimple();
  301. + child_slot->GetValue();
  302. }
  303. SkipSlots(1, frame, value_index);
  304. }
  305. @@ -3667,16 +3659,17 @@ void TranslatedState::EnsurePropertiesAllocatedAndMarked(
  306. properties_slot->mark_allocated();
  307. properties_slot->set_storage(object_storage);
  308. - // Set markers for the double properties.
  309. + // Set markers for out-of-object properties.
  310. Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate());
  311. for (InternalIndex i : map->IterateOwnDescriptors()) {
  312. FieldIndex index = FieldIndex::ForDescriptor(*map, i);
  313. - if (descriptors->GetDetails(i).representation().IsDouble() &&
  314. - !index.is_inobject()) {
  315. + Representation representation = descriptors->GetDetails(i).representation();
  316. + if (!index.is_inobject() &&
  317. + (representation.IsDouble() || representation.IsHeapObject())) {
  318. CHECK(!map->IsUnboxedDoubleField(index));
  319. int outobject_index = index.outobject_array_index();
  320. int array_index = outobject_index * kTaggedSize;
  321. - object_storage->set(array_index, kStoreMutableHeapNumber);
  322. + object_storage->set(array_index, kStoreHeapObject);
  323. }
  324. }
  325. }
  326. @@ -3702,31 +3695,44 @@ void TranslatedState::EnsureJSObjectAllocated(TranslatedValue* slot,
  327. // Now we handle the interesting (JSObject) case.
  328. Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate());
  329. - // Set markers for the double properties.
  330. + // Set markers for in-object properties.
  331. for (InternalIndex i : map->IterateOwnDescriptors()) {
  332. FieldIndex index = FieldIndex::ForDescriptor(*map, i);
  333. - if (descriptors->GetDetails(i).representation().IsDouble() &&
  334. - index.is_inobject()) {
  335. + Representation representation = descriptors->GetDetails(i).representation();
  336. + if (index.is_inobject() &&
  337. + (representation.IsDouble() || representation.IsHeapObject())) {
  338. CHECK_GE(index.index(), FixedArray::kHeaderSize / kTaggedSize);
  339. int array_index = index.index() * kTaggedSize - FixedArray::kHeaderSize;
  340. - uint8_t marker = map->IsUnboxedDoubleField(index)
  341. - ? kStoreUnboxedDouble
  342. - : kStoreMutableHeapNumber;
  343. + uint8_t marker = map->IsUnboxedDoubleField(index) ? kStoreUnboxedDouble
  344. + : kStoreHeapObject;
  345. object_storage->set(array_index, marker);
  346. }
  347. }
  348. slot->set_storage(object_storage);
  349. }
  350. -Handle<Object> TranslatedState::GetValueAndAdvance(TranslatedFrame* frame,
  351. - int* value_index) {
  352. - TranslatedValue* slot = frame->ValueAt(*value_index);
  353. - SkipSlots(1, frame, value_index);
  354. +TranslatedValue* TranslatedState::GetResolvedSlot(TranslatedFrame* frame,
  355. + int value_index) {
  356. + TranslatedValue* slot = frame->ValueAt(value_index);
  357. if (slot->kind() == TranslatedValue::kDuplicatedObject) {
  358. slot = ResolveCapturedObject(slot);
  359. }
  360. - CHECK_NE(TranslatedValue::kUninitialized, slot->materialization_state());
  361. - return slot->GetStorage();
  362. + CHECK_NE(slot->materialization_state(), TranslatedValue::kUninitialized);
  363. + return slot;
  364. +}
  365. +
  366. +TranslatedValue* TranslatedState::GetResolvedSlotAndAdvance(
  367. + TranslatedFrame* frame, int* value_index) {
  368. + TranslatedValue* slot = GetResolvedSlot(frame, *value_index);
  369. + SkipSlots(1, frame, value_index);
  370. + return slot;
  371. +}
  372. +
  373. +Handle<Object> TranslatedState::GetValueAndAdvance(TranslatedFrame* frame,
  374. + int* value_index) {
  375. + TranslatedValue* slot = GetResolvedSlot(frame, *value_index);
  376. + SkipSlots(1, frame, value_index);
  377. + return slot->GetValue();
  378. }
  379. void TranslatedState::InitializeJSObjectAt(
  380. @@ -3754,29 +3760,25 @@ void TranslatedState::InitializeJSObjectAt(
  381. // marker to see if we store an unboxed double.
  382. DCHECK_EQ(kTaggedSize, JSObject::kPropertiesOrHashOffset);
  383. for (int i = 2; i < slot->GetChildrenCount(); i++) {
  384. - // Initialize and extract the value from its slot.
  385. - Handle<Object> field_value = GetValueAndAdvance(frame, value_index);
  386. -
  387. + TranslatedValue* slot = GetResolvedSlotAndAdvance(frame, value_index);
  388. // Read out the marker and ensure the field is consistent with
  389. // what the markers in the storage say (note that all heap numbers
  390. // should be fully initialized by now).
  391. int offset = i * kTaggedSize;
  392. uint8_t marker = object_storage->ReadField<uint8_t>(offset);
  393. if (marker == kStoreUnboxedDouble) {
  394. - double double_field_value;
  395. - if (field_value->IsSmi()) {
  396. - double_field_value = Smi::cast(*field_value).value();
  397. - } else {
  398. - CHECK(field_value->IsHeapNumber());
  399. - double_field_value = HeapNumber::cast(*field_value).value();
  400. - }
  401. - object_storage->WriteField<double>(offset, double_field_value);
  402. - } else if (marker == kStoreMutableHeapNumber) {
  403. + Handle<HeapObject> field_value = slot->storage();
  404. CHECK(field_value->IsHeapNumber());
  405. + object_storage->WriteField<double>(offset, field_value->Number());
  406. + } else if (marker == kStoreHeapObject) {
  407. + Handle<HeapObject> field_value = slot->storage();
  408. WRITE_FIELD(*object_storage, offset, *field_value);
  409. WRITE_BARRIER(*object_storage, offset, *field_value);
  410. } else {
  411. CHECK_EQ(kStoreTagged, marker);
  412. + Handle<Object> field_value = slot->GetValue();
  413. + DCHECK_IMPLIES(field_value->IsHeapNumber(),
  414. + !IsSmiDouble(field_value->Number()));
  415. WRITE_FIELD(*object_storage, offset, *field_value);
  416. WRITE_BARRIER(*object_storage, offset, *field_value);
  417. }
  418. @@ -3802,15 +3804,18 @@ void TranslatedState::InitializeObjectWithTaggedFieldsAt(
  419. // Write the fields to the object.
  420. for (int i = 1; i < slot->GetChildrenCount(); i++) {
  421. - Handle<Object> field_value = GetValueAndAdvance(frame, value_index);
  422. + TranslatedValue* slot = GetResolvedSlotAndAdvance(frame, value_index);
  423. int offset = i * kTaggedSize;
  424. uint8_t marker = object_storage->ReadField<uint8_t>(offset);
  425. - if (i > 1 && marker == kStoreMutableHeapNumber) {
  426. - CHECK(field_value->IsHeapNumber());
  427. + Handle<Object> field_value;
  428. + if (i > 1 && marker == kStoreHeapObject) {
  429. + field_value = slot->storage();
  430. } else {
  431. CHECK(marker == kStoreTagged || i == 1);
  432. + field_value = slot->GetValue();
  433. + DCHECK_IMPLIES(field_value->IsHeapNumber(),
  434. + !IsSmiDouble(field_value->Number()));
  435. }
  436. -
  437. WRITE_FIELD(*object_storage, offset, *field_value);
  438. WRITE_BARRIER(*object_storage, offset, *field_value);
  439. }
  440. @@ -3877,10 +3882,7 @@ TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex(
  441. // argument (the receiver).
  442. static constexpr int kTheContext = 1;
  443. const int height = frames_[i].height() + kTheContext;
  444. - Object argc_object = frames_[i].ValueAt(height - 1)->GetRawValue();
  445. - CHECK(argc_object.IsSmi());
  446. - *args_count = Smi::ToInt(argc_object);
  447. -
  448. + *args_count = frames_[i].ValueAt(height - 1)->GetSmiValue();
  449. DCHECK_EQ(*args_count, 1);
  450. } else {
  451. *args_count = InternalFormalParameterCountWithReceiver(
  452. @@ -3922,21 +3924,30 @@ void TranslatedState::StoreMaterializedValuesAndDeopt(JavaScriptFrame* frame) {
  453. CHECK(value_info->IsMaterializedObject());
  454. - // Skip duplicate objects (i.e., those that point to some
  455. - // other object id).
  456. + // Skip duplicate objects (i.e., those that point to some other object id).
  457. if (value_info->object_index() != i) continue;
  458. + Handle<Object> previous_value(previously_materialized_objects->get(i),
  459. + isolate_);
  460. Handle<Object> value(value_info->GetRawValue(), isolate_);
  461. - if (!value.is_identical_to(marker)) {
  462. - if (previously_materialized_objects->get(i) == *marker) {
  463. + if (value.is_identical_to(marker)) {
  464. + DCHECK_EQ(*previous_value, *marker);
  465. + } else {
  466. + if (*previous_value == *marker) {
  467. + if (value->IsSmi()) {
  468. + value = isolate()->factory()->NewHeapNumber(value->Number());
  469. + }
  470. previously_materialized_objects->set(i, *value);
  471. value_changed = true;
  472. } else {
  473. - CHECK(previously_materialized_objects->get(i) == *value);
  474. + CHECK(*previous_value == *value ||
  475. + (previous_value->IsHeapNumber() && value->IsSmi() &&
  476. + previous_value->Number() == value->Number()));
  477. }
  478. }
  479. }
  480. +
  481. if (new_store && value_changed) {
  482. materialized_store->Set(stack_frame_pointer_,
  483. previously_materialized_objects);
  484. @@ -3970,8 +3981,10 @@ void TranslatedState::UpdateFromPreviouslyMaterializedObjects() {
  485. CHECK(value_info->IsMaterializedObject());
  486. if (value_info->kind() == TranslatedValue::kCapturedObject) {
  487. - value_info->set_initialized_storage(
  488. - Handle<Object>(previously_materialized_objects->get(i), isolate_));
  489. + Handle<Object> object(previously_materialized_objects->get(i),
  490. + isolate_);
  491. + CHECK(object->IsHeapObject());
  492. + value_info->set_initialized_storage(Handle<HeapObject>::cast(object));
  493. }
  494. }
  495. }
  496. @@ -3985,7 +3998,7 @@ void TranslatedState::VerifyMaterializedObjects() {
  497. if (slot->kind() == TranslatedValue::kCapturedObject) {
  498. CHECK_EQ(slot, GetValueByObjectIndex(slot->object_index()));
  499. if (slot->materialization_state() == TranslatedValue::kFinished) {
  500. - slot->GetStorage()->ObjectVerify(isolate());
  501. + slot->storage()->ObjectVerify(isolate());
  502. } else {
  503. CHECK_EQ(slot->materialization_state(),
  504. TranslatedValue::kUninitialized);
  505. diff --git a/src/deoptimizer/deoptimizer.h b/src/deoptimizer/deoptimizer.h
  506. index 6d0a350aaceb59fa6486d41566ad22ee3fbe1bdd..3d8155616cfa4730c1a8665f3180856eaf7f9133 100644
  507. --- a/src/deoptimizer/deoptimizer.h
  508. +++ b/src/deoptimizer/deoptimizer.h
  509. @@ -39,13 +39,17 @@ enum class BuiltinContinuationMode;
  510. class TranslatedValue {
  511. public:
  512. - // Allocation-less getter of the value.
  513. + // Allocation-free getter of the value.
  514. // Returns ReadOnlyRoots::arguments_marker() if allocation would be necessary
  515. - // to get the value.
  516. + // to get the value. In the case of numbers, returns a Smi if possible.
  517. Object GetRawValue() const;
  518. - // Getter for the value, takes care of materializing the subgraph
  519. - // reachable from this value.
  520. + // Convenience wrapper around GetRawValue (checked).
  521. + int GetSmiValue() const;
  522. +
  523. + // Returns the value, possibly materializing it first (and the whole subgraph
  524. + // reachable from this value). In the case of numbers, returns a Smi if
  525. + // possible.
  526. Handle<Object> GetValue();
  527. bool IsMaterializedObject() const;
  528. @@ -102,15 +106,14 @@ class TranslatedValue {
  529. static TranslatedValue NewInvalid(TranslatedState* container);
  530. Isolate* isolate() const;
  531. - void MaterializeSimple();
  532. void set_storage(Handle<HeapObject> storage) { storage_ = storage; }
  533. - void set_initialized_storage(Handle<Object> storage);
  534. + void set_initialized_storage(Handle<HeapObject> storage);
  535. void mark_finished() { materialization_state_ = kFinished; }
  536. void mark_allocated() { materialization_state_ = kAllocated; }
  537. - Handle<Object> GetStorage() {
  538. - DCHECK_NE(kUninitialized, materialization_state());
  539. + Handle<HeapObject> storage() {
  540. + DCHECK_NE(materialization_state(), kUninitialized);
  541. return storage_;
  542. }
  543. @@ -120,9 +123,9 @@ class TranslatedValue {
  544. // objects and constructing handles (to get
  545. // to the isolate).
  546. - Handle<Object> storage_; // Contains the materialized value or the
  547. - // byte-array that will be later morphed into
  548. - // the materialized object.
  549. + Handle<HeapObject> storage_; // Contains the materialized value or the
  550. + // byte-array that will be later morphed into
  551. + // the materialized object.
  552. struct MaterializedObjectInfo {
  553. int id_;
  554. @@ -376,7 +379,7 @@ class TranslatedState {
  555. int* value_index, std::stack<int>* worklist);
  556. void EnsureCapturedObjectAllocatedAt(int object_index,
  557. std::stack<int>* worklist);
  558. - Handle<Object> InitializeObjectAt(TranslatedValue* slot);
  559. + Handle<HeapObject> InitializeObjectAt(TranslatedValue* slot);
  560. void InitializeCapturedObjectAt(int object_index, std::stack<int>* worklist,
  561. const DisallowHeapAllocation& no_allocation);
  562. void InitializeJSObjectAt(TranslatedFrame* frame, int* value_index,
  563. @@ -392,6 +395,9 @@ class TranslatedState {
  564. TranslatedValue* ResolveCapturedObject(TranslatedValue* slot);
  565. TranslatedValue* GetValueByObjectIndex(int object_index);
  566. Handle<Object> GetValueAndAdvance(TranslatedFrame* frame, int* value_index);
  567. + TranslatedValue* GetResolvedSlot(TranslatedFrame* frame, int value_index);
  568. + TranslatedValue* GetResolvedSlotAndAdvance(TranslatedFrame* frame,
  569. + int* value_index);
  570. static uint32_t GetUInt32Slot(Address fp, int slot_index);
  571. static uint64_t GetUInt64Slot(Address fp, int slot_index);
  572. @@ -772,7 +778,7 @@ class FrameDescription {
  573. intptr_t continuation_;
  574. // This must be at the end of the object as the object is allocated larger
  575. - // than it's definition indicate to extend this array.
  576. + // than its definition indicates to extend this array.
  577. intptr_t frame_content_[1];
  578. intptr_t* GetFrameSlotPointer(unsigned offset) {
  579. diff --git a/test/mjsunit/compiler/regress-1084820.js b/test/mjsunit/compiler/regress-1084820.js
  580. new file mode 100644
  581. index 0000000000000000000000000000000000000000..beb168b413ff045c5aff8e68d2e6da32b27800d6
  582. --- /dev/null
  583. +++ b/test/mjsunit/compiler/regress-1084820.js
  584. @@ -0,0 +1,27 @@
  585. +// Copyright 2020 the V8 project authors. All rights reserved.
  586. +// Use of this source code is governed by a BSD-style license that can be
  587. +// found in the LICENSE file.
  588. +
  589. +// Flags: --allow-natives-syntax
  590. +
  591. +// Create a map where 'my_property' has HeapObject representation.
  592. +const dummy_obj = {};
  593. +dummy_obj.my_property = 'some HeapObject';
  594. +dummy_obj.my_property = 'some other HeapObject';
  595. +
  596. +function gaga() {
  597. + const obj = {};
  598. + // Store a HeapNumber and then a Smi.
  599. + // This must happen in a loop, even if it's only 2 iterations:
  600. + for (let j = -3_000_000_000; j <= -1_000_000_000; j += 2_000_000_000) {
  601. + obj.my_property = j;
  602. + }
  603. + // Trigger (soft) deopt.
  604. + if (!%IsBeingInterpreted()) obj + obj;
  605. +}
  606. +
  607. +%PrepareFunctionForOptimization(gaga);
  608. +gaga();
  609. +gaga();
  610. +%OptimizeFunctionOnNextCall(gaga);
  611. +gaga();
  612. diff --git a/test/mjsunit/compiler/regress-1092650.js b/test/mjsunit/compiler/regress-1092650.js
  613. new file mode 100644
  614. index 0000000000000000000000000000000000000000..ba94375aeb8262536e28d5d409d69115e385c3b3
  615. --- /dev/null
  616. +++ b/test/mjsunit/compiler/regress-1092650.js
  617. @@ -0,0 +1,23 @@
  618. +// Copyright 2020 the V8 project authors. All rights reserved.
  619. +// Use of this source code is governed by a BSD-style license that can be
  620. +// found in the LICENSE file.
  621. +
  622. +// Flags: --allow-natives-syntax
  623. +
  624. +// Create map with HeapNumber in field 'a'
  625. +({a: 2**30});
  626. +
  627. +function foo() {
  628. + return foo.arguments[0];
  629. +}
  630. +
  631. +function main() {
  632. + foo({a: 42});
  633. +}
  634. +
  635. +%PrepareFunctionForOptimization(foo);
  636. +%PrepareFunctionForOptimization(main);
  637. +main();
  638. +main();
  639. +%OptimizeFunctionOnNextCall(main);
  640. +main();
  641. diff --git a/test/mjsunit/compiler/regress-1094132.js b/test/mjsunit/compiler/regress-1094132.js
  642. new file mode 100644
  643. index 0000000000000000000000000000000000000000..418637d86f8c363b9c0c41c450914e758ff73e9c
  644. --- /dev/null
  645. +++ b/test/mjsunit/compiler/regress-1094132.js
  646. @@ -0,0 +1,78 @@
  647. +// Copyright 2020 the V8 project authors. All rights reserved.
  648. +// Use of this source code is governed by a BSD-style license that can be
  649. +// found in the LICENSE file.
  650. +
  651. +// Flags: --allow-natives-syntax
  652. +
  653. +function prettyPrinted() {}
  654. +
  655. +function formatFailureText() {
  656. + if (expectedText.length <= 40 && foundText.length <= 40) {
  657. + message += ": expected <" + expectedText + "> found <" + foundText + ">";
  658. + message += ":\nexpected:\n" + expectedText + "\nfound:\n" + foundText;
  659. + }
  660. +}
  661. +
  662. +function fail(expectedText, found, name_opt) {
  663. + formatFailureText(expectedText, found, name_opt);
  664. + if (!a[aProps[i]][aProps[i]]) { }
  665. +}
  666. +
  667. +function deepEquals(a, b) {
  668. + if (a === 0) return 1 / a === 1 / b;
  669. + if (typeof a !== typeof a) return false;
  670. + if (typeof a !== "object" && typeof a !== "function") return false;
  671. + if (objectClass !== classOf()) return false;
  672. + if (objectClass === "RegExp") { }
  673. +}
  674. +
  675. +function assertEquals() {
  676. + if (!deepEquals()) {
  677. + fail(prettyPrinted(), undefined, undefined);
  678. + }
  679. +}
  680. +
  681. +({y: {}, x: 0.42});
  682. +
  683. +function gaga() {
  684. + return {gx: bar.arguments[0], hx: baz.arguments[0]};
  685. +}
  686. +
  687. +function baz() {
  688. + return gaga();
  689. +}
  690. +
  691. +function bar(obj) {
  692. + return baz(obj.y);
  693. +}
  694. +
  695. +function foo() {
  696. + bar({y: {}, x: 42});
  697. + try { assertEquals() } catch (e) {}
  698. + try { assertEquals() } catch (e) {}
  699. + assertEquals();
  700. +}
  701. +
  702. +%PrepareFunctionForOptimization(prettyPrinted);
  703. +%PrepareFunctionForOptimization(formatFailureText);
  704. +%PrepareFunctionForOptimization(fail);
  705. +%PrepareFunctionForOptimization(deepEquals);
  706. +%PrepareFunctionForOptimization(assertEquals);
  707. +%PrepareFunctionForOptimization(gaga);
  708. +%PrepareFunctionForOptimization(baz);
  709. +%PrepareFunctionForOptimization(bar);
  710. +%PrepareFunctionForOptimization(foo);
  711. +try { foo() } catch (e) {}
  712. +%OptimizeFunctionOnNextCall(foo);
  713. +try { foo() } catch (e) {}
  714. +%PrepareFunctionForOptimization(prettyPrinted);
  715. +%PrepareFunctionForOptimization(formatFailureText);
  716. +%PrepareFunctionForOptimization(fail);
  717. +%PrepareFunctionForOptimization(deepEquals);
  718. +%PrepareFunctionForOptimization(assertEquals);
  719. +%PrepareFunctionForOptimization(gaga);
  720. +%PrepareFunctionForOptimization(baz);
  721. +%PrepareFunctionForOptimization(bar);
  722. +%PrepareFunctionForOptimization(foo);
  723. +%OptimizeFunctionOnNextCall(foo);
  724. +try { foo() } catch (e) {}