Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(630)

Side by Side Diff: src/map-updater.cc

Issue 2601643002: [runtime] Add MapUpdater class that manages all kinds of map updates. (Closed)
Patch Set: Addressing comments Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/map-updater.h ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/map-updater.h"
6
7 #include "src/field-type.h"
8 #include "src/handles.h"
9 #include "src/isolate.h"
10 #include "src/objects-inl.h"
11 #include "src/objects.h"
12 #include "src/transitions.h"
13
14 namespace v8 {
15 namespace internal {
16
17 namespace {
18
19 inline bool EqualImmutableValues(Object* obj1, Object* obj2) {
20 if (obj1 == obj2) return true; // Valid for both kData and kAccessor kinds.
21 // TODO(ishell): compare AccessorPairs.
22 return false;
23 }
24
25 } // namespace
26
27 Name* MapUpdater::GetKey(int descriptor) const {
28 return old_descriptors_->GetKey(descriptor);
29 }
30
31 PropertyDetails MapUpdater::GetDetails(int descriptor) const {
32 DCHECK_LE(0, descriptor);
33 if (descriptor == modified_descriptor_) {
34 return PropertyDetails(new_kind_, new_attributes_, new_location_,
35 new_representation_);
36 }
37 return old_descriptors_->GetDetails(descriptor);
38 }
39
40 Object* MapUpdater::GetValue(int descriptor) const {
41 DCHECK_LE(0, descriptor);
42 if (descriptor == modified_descriptor_) {
43 DCHECK_EQ(kDescriptor, new_location_);
44 return *new_value_;
45 }
46 DCHECK_EQ(kDescriptor, GetDetails(descriptor).location());
47 return old_descriptors_->GetValue(descriptor);
48 }
49
50 FieldType* MapUpdater::GetFieldType(int descriptor) const {
51 DCHECK_LE(0, descriptor);
52 if (descriptor == modified_descriptor_) {
53 DCHECK_EQ(kField, new_location_);
54 return *new_field_type_;
55 }
56 DCHECK_EQ(kField, GetDetails(descriptor).location());
57 return old_descriptors_->GetFieldType(descriptor);
58 }
59
60 Handle<FieldType> MapUpdater::GetOrComputeFieldType(
61 int descriptor, PropertyLocation location,
62 Representation representation) const {
63 DCHECK_LE(0, descriptor);
64 // |location| is just a pre-fetched GetDetails(descriptor).location().
65 DCHECK_EQ(location, GetDetails(descriptor).location());
66 if (location == kField) {
67 return handle(GetFieldType(descriptor), isolate_);
68 } else {
69 return GetValue(descriptor)->OptimalType(isolate_, representation);
70 }
71 }
72
73 Handle<FieldType> MapUpdater::GetOrComputeFieldType(
74 Handle<DescriptorArray> descriptors, int descriptor,
75 PropertyLocation location, Representation representation) {
76 // |location| is just a pre-fetched GetDetails(descriptor).location().
77 DCHECK_EQ(descriptors->GetDetails(descriptor).location(), location);
78 if (location == kField) {
79 return handle(descriptors->GetFieldType(descriptor), isolate_);
80 } else {
81 return descriptors->GetValue(descriptor)
82 ->OptimalType(isolate_, representation);
83 }
84 }
85
86 Handle<Map> MapUpdater::ReconfigureToDataField(int descriptor,
87 PropertyAttributes attributes,
88 Representation representation,
89 Handle<FieldType> field_type) {
90 DCHECK_EQ(kInitialized, state_);
91 DCHECK_LE(0, descriptor);
92 DCHECK(!old_map_->is_dictionary_map());
93 modified_descriptor_ = descriptor;
94 new_kind_ = kData;
95 new_attributes_ = attributes;
96 new_location_ = kField;
97 new_representation_ = representation;
98 new_field_type_ = field_type;
99
100 PropertyDetails old_details =
101 old_descriptors_->GetDetails(modified_descriptor_);
102
103 // If property kind is not reconfigured merge the result with
104 // representation/field type from the old descriptor.
105 if (old_details.kind() == new_kind_) {
106 Representation old_representation = old_details.representation();
107 new_representation_ = new_representation_.generalize(old_representation);
108
109 Handle<FieldType> old_field_type =
110 GetOrComputeFieldType(old_descriptors_, modified_descriptor_,
111 old_details.location(), new_representation_);
112
113 new_field_type_ = Map::GeneralizeFieldType(
114 old_representation, old_field_type, new_representation_,
115 new_field_type_, isolate_);
116 }
117
118 if (TryRecofigureToDataFieldInplace() == kEnd) return result_map_;
119 if (FindRootMap() == kEnd) return result_map_;
120 if (FindTargetMap() == kEnd) return result_map_;
121 ConstructNewMap();
122 DCHECK_EQ(kEnd, state_);
123 return result_map_;
124 }
125
126 Handle<Map> MapUpdater::ReconfigureElementsKind(ElementsKind elements_kind) {
127 DCHECK_EQ(kInitialized, state_);
128 new_elements_kind_ = elements_kind;
129
130 if (FindRootMap() == kEnd) return result_map_;
131 if (FindTargetMap() == kEnd) return result_map_;
132 ConstructNewMap();
133 DCHECK_EQ(kEnd, state_);
134 return result_map_;
135 }
136
137 Handle<Map> MapUpdater::Update() {
138 DCHECK_EQ(kInitialized, state_);
139 DCHECK(old_map_->is_deprecated());
140
141 if (FindRootMap() == kEnd) return result_map_;
142 if (FindTargetMap() == kEnd) return result_map_;
143 ConstructNewMap();
144 DCHECK_EQ(kEnd, state_);
145 return result_map_;
146 }
147
148 MapUpdater::State MapUpdater::CopyGeneralizeAllRepresentations(
149 const char* reason) {
150 StoreMode store_mode =
151 modified_descriptor_ >= 0 ? FORCE_FIELD : ALLOW_IN_DESCRIPTOR;
152 result_map_ = Map::CopyGeneralizeAllRepresentations(
153 old_map_, new_elements_kind_, modified_descriptor_, store_mode, new_kind_,
154 new_attributes_, reason);
155 state_ = kEnd;
156 return state_; // Done.
157 }
158
159 MapUpdater::State MapUpdater::TryRecofigureToDataFieldInplace() {
160 // If it's just a representation generalization case (i.e. property kind and
161 // attributes stays unchanged) it's fine to transition from None to anything
162 // but double without any modification to the object, because the default
163 // uninitialized value for representation None can be overwritten by both
164 // smi and tagged values. Doubles, however, would require a box allocation.
165 if (new_representation_.IsNone() || new_representation_.IsDouble()) {
166 return state_; // Not done yet.
167 }
168
169 PropertyDetails old_details =
170 old_descriptors_->GetDetails(modified_descriptor_);
171 Representation old_representation = old_details.representation();
172 if (!old_representation.IsNone()) {
173 return state_; // Not done yet.
174 }
175
176 DCHECK_EQ(new_kind_, old_details.kind());
177 DCHECK_EQ(new_attributes_, old_details.attributes());
178 DCHECK_EQ(kField, old_details.location());
179 if (FLAG_trace_generalization) {
180 old_map_->PrintGeneralization(
181 stdout, "uninitialized field", modified_descriptor_, old_nof_, old_nof_,
182 false, old_representation, new_representation_,
183 handle(old_descriptors_->GetFieldType(modified_descriptor_), isolate_),
184 MaybeHandle<Object>(), new_field_type_, MaybeHandle<Object>());
185 }
186 Handle<Map> field_owner(old_map_->FindFieldOwner(modified_descriptor_),
187 isolate_);
188
189 Map::GeneralizeField(field_owner, modified_descriptor_, new_representation_,
190 new_field_type_);
191 // Check that the descriptor array was updated.
192 DCHECK(old_descriptors_->GetDetails(modified_descriptor_)
193 .representation()
194 .Equals(new_representation_));
195 DCHECK(old_descriptors_->GetFieldType(modified_descriptor_)
196 ->NowIs(new_field_type_));
197
198 result_map_ = old_map_;
199 state_ = kEnd;
200 return state_; // Done.
201 }
202
203 MapUpdater::State MapUpdater::FindRootMap() {
204 DCHECK_EQ(kInitialized, state_);
205 // Check the state of the root map.
206 root_map_ = handle(old_map_->FindRootMap(), isolate_);
207 int root_nof = root_map_->NumberOfOwnDescriptors();
208 if (!old_map_->EquivalentToForTransition(*root_map_)) {
209 return CopyGeneralizeAllRepresentations("GenAll_NotEquivalent");
210 }
211
212 ElementsKind from_kind = root_map_->elements_kind();
213 ElementsKind to_kind = new_elements_kind_;
214 // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
215 if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
216 to_kind != SLOW_STRING_WRAPPER_ELEMENTS &&
217 to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
218 !(IsTransitionableFastElementsKind(from_kind) &&
219 IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
220 return CopyGeneralizeAllRepresentations("GenAll_InvalidElementsTransition");
221 }
222
223 if (modified_descriptor_ >= 0 && modified_descriptor_ < root_nof) {
224 PropertyDetails old_details =
225 old_descriptors_->GetDetails(modified_descriptor_);
226 if (old_details.kind() != new_kind_ ||
227 old_details.attributes() != new_attributes_) {
228 return CopyGeneralizeAllRepresentations("GenAll_RootModification1");
229 }
230 if (!new_representation_.fits_into(old_details.representation())) {
231 return CopyGeneralizeAllRepresentations("GenAll_RootModification2");
232 }
233 if (old_details.location() != kField) {
234 return CopyGeneralizeAllRepresentations("GenAll_RootModification3");
235 }
236 DCHECK_EQ(kData, old_details.kind());
237 DCHECK_EQ(kData, new_kind_);
238 DCHECK_EQ(kField, new_location_);
239 FieldType* old_field_type =
240 old_descriptors_->GetFieldType(modified_descriptor_);
241 if (!new_field_type_->NowIs(old_field_type)) {
242 return CopyGeneralizeAllRepresentations("GenAll_RootModification4");
243 }
244 }
245
246 // From here on, use the map with correct elements kind as root map.
247 if (from_kind != to_kind) {
248 root_map_ = Map::AsElementsKind(root_map_, to_kind);
249 }
250 state_ = kAtRootMap;
251 return state_; // Not done yet.
252 }
253
254 MapUpdater::State MapUpdater::FindTargetMap() {
255 DCHECK_EQ(kAtRootMap, state_);
256 target_map_ = root_map_;
257
258 int root_nof = root_map_->NumberOfOwnDescriptors();
259 for (int i = root_nof; i < old_nof_; ++i) {
260 PropertyDetails old_details = GetDetails(i);
261 Map* transition = TransitionArray::SearchTransition(
262 *target_map_, old_details.kind(), GetKey(i), old_details.attributes());
263 if (transition == NULL) break;
264 Handle<Map> tmp_map(transition, isolate_);
265
266 Handle<DescriptorArray> tmp_descriptors(tmp_map->instance_descriptors(),
267 isolate_);
268
269 // Check if target map is incompatible.
270 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
271 DCHECK_EQ(old_details.kind(), tmp_details.kind());
272 DCHECK_EQ(old_details.attributes(), tmp_details.attributes());
273 if (old_details.kind() == kAccessor &&
274 !EqualImmutableValues(GetValue(i), tmp_descriptors->GetValue(i))) {
275 // TODO(ishell): mutable accessors are not implemented yet.
276 return CopyGeneralizeAllRepresentations("GenAll_Incompatible");
277 }
278 // Check if old location fits into tmp location.
279 if (old_details.location() == kField &&
280 tmp_details.location() == kDescriptor) {
281 break;
282 }
283
284 // Check if old representation fits into tmp representation.
285 Representation tmp_representation = tmp_details.representation();
286 if (!old_details.representation().fits_into(tmp_representation)) {
287 break;
288 }
289
290 if (tmp_details.location() == kField) {
291 Handle<FieldType> old_field_type =
292 GetOrComputeFieldType(i, old_details.location(), tmp_representation);
293 Map::GeneralizeField(tmp_map, i, tmp_representation, old_field_type);
294 } else {
295 // kDescriptor: Check that the value matches.
296 if (!EqualImmutableValues(GetValue(i), tmp_descriptors->GetValue(i))) {
297 break;
298 }
299 }
300 DCHECK(!tmp_map->is_deprecated());
301 target_map_ = tmp_map;
302 }
303
304 // Directly change the map if the target map is more general.
305 int target_nof = target_map_->NumberOfOwnDescriptors();
306 if (target_nof == old_nof_) {
307 #ifdef DEBUG
308 if (modified_descriptor_ >= 0) {
309 DescriptorArray* target_descriptors = target_map_->instance_descriptors();
310 PropertyDetails details =
311 target_descriptors->GetDetails(modified_descriptor_);
312 DCHECK_EQ(new_kind_, details.kind());
313 DCHECK_EQ(new_attributes_, details.attributes());
314 DCHECK_EQ(new_location_, details.location());
315 DCHECK(new_representation_.fits_into(details.representation()));
316 if (new_location_ == kField) {
317 DCHECK_EQ(kField, details.location());
318 DCHECK(new_field_type_->NowIs(
319 target_descriptors->GetFieldType(modified_descriptor_)));
320 } else {
321 DCHECK(details.location() == kField ||
322 EqualImmutableValues(*new_value_, target_descriptors->GetValue(
323 modified_descriptor_)));
324 }
325 }
326 #endif
327 if (*target_map_ != *old_map_) {
328 old_map_->NotifyLeafMapLayoutChange();
329 }
330 result_map_ = target_map_;
331 state_ = kEnd;
332 return state_; // Done.
333 }
334
335 // Find the last compatible target map in the transition tree.
336 for (int i = target_nof; i < old_nof_; ++i) {
337 PropertyDetails old_details = GetDetails(i);
338 Map* transition = TransitionArray::SearchTransition(
339 *target_map_, old_details.kind(), GetKey(i), old_details.attributes());
340 if (transition == NULL) break;
341 Handle<Map> tmp_map(transition, isolate_);
342 Handle<DescriptorArray> tmp_descriptors(tmp_map->instance_descriptors(),
343 isolate_);
344
345 #ifdef DEBUG
346 // Check that target map is compatible.
347 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
348 DCHECK_EQ(old_details.kind(), tmp_details.kind());
349 DCHECK_EQ(old_details.attributes(), tmp_details.attributes());
350 #endif
351 if (old_details.kind() == kAccessor &&
352 !EqualImmutableValues(GetValue(i), tmp_descriptors->GetValue(i))) {
353 return CopyGeneralizeAllRepresentations("GenAll_Incompatible");
354 }
355 DCHECK(!tmp_map->is_deprecated());
356 target_map_ = tmp_map;
357 }
358
359 state_ = kAtTargetMap;
360 return state_; // Not done yet.
361 }
362
363 Handle<DescriptorArray> MapUpdater::BuildDescriptorArray() {
364 int target_nof = target_map_->NumberOfOwnDescriptors();
365 Handle<DescriptorArray> target_descriptors(
366 target_map_->instance_descriptors(), isolate_);
367
368 // Allocate a new descriptor array large enough to hold the required
369 // descriptors, with minimally the exact same size as the old descriptor
370 // array.
371 int new_slack =
372 Max(old_nof_, old_descriptors_->number_of_descriptors()) - old_nof_;
373 Handle<DescriptorArray> new_descriptors =
374 DescriptorArray::Allocate(isolate_, old_nof_, new_slack);
375 DCHECK(new_descriptors->length() > target_descriptors->length() ||
376 new_descriptors->NumberOfSlackDescriptors() > 0 ||
377 new_descriptors->number_of_descriptors() ==
378 old_descriptors_->number_of_descriptors());
379 DCHECK(new_descriptors->number_of_descriptors() == old_nof_);
380
381 int root_nof = root_map_->NumberOfOwnDescriptors();
382
383 // Given that we passed root modification check in FindRootMap() so
384 // the root descriptors are either not modified at all or already more
385 // general than we requested. Take |root_nof| entries as is.
386 // 0 -> |root_nof|
387 int current_offset = 0;
388 for (int i = 0; i < root_nof; ++i) {
389 PropertyDetails old_details = old_descriptors_->GetDetails(i);
390 if (old_details.location() == kField) {
391 current_offset += old_details.field_width_in_words();
392 }
393 Descriptor d(handle(GetKey(i), isolate_),
394 handle(old_descriptors_->GetValue(i), isolate_), old_details);
395 new_descriptors->Set(i, &d);
396 }
397
398 // Merge "updated" old_descriptor entries with target_descriptor entries.
399 // |root_nof| -> |target_nof|
400 for (int i = root_nof; i < target_nof; ++i) {
401 Handle<Name> key(GetKey(i), isolate_);
402 PropertyDetails old_details = GetDetails(i);
403 PropertyDetails target_details = target_descriptors->GetDetails(i);
404
405 PropertyKind next_kind = old_details.kind();
406 PropertyAttributes next_attributes = old_details.attributes();
407 PropertyLocation next_location =
408 old_details.location() == kField ||
409 target_details.location() == kField ||
410 !EqualImmutableValues(target_descriptors->GetValue(i),
411 GetValue(i))
412 ? kField
413 : kDescriptor;
414
415 Representation next_representation =
416 old_details.representation().generalize(
417 target_details.representation());
418
419 DCHECK_EQ(next_kind, target_details.kind());
420 DCHECK_EQ(next_attributes, target_details.attributes());
421
422 if (next_location == kField) {
423 Handle<FieldType> old_field_type =
424 GetOrComputeFieldType(i, old_details.location(), next_representation);
425
426 Handle<FieldType> target_field_type =
427 GetOrComputeFieldType(target_descriptors, i,
428 target_details.location(), next_representation);
429
430 Handle<FieldType> next_field_type = Map::GeneralizeFieldType(
431 old_details.representation(), old_field_type, next_representation,
432 target_field_type, isolate_);
433
434 Handle<Object> wrapped_type(Map::WrapType(next_field_type));
435 Descriptor d;
436 if (next_kind == kData) {
437 d = Descriptor::DataField(key, current_offset, wrapped_type,
438 next_attributes, next_representation);
439 } else {
440 // TODO(ishell): mutable accessors are not implemented yet.
441 UNIMPLEMENTED();
442 }
443 current_offset += d.GetDetails().field_width_in_words();
444 new_descriptors->Set(i, &d);
445 } else {
446 DCHECK_EQ(kDescriptor, next_location);
447
448 Handle<Object> value(GetValue(i), isolate_);
449 Descriptor d;
450 if (next_kind == kData) {
451 d = Descriptor::DataConstant(key, value, next_attributes);
452 } else {
453 DCHECK_EQ(kAccessor, next_kind);
454 d = Descriptor::AccessorConstant(key, value, next_attributes);
455 }
456 new_descriptors->Set(i, &d);
457 }
458 }
459
460 // Take "updated" old_descriptor entries.
461 // |target_nof| -> |old_nof|
462 for (int i = target_nof; i < old_nof_; ++i) {
463 PropertyDetails old_details = GetDetails(i);
464 Handle<Name> key(GetKey(i), isolate_);
465
466 PropertyKind next_kind = old_details.kind();
467 PropertyAttributes next_attributes = old_details.attributes();
468 PropertyLocation next_location = old_details.location();
469 Representation next_representation = old_details.representation();
470
471 Descriptor d;
472 if (next_location == kField) {
473 Handle<FieldType> old_field_type =
474 GetOrComputeFieldType(i, old_details.location(), next_representation);
475
476 Handle<Object> wrapped_type(Map::WrapType(old_field_type));
477 Descriptor d;
478 if (next_kind == kData) {
479 d = Descriptor::DataField(key, current_offset, wrapped_type,
480 next_attributes, next_representation);
481 } else {
482 // TODO(ishell): mutable accessors are not implemented yet.
483 UNIMPLEMENTED();
484 }
485 current_offset += d.GetDetails().field_width_in_words();
486 new_descriptors->Set(i, &d);
487 } else {
488 DCHECK_EQ(kDescriptor, next_location);
489
490 Handle<Object> value(GetValue(i), isolate_);
491 if (next_kind == kData) {
492 d = Descriptor::DataConstant(key, value, next_attributes);
493 } else {
494 DCHECK_EQ(kAccessor, next_kind);
495 d = Descriptor::AccessorConstant(key, value, next_attributes);
496 }
497 new_descriptors->Set(i, &d);
498 }
499 }
500
501 new_descriptors->Sort();
502 return new_descriptors;
503 }
504
505 Handle<Map> MapUpdater::FindSplitMap(Handle<DescriptorArray> descriptors) {
506 DisallowHeapAllocation no_allocation;
507
508 int root_nof = root_map_->NumberOfOwnDescriptors();
509 Map* current = *root_map_;
510 for (int i = root_nof; i < old_nof_; i++) {
511 Name* name = descriptors->GetKey(i);
512 PropertyDetails details = descriptors->GetDetails(i);
513 Map* next = TransitionArray::SearchTransition(current, details.kind(), name,
514 details.attributes());
515 if (next == NULL) break;
516 DescriptorArray* next_descriptors = next->instance_descriptors();
517
518 PropertyDetails next_details = next_descriptors->GetDetails(i);
519 DCHECK_EQ(details.kind(), next_details.kind());
520 DCHECK_EQ(details.attributes(), next_details.attributes());
521 if (details.location() != next_details.location()) break;
522 if (!details.representation().Equals(next_details.representation())) break;
523
524 if (next_details.location() == kField) {
525 FieldType* next_field_type = next_descriptors->GetFieldType(i);
526 if (!descriptors->GetFieldType(i)->NowIs(next_field_type)) {
527 break;
528 }
529 } else {
530 if (!EqualImmutableValues(descriptors->GetValue(i),
531 next_descriptors->GetValue(i))) {
532 break;
533 }
534 }
535 current = next;
536 }
537 return handle(current, isolate_);
538 }
539
540 MapUpdater::State MapUpdater::ConstructNewMap() {
541 Handle<DescriptorArray> new_descriptors = BuildDescriptorArray();
542
543 Handle<Map> split_map = FindSplitMap(new_descriptors);
544 int split_nof = split_map->NumberOfOwnDescriptors();
545 DCHECK_NE(old_nof_, split_nof);
546
547 PropertyDetails split_details = GetDetails(split_nof);
548
549 // Invalidate a transition target at |key|.
550 Map* maybe_transition = TransitionArray::SearchTransition(
551 *split_map, split_details.kind(), GetKey(split_nof),
552 split_details.attributes());
553 if (maybe_transition != NULL) {
554 maybe_transition->DeprecateTransitionTree();
555 }
556
557 // If |maybe_transition| is not NULL then the transition array already
558 // contains entry for given descriptor. This means that the transition
559 // could be inserted regardless of whether transitions array is full or not.
560 if (maybe_transition == NULL &&
561 !TransitionArray::CanHaveMoreTransitions(split_map)) {
562 return CopyGeneralizeAllRepresentations("GenAll_CantHaveMoreTransitions");
563 }
564
565 old_map_->NotifyLeafMapLayoutChange();
566
567 if (FLAG_trace_generalization && modified_descriptor_ >= 0) {
568 PropertyDetails old_details =
569 old_descriptors_->GetDetails(modified_descriptor_);
570 PropertyDetails new_details =
571 new_descriptors->GetDetails(modified_descriptor_);
572 MaybeHandle<FieldType> old_field_type;
573 MaybeHandle<FieldType> new_field_type;
574 MaybeHandle<Object> old_value;
575 MaybeHandle<Object> new_value;
576 if (old_details.type() == DATA) {
577 old_field_type = handle(
578 old_descriptors_->GetFieldType(modified_descriptor_), isolate_);
579 } else {
580 old_value =
581 handle(old_descriptors_->GetValue(modified_descriptor_), isolate_);
582 }
583 if (new_details.type() == DATA) {
584 new_field_type =
585 handle(new_descriptors->GetFieldType(modified_descriptor_), isolate_);
586 } else {
587 new_value =
588 handle(new_descriptors->GetValue(modified_descriptor_), isolate_);
589 }
590
591 old_map_->PrintGeneralization(
592 stdout, "", modified_descriptor_, split_nof, old_nof_,
593 old_details.location() == kDescriptor && new_location_ == kField,
594 old_details.representation(), new_details.representation(),
595 old_field_type, old_value, new_field_type, new_value);
596 }
597
598 Handle<LayoutDescriptor> new_layout_descriptor =
599 LayoutDescriptor::New(split_map, new_descriptors, old_nof_);
600
601 Handle<Map> new_map = Map::AddMissingTransitions(split_map, new_descriptors,
602 new_layout_descriptor);
603
604 // Deprecated part of the transition tree is no longer reachable, so replace
605 // current instance descriptors in the "survived" part of the tree with
606 // the new descriptors to maintain descriptors sharing invariant.
607 split_map->ReplaceDescriptors(*new_descriptors, *new_layout_descriptor);
608
609 result_map_ = new_map;
610 state_ = kEnd;
611 return state_; // Done.
612 }
613
614 } // namespace internal
615 } // namespace v8
OLDNEW
« no previous file with comments | « src/map-updater.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698