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

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

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

Powered by Google App Engine
This is Rietveld 408576698