Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <iomanip> | 5 #include <iomanip> |
| 6 #include <sstream> | 6 #include <sstream> |
| 7 | 7 |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 | 9 |
| 10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
| (...skipping 12431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12442 context->set(context_index, *value); | 12442 context->set(context_index, *value); |
| 12443 // For elements that are still writable we keep slow aliasing. | 12443 // For elements that are still writable we keep slow aliasing. |
| 12444 if (!details.IsReadOnly()) value = element; | 12444 if (!details.IsReadOnly()) value = element; |
| 12445 } | 12445 } |
| 12446 } | 12446 } |
| 12447 | 12447 |
| 12448 dictionary->ValueAtPut(entry, *value); | 12448 dictionary->ValueAtPut(entry, *value); |
| 12449 } | 12449 } |
| 12450 | 12450 |
| 12451 | 12451 |
| 12452 static bool ShouldConvertToFastElements(SeededNumberDictionary* dictionary, | |
| 12453 uint32_t array_size) { | |
| 12454 // If properties with non-standard attributes or accessors were added, we | |
| 12455 // cannot go back to fast elements. | |
| 12456 if (dictionary->requires_slow_elements()) return false; | |
| 12457 uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) * | |
| 12458 SeededNumberDictionary::kEntrySize; | |
| 12459 return 2 * dictionary_size >= array_size; | |
| 12460 } | |
| 12461 | |
| 12462 | |
| 12452 void JSObject::AddDictionaryElement(Handle<JSObject> object, uint32_t index, | 12463 void JSObject::AddDictionaryElement(Handle<JSObject> object, uint32_t index, |
| 12453 Handle<Object> value, | 12464 Handle<Object> value, |
| 12454 PropertyAttributes attributes) { | 12465 PropertyAttributes attributes) { |
| 12455 // TODO(verwaest): Handle with the elements accessor. | 12466 // TODO(verwaest): Handle with the elements accessor. |
| 12456 Isolate* isolate = object->GetIsolate(); | |
| 12457 | |
| 12458 // Insert element in the dictionary. | 12467 // Insert element in the dictionary. |
| 12459 Handle<FixedArray> elements(FixedArray::cast(object->elements())); | |
| 12460 bool is_arguments = | |
| 12461 (elements->map() == isolate->heap()->sloppy_arguments_elements_map()); | |
| 12462 | |
| 12463 DCHECK(object->HasDictionaryElements() || | 12468 DCHECK(object->HasDictionaryElements() || |
| 12464 object->HasDictionaryArgumentsElements()); | 12469 object->HasDictionaryArgumentsElements()); |
| 12470 DCHECK(object->map()->is_extensible()); | |
| 12465 | 12471 |
| 12472 Handle<FixedArray> elements(FixedArray::cast(object->elements())); | |
| 12473 bool is_arguments = object->HasSloppyArgumentsElements(); | |
| 12466 Handle<SeededNumberDictionary> dictionary( | 12474 Handle<SeededNumberDictionary> dictionary( |
| 12467 is_arguments ? SeededNumberDictionary::cast(elements->get(1)) | 12475 is_arguments ? SeededNumberDictionary::cast(elements->get(1)) |
| 12468 : SeededNumberDictionary::cast(*elements)); | 12476 : SeededNumberDictionary::cast(*elements)); |
| 12469 | 12477 |
| 12470 #ifdef DEBUG | 12478 #ifdef DEBUG |
| 12471 int entry = dictionary->FindEntry(index); | 12479 int entry = dictionary->FindEntry(index); |
| 12472 DCHECK_EQ(SeededNumberDictionary::kNotFound, entry); | 12480 DCHECK_EQ(SeededNumberDictionary::kNotFound, entry); |
| 12473 DCHECK(object->map()->is_extensible()); | |
| 12474 #endif | 12481 #endif |
| 12475 | 12482 |
| 12476 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | 12483 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
| 12477 Handle<SeededNumberDictionary> new_dictionary = | 12484 Handle<SeededNumberDictionary> new_dictionary = |
| 12478 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, details); | 12485 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, details); |
| 12486 | |
| 12479 if (*dictionary != *new_dictionary) { | 12487 if (*dictionary != *new_dictionary) { |
| 12480 if (is_arguments) { | 12488 if (is_arguments) { |
| 12481 elements->set(1, *new_dictionary); | 12489 elements->set(1, *new_dictionary); |
| 12482 } else { | 12490 } else { |
| 12483 object->set_elements(*new_dictionary); | 12491 object->set_elements(*new_dictionary); |
| 12484 } | 12492 } |
| 12485 dictionary = new_dictionary; | |
| 12486 } | 12493 } |
| 12487 | 12494 |
| 12488 // Update the array length if this JSObject is an array. | 12495 uint32_t length; |
| 12489 if (object->IsJSArray()) { | 12496 if (object->IsJSArray()) { |
| 12490 JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index, | 12497 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&length)); |
| 12491 value); | 12498 if (index >= length) { |
| 12499 length = index + 1; | |
|
Jakob Kummerow
2015/06/23 12:05:14
Who guarantees that index != kMaxUint32?
Toon Verwaest
2015/06/23 12:28:17
We shouldn't be in the AddDataElement path altoget
| |
| 12500 Isolate* isolate = object->GetIsolate(); | |
| 12501 Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length); | |
| 12502 JSArray::cast(*object)->set_length(*length_obj); | |
| 12503 } | |
| 12504 } else if (!new_dictionary->requires_slow_elements()) { | |
| 12505 length = new_dictionary->max_number_key() + 1; | |
| 12492 } | 12506 } |
| 12493 | 12507 |
| 12494 // Attempt to put this object back in fast case. | 12508 // Attempt to put this object back in fast case. |
| 12495 if (object->ShouldConvertToFastElements()) { | 12509 if (object->HasDenseElements() && |
| 12496 uint32_t new_length = 0; | 12510 ShouldConvertToFastElements(*new_dictionary, length)) { |
| 12497 if (object->IsJSArray()) { | |
| 12498 CHECK(JSArray::cast(*object)->length()->ToArrayLength(&new_length)); | |
| 12499 } else { | |
| 12500 new_length = dictionary->max_number_key() + 1; | |
| 12501 } | |
| 12502 ElementsKind to_kind = object->BestFittingFastElementsKind(); | 12511 ElementsKind to_kind = object->BestFittingFastElementsKind(); |
| 12503 ElementsAccessor* accessor = ElementsAccessor::ForKind(to_kind); | 12512 ElementsAccessor* accessor = ElementsAccessor::ForKind(to_kind); |
| 12504 accessor->GrowCapacityAndConvert(object, new_length); | 12513 accessor->GrowCapacityAndConvert(object, length); |
| 12505 #ifdef DEBUG | 12514 #ifdef DEBUG |
| 12506 if (FLAG_trace_normalization) { | 12515 if (FLAG_trace_normalization) { |
| 12507 OFStream os(stdout); | 12516 OFStream os(stdout); |
| 12508 os << "Object elements are fast case again:\n"; | 12517 os << "Object elements are fast case again:\n"; |
| 12509 object->Print(os); | 12518 object->Print(os); |
| 12510 } | 12519 } |
| 12511 #endif | 12520 #endif |
| 12512 } | 12521 } |
| 12513 } | 12522 } |
| 12514 | 12523 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12569 | 12578 |
| 12570 Isolate* isolate = object->GetIsolate(); | 12579 Isolate* isolate = object->GetIsolate(); |
| 12571 | 12580 |
| 12572 // TODO(verwaest): Use ElementAccessor. | 12581 // TODO(verwaest): Use ElementAccessor. |
| 12573 Handle<Object> old_length_handle; | 12582 Handle<Object> old_length_handle; |
| 12574 if (object->IsJSArray() && object->map()->is_observed()) { | 12583 if (object->IsJSArray() && object->map()->is_observed()) { |
| 12575 old_length_handle = handle(JSArray::cast(*object)->length(), isolate); | 12584 old_length_handle = handle(JSArray::cast(*object)->length(), isolate); |
| 12576 } | 12585 } |
| 12577 | 12586 |
| 12578 ElementsKind kind = object->GetElementsKind(); | 12587 ElementsKind kind = object->GetElementsKind(); |
| 12579 bool handle_slow = false; | 12588 bool handle_slow = IsDictionaryElementsKind(kind); |
| 12580 uint32_t capacity = 0; | 12589 uint32_t capacity = 0; |
| 12581 uint32_t new_capacity = 0; | 12590 uint32_t new_capacity = 0; |
| 12582 if (IsFastElementsKind(kind) || object->HasFastArgumentsElements()) { | 12591 if (attributes != NONE) { |
| 12583 if (attributes != NONE) { | 12592 // TODO(verwaest): Move set_requires_slow_elements into NormalizeElements. |
| 12584 // TODO(verwaest): Move set_requires_slow_elements into NormalizeElements. | 12593 NormalizeElements(object)->set_requires_slow_elements(); |
| 12585 NormalizeElements(object)->set_requires_slow_elements(); | 12594 handle_slow = true; |
| 12595 } else if (IsSloppyArgumentsElements(kind)) { | |
| 12596 FixedArray* parameter_map = FixedArray::cast(object->elements()); | |
| 12597 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | |
| 12598 if (arguments->IsDictionary()) { | |
| 12586 handle_slow = true; | 12599 handle_slow = true; |
| 12587 } else { | 12600 } else { |
| 12588 if (IsSloppyArgumentsElements(kind)) { | 12601 capacity = static_cast<uint32_t>(arguments->length()); |
| 12589 FixedArray* parameter_map = FixedArray::cast(object->elements()); | 12602 handle_slow = |
| 12590 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 12603 object->ShouldConvertToSlowElements(capacity, index, &new_capacity); |
| 12591 capacity = static_cast<uint32_t>(arguments->length()); | 12604 if (handle_slow) NormalizeElements(object); |
| 12592 } else { | |
| 12593 if (IsFastSmiOrObjectElementsKind(kind)) { | |
| 12594 EnsureWritableFastElements(object); | |
| 12595 } | |
| 12596 capacity = static_cast<uint32_t>(object->elements()->length()); | |
| 12597 } | |
| 12598 | |
| 12599 new_capacity = capacity; | |
| 12600 // Check if the capacity of the backing store needs to be increased, or if | |
| 12601 // a transition to slow elements is necessary. | |
| 12602 if (index >= capacity) { | |
| 12603 handle_slow = true; | |
| 12604 if ((index - capacity) < kMaxGap) { | |
| 12605 new_capacity = NewElementsCapacity(index + 1); | |
| 12606 DCHECK_LT(index, new_capacity); | |
| 12607 handle_slow = object->ShouldConvertToSlowElements(new_capacity); | |
| 12608 } | |
| 12609 if (handle_slow) NormalizeElements(object); | |
| 12610 } | |
| 12611 } | 12605 } |
| 12612 } else { | 12606 } else if (!handle_slow) { |
| 12613 handle_slow = true; | 12607 if (IsFastSmiOrObjectElementsKind(kind)) EnsureWritableFastElements(object); |
|
Jakob Kummerow
2015/06/23 12:05:14
Isn't it unnecessary to do this if we'll decide to
Toon Verwaest
2015/06/23 12:28:17
Done.
| |
| 12608 capacity = static_cast<uint32_t>(object->elements()->length()); | |
| 12609 handle_slow = | |
| 12610 object->ShouldConvertToSlowElements(capacity, index, &new_capacity); | |
| 12611 if (handle_slow) NormalizeElements(object); | |
| 12614 } | 12612 } |
| 12615 | 12613 |
| 12616 if (handle_slow) { | 12614 if (handle_slow) { |
| 12617 DCHECK(object->HasDictionaryElements() || | 12615 DCHECK(object->HasDictionaryElements() || |
| 12618 object->HasDictionaryArgumentsElements()); | 12616 object->HasDictionaryArgumentsElements()); |
| 12619 AddDictionaryElement(object, index, value, attributes); | 12617 AddDictionaryElement(object, index, value, attributes); |
| 12620 } else { | 12618 } else { |
| 12621 AddFastElement(object, index, value, kind, capacity, new_capacity); | 12619 AddFastElement(object, index, value, kind, capacity, new_capacity); |
| 12622 } | 12620 } |
| 12623 | 12621 |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12823 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { | 12821 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { |
| 12824 return false; | 12822 return false; |
| 12825 } | 12823 } |
| 12826 | 12824 |
| 12827 // Transitions from HOLEY -> PACKED are not allowed. | 12825 // Transitions from HOLEY -> PACKED are not allowed. |
| 12828 return !IsFastHoleyElementsKind(from_kind) || | 12826 return !IsFastHoleyElementsKind(from_kind) || |
| 12829 IsFastHoleyElementsKind(to_kind); | 12827 IsFastHoleyElementsKind(to_kind); |
| 12830 } | 12828 } |
| 12831 | 12829 |
| 12832 | 12830 |
| 12833 void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array, | |
| 12834 uint32_t index, | |
| 12835 Handle<Object> value) { | |
| 12836 uint32_t old_len = 0; | |
| 12837 CHECK(array->length()->ToArrayLength(&old_len)); | |
| 12838 // Check to see if we need to update the length. For now, we make | |
| 12839 // sure that the length stays within 32-bits (unsigned). | |
| 12840 if (index >= old_len && index != 0xffffffff) { | |
| 12841 Handle<Object> len = array->GetIsolate()->factory()->NewNumber( | |
| 12842 static_cast<double>(index) + 1); | |
| 12843 array->set_length(*len); | |
| 12844 } | |
| 12845 } | |
| 12846 | |
| 12847 | |
| 12848 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) { | 12831 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) { |
| 12849 LookupIterator it(array, array->GetIsolate()->factory()->length_string(), | 12832 LookupIterator it(array, array->GetIsolate()->factory()->length_string(), |
| 12850 LookupIterator::OWN_SKIP_INTERCEPTOR); | 12833 LookupIterator::OWN_SKIP_INTERCEPTOR); |
| 12851 CHECK_NE(LookupIterator::ACCESS_CHECK, it.state()); | 12834 CHECK_NE(LookupIterator::ACCESS_CHECK, it.state()); |
| 12852 CHECK(it.IsFound()); | 12835 CHECK(it.IsFound()); |
| 12853 CHECK_EQ(LookupIterator::ACCESSOR, it.state()); | 12836 CHECK_EQ(LookupIterator::ACCESSOR, it.state()); |
| 12854 return it.IsReadOnly(); | 12837 return it.IsReadOnly(); |
| 12855 } | 12838 } |
| 12856 | 12839 |
| 12857 | 12840 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12954 break; | 12937 break; |
| 12955 } | 12938 } |
| 12956 } | 12939 } |
| 12957 } | 12940 } |
| 12958 | 12941 |
| 12959 | 12942 |
| 12960 bool JSObject::WouldConvertToSlowElements(uint32_t index) { | 12943 bool JSObject::WouldConvertToSlowElements(uint32_t index) { |
| 12961 if (HasFastElements()) { | 12944 if (HasFastElements()) { |
| 12962 Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements())); | 12945 Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements())); |
| 12963 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); | 12946 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); |
| 12964 if (index >= capacity) { | 12947 uint32_t new_capacity; |
| 12965 if ((index - capacity) >= kMaxGap) return true; | 12948 return ShouldConvertToSlowElements(capacity, index, &new_capacity); |
| 12966 uint32_t new_capacity = NewElementsCapacity(index + 1); | |
| 12967 return ShouldConvertToSlowElements(new_capacity); | |
| 12968 } | |
| 12969 } | 12949 } |
| 12970 return false; | 12950 return false; |
| 12971 } | 12951 } |
| 12972 | 12952 |
| 12973 | 12953 |
| 12974 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { | 12954 bool JSObject::ShouldConvertToSlowElements(uint32_t capacity, uint32_t index, |
| 12955 uint32_t* new_capacity) { | |
| 12975 STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <= | 12956 STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <= |
| 12976 kMaxUncheckedFastElementsLength); | 12957 kMaxUncheckedFastElementsLength); |
| 12977 if (new_capacity <= kMaxUncheckedOldFastElementsLength || | 12958 if (index < capacity) { |
| 12978 (new_capacity <= kMaxUncheckedFastElementsLength && | 12959 *new_capacity = capacity; |
| 12960 return false; | |
| 12961 } | |
| 12962 if (index - capacity >= kMaxGap) return true; | |
| 12963 *new_capacity = NewElementsCapacity(index + 1); | |
| 12964 DCHECK_LT(index, *new_capacity); | |
| 12965 if (*new_capacity <= kMaxUncheckedOldFastElementsLength || | |
| 12966 (*new_capacity <= kMaxUncheckedFastElementsLength && | |
| 12979 GetHeap()->InNewSpace(this))) { | 12967 GetHeap()->InNewSpace(this))) { |
| 12980 return false; | 12968 return false; |
| 12981 } | 12969 } |
| 12982 // If the fast-case backing storage takes up roughly three times as | 12970 // If the fast-case backing storage takes up roughly three times as |
| 12983 // much space (in machine words) as a dictionary backing storage | 12971 // much space (in machine words) as a dictionary backing storage |
| 12984 // would, the object should have slow elements. | 12972 // would, the object should have slow elements. |
| 12985 int old_capacity = 0; | 12973 int old_capacity = 0; |
| 12986 int used_elements = 0; | 12974 int used_elements = 0; |
| 12987 GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 12975 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
| 12988 int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) * | 12976 int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) * |
| 12989 SeededNumberDictionary::kEntrySize; | 12977 SeededNumberDictionary::kEntrySize; |
| 12990 return 3 * dictionary_size <= new_capacity; | 12978 return 3 * static_cast<uint32_t>(dictionary_size) <= *new_capacity; |
| 12991 } | 12979 } |
| 12992 | 12980 |
| 12993 | 12981 |
| 12994 bool JSObject::ShouldConvertToFastElements() { | |
| 12995 DCHECK(HasDictionaryElements() || HasDictionaryArgumentsElements()); | |
| 12996 // If the elements are sparse, we should not go back to fast case. | |
| 12997 if (!HasDenseElements()) return false; | |
| 12998 // An object requiring access checks is never allowed to have fast | |
| 12999 // elements. If it had fast elements we would skip security checks. | |
| 13000 if (IsAccessCheckNeeded()) return false; | |
| 13001 // Observed objects may not go to fast mode because they rely on map checks, | |
| 13002 // and for fast element accesses we sometimes check element kinds only. | |
| 13003 if (map()->is_observed()) return false; | |
| 13004 | |
| 13005 FixedArray* elements = FixedArray::cast(this->elements()); | |
| 13006 SeededNumberDictionary* dictionary = NULL; | |
| 13007 if (elements->map() == GetHeap()->sloppy_arguments_elements_map()) { | |
| 13008 dictionary = SeededNumberDictionary::cast(elements->get(1)); | |
| 13009 } else { | |
| 13010 dictionary = SeededNumberDictionary::cast(elements); | |
| 13011 } | |
| 13012 // If an element has been added at a very high index in the elements | |
| 13013 // dictionary, we cannot go back to fast case. | |
| 13014 if (dictionary->requires_slow_elements()) return false; | |
| 13015 // If the dictionary backing storage takes up roughly half as much | |
| 13016 // space (in machine words) as a fast-case backing storage would, | |
| 13017 // the object should have fast elements. | |
| 13018 uint32_t array_size = 0; | |
| 13019 if (IsJSArray()) { | |
| 13020 CHECK(JSArray::cast(this)->length()->ToArrayLength(&array_size)); | |
| 13021 } else { | |
| 13022 array_size = dictionary->max_number_key(); | |
| 13023 } | |
| 13024 uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) * | |
| 13025 SeededNumberDictionary::kEntrySize; | |
| 13026 return 2 * dictionary_size >= array_size; | |
| 13027 } | |
| 13028 | |
| 13029 | |
| 13030 ElementsKind JSObject::BestFittingFastElementsKind() { | 12982 ElementsKind JSObject::BestFittingFastElementsKind() { |
| 13031 if (HasSloppyArgumentsElements()) return FAST_HOLEY_ELEMENTS; | 12983 if (HasSloppyArgumentsElements()) return FAST_HOLEY_ELEMENTS; |
| 13032 DCHECK(HasDictionaryElements()); | 12984 DCHECK(HasDictionaryElements()); |
| 13033 SeededNumberDictionary* dictionary = element_dictionary(); | 12985 SeededNumberDictionary* dictionary = element_dictionary(); |
| 13034 ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS; | 12986 ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS; |
| 13035 for (int i = 0; i < dictionary->Capacity(); i++) { | 12987 for (int i = 0; i < dictionary->Capacity(); i++) { |
| 13036 Object* key = dictionary->KeyAt(i); | 12988 Object* key = dictionary->KeyAt(i); |
| 13037 if (key->IsNumber()) { | 12989 if (key->IsNumber()) { |
| 13038 Object* value = dictionary->ValueAt(i); | 12990 Object* value = dictionary->ValueAt(i); |
| 13039 if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS; | 12991 if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS; |
| (...skipping 3323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 16363 Handle<Object> new_value) { | 16315 Handle<Object> new_value) { |
| 16364 if (cell->value() != *new_value) { | 16316 if (cell->value() != *new_value) { |
| 16365 cell->set_value(*new_value); | 16317 cell->set_value(*new_value); |
| 16366 Isolate* isolate = cell->GetIsolate(); | 16318 Isolate* isolate = cell->GetIsolate(); |
| 16367 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16319 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 16368 isolate, DependentCode::kPropertyCellChangedGroup); | 16320 isolate, DependentCode::kPropertyCellChangedGroup); |
| 16369 } | 16321 } |
| 16370 } | 16322 } |
| 16371 } // namespace internal | 16323 } // namespace internal |
| 16372 } // namespace v8 | 16324 } // namespace v8 |
| OLD | NEW |