OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1525 JSValue::cast(this)->value()->ShortPrint(accumulator); | 1525 JSValue::cast(this)->value()->ShortPrint(accumulator); |
1526 } | 1526 } |
1527 accumulator->Put('>'); | 1527 accumulator->Put('>'); |
1528 break; | 1528 break; |
1529 } | 1529 } |
1530 } | 1530 } |
1531 } | 1531 } |
1532 | 1532 |
1533 | 1533 |
1534 void JSObject::PrintElementsTransition( | 1534 void JSObject::PrintElementsTransition( |
1535 FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements, | 1535 FILE* file, Handle<JSObject> object, |
1536 ElementsKind to_kind, FixedArrayBase* to_elements) { | 1536 ElementsKind from_kind, Handle<FixedArrayBase> from_elements, |
| 1537 ElementsKind to_kind, Handle<FixedArrayBase> to_elements) { |
1537 if (from_kind != to_kind) { | 1538 if (from_kind != to_kind) { |
1538 PrintF(file, "elements transition ["); | 1539 PrintF(file, "elements transition ["); |
1539 PrintElementsKind(file, from_kind); | 1540 PrintElementsKind(file, from_kind); |
1540 PrintF(file, " -> "); | 1541 PrintF(file, " -> "); |
1541 PrintElementsKind(file, to_kind); | 1542 PrintElementsKind(file, to_kind); |
1542 PrintF(file, "] in "); | 1543 PrintF(file, "] in "); |
1543 JavaScriptFrame::PrintTop(GetIsolate(), file, false, true); | 1544 JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true); |
1544 PrintF(file, " for "); | 1545 PrintF(file, " for "); |
1545 ShortPrint(file); | 1546 object->ShortPrint(file); |
1546 PrintF(file, " from "); | 1547 PrintF(file, " from "); |
1547 from_elements->ShortPrint(file); | 1548 from_elements->ShortPrint(file); |
1548 PrintF(file, " to "); | 1549 PrintF(file, " to "); |
1549 to_elements->ShortPrint(file); | 1550 to_elements->ShortPrint(file); |
1550 PrintF(file, "\n"); | 1551 PrintF(file, "\n"); |
1551 } | 1552 } |
1552 } | 1553 } |
1553 | 1554 |
1554 | 1555 |
1555 void Map::PrintGeneralization(FILE* file, | 1556 void Map::PrintGeneralization(FILE* file, |
(...skipping 9576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11132 PrintF(out, "\n"); | 11133 PrintF(out, "\n"); |
11133 } | 11134 } |
11134 #endif // ENABLE_DISASSEMBLER | 11135 #endif // ENABLE_DISASSEMBLER |
11135 | 11136 |
11136 | 11137 |
11137 Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength( | 11138 Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength( |
11138 Handle<JSObject> object, | 11139 Handle<JSObject> object, |
11139 int capacity, | 11140 int capacity, |
11140 int length, | 11141 int length, |
11141 SetFastElementsCapacitySmiMode smi_mode) { | 11142 SetFastElementsCapacitySmiMode smi_mode) { |
11142 CALL_HEAP_FUNCTION( | |
11143 object->GetIsolate(), | |
11144 object->SetFastElementsCapacityAndLength(capacity, length, smi_mode), | |
11145 FixedArray); | |
11146 } | |
11147 | |
11148 | |
11149 MaybeObject* JSObject::SetFastElementsCapacityAndLength( | |
11150 int capacity, | |
11151 int length, | |
11152 SetFastElementsCapacitySmiMode smi_mode) { | |
11153 Heap* heap = GetHeap(); | |
11154 // We should never end in here with a pixel or external array. | 11143 // We should never end in here with a pixel or external array. |
11155 ASSERT(!HasExternalArrayElements()); | 11144 ASSERT(!object->HasExternalArrayElements()); |
11156 | 11145 |
11157 // Allocate a new fast elements backing store. | 11146 // Allocate a new fast elements backing store. |
11158 FixedArray* new_elements; | 11147 Handle<FixedArray> new_elements = |
11159 MaybeObject* maybe = heap->AllocateUninitializedFixedArray(capacity); | 11148 object->GetIsolate()->factory()->NewUninitializedFixedArray(capacity); |
11160 if (!maybe->To(&new_elements)) return maybe; | |
11161 | 11149 |
11162 ElementsKind elements_kind = GetElementsKind(); | 11150 ElementsKind elements_kind = object->GetElementsKind(); |
11163 ElementsKind new_elements_kind; | 11151 ElementsKind new_elements_kind; |
11164 // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it, | 11152 // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it, |
11165 // or if it's allowed and the old elements array contained only SMIs. | 11153 // or if it's allowed and the old elements array contained only SMIs. |
11166 bool has_fast_smi_elements = | 11154 bool has_fast_smi_elements = |
11167 (smi_mode == kForceSmiElements) || | 11155 (smi_mode == kForceSmiElements) || |
11168 ((smi_mode == kAllowSmiElements) && HasFastSmiElements()); | 11156 ((smi_mode == kAllowSmiElements) && object->HasFastSmiElements()); |
11169 if (has_fast_smi_elements) { | 11157 if (has_fast_smi_elements) { |
11170 if (IsHoleyElementsKind(elements_kind)) { | 11158 if (IsHoleyElementsKind(elements_kind)) { |
11171 new_elements_kind = FAST_HOLEY_SMI_ELEMENTS; | 11159 new_elements_kind = FAST_HOLEY_SMI_ELEMENTS; |
11172 } else { | 11160 } else { |
11173 new_elements_kind = FAST_SMI_ELEMENTS; | 11161 new_elements_kind = FAST_SMI_ELEMENTS; |
11174 } | 11162 } |
11175 } else { | 11163 } else { |
11176 if (IsHoleyElementsKind(elements_kind)) { | 11164 if (IsHoleyElementsKind(elements_kind)) { |
11177 new_elements_kind = FAST_HOLEY_ELEMENTS; | 11165 new_elements_kind = FAST_HOLEY_ELEMENTS; |
11178 } else { | 11166 } else { |
11179 new_elements_kind = FAST_ELEMENTS; | 11167 new_elements_kind = FAST_ELEMENTS; |
11180 } | 11168 } |
11181 } | 11169 } |
11182 FixedArrayBase* old_elements = elements(); | 11170 Handle<FixedArrayBase> old_elements(object->elements()); |
11183 ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind); | 11171 ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind); |
11184 MaybeObject* maybe_obj = | 11172 accessor->CopyElements(object, new_elements, elements_kind); |
11185 accessor->CopyElements(this, new_elements, elements_kind); | |
11186 if (maybe_obj->IsFailure()) return maybe_obj; | |
11187 | 11173 |
11188 if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) { | 11174 if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) { |
11189 Map* new_map = map(); | 11175 Handle<Map> new_map = (new_elements_kind != elements_kind) |
11190 if (new_elements_kind != elements_kind) { | 11176 ? GetElementsTransitionMap(object, new_elements_kind) |
11191 MaybeObject* maybe = | 11177 : handle(object->map()); |
11192 GetElementsTransitionMap(GetIsolate(), new_elements_kind); | 11178 object->ValidateElements(); |
11193 if (!maybe->To(&new_map)) return maybe; | 11179 object->set_map_and_elements(*new_map, *new_elements); |
11194 } | |
11195 ValidateElements(); | |
11196 set_map_and_elements(new_map, new_elements); | |
11197 | 11180 |
11198 // Transition through the allocation site as well if present. | 11181 // Transition through the allocation site as well if present. |
11199 maybe_obj = UpdateAllocationSite(new_elements_kind); | 11182 JSObject::UpdateAllocationSite(object, new_elements_kind); |
11200 if (maybe_obj->IsFailure()) return maybe_obj; | |
11201 } else { | 11183 } else { |
11202 FixedArray* parameter_map = FixedArray::cast(old_elements); | 11184 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(old_elements); |
11203 parameter_map->set(1, new_elements); | 11185 parameter_map->set(1, *new_elements); |
11204 } | 11186 } |
11205 | 11187 |
11206 if (FLAG_trace_elements_transitions) { | 11188 if (FLAG_trace_elements_transitions) { |
11207 PrintElementsTransition(stdout, elements_kind, old_elements, | 11189 PrintElementsTransition(stdout, object, elements_kind, old_elements, |
11208 GetElementsKind(), new_elements); | 11190 object->GetElementsKind(), new_elements); |
11209 } | 11191 } |
11210 | 11192 |
11211 if (IsJSArray()) { | 11193 if (object->IsJSArray()) { |
11212 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 11194 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length)); |
11213 } | 11195 } |
11214 return new_elements; | 11196 return new_elements; |
11215 } | 11197 } |
11216 | 11198 |
11217 | 11199 |
11218 void JSObject::SetFastDoubleElementsCapacityAndLength(Handle<JSObject> object, | 11200 void JSObject::SetFastDoubleElementsCapacityAndLength(Handle<JSObject> object, |
11219 int capacity, | 11201 int capacity, |
11220 int length) { | 11202 int length) { |
11221 CALL_HEAP_FUNCTION_VOID( | 11203 // We should never end in here with a pixel or external array. |
11222 object->GetIsolate(), | 11204 ASSERT(!object->HasExternalArrayElements()); |
11223 object->SetFastDoubleElementsCapacityAndLength(capacity, length)); | |
11224 } | |
11225 | 11205 |
| 11206 Handle<FixedArrayBase> elems = |
| 11207 object->GetIsolate()->factory()->NewFixedDoubleArray(capacity); |
11226 | 11208 |
11227 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( | 11209 ElementsKind elements_kind = object->GetElementsKind(); |
11228 int capacity, | |
11229 int length) { | |
11230 Heap* heap = GetHeap(); | |
11231 // We should never end in here with a pixel or external array. | |
11232 ASSERT(!HasExternalArrayElements()); | |
11233 | |
11234 FixedArrayBase* elems; | |
11235 { MaybeObject* maybe_obj = | |
11236 heap->AllocateUninitializedFixedDoubleArray(capacity); | |
11237 if (!maybe_obj->To(&elems)) return maybe_obj; | |
11238 } | |
11239 | |
11240 ElementsKind elements_kind = GetElementsKind(); | |
11241 CHECK(elements_kind != SLOPPY_ARGUMENTS_ELEMENTS); | 11210 CHECK(elements_kind != SLOPPY_ARGUMENTS_ELEMENTS); |
11242 ElementsKind new_elements_kind = elements_kind; | 11211 ElementsKind new_elements_kind = elements_kind; |
11243 if (IsHoleyElementsKind(elements_kind)) { | 11212 if (IsHoleyElementsKind(elements_kind)) { |
11244 new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS; | 11213 new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS; |
11245 } else { | 11214 } else { |
11246 new_elements_kind = FAST_DOUBLE_ELEMENTS; | 11215 new_elements_kind = FAST_DOUBLE_ELEMENTS; |
11247 } | 11216 } |
11248 | 11217 |
11249 Map* new_map; | 11218 Handle<Map> new_map = GetElementsTransitionMap(object, new_elements_kind); |
11250 { MaybeObject* maybe_obj = | 11219 |
11251 GetElementsTransitionMap(heap->isolate(), new_elements_kind); | 11220 Handle<FixedArrayBase> old_elements(object->elements()); |
11252 if (!maybe_obj->To(&new_map)) return maybe_obj; | 11221 ElementsAccessor* accessor = ElementsAccessor::ForKind(FAST_DOUBLE_ELEMENTS); |
| 11222 accessor->CopyElements(object, elems, elements_kind); |
| 11223 |
| 11224 object->ValidateElements(); |
| 11225 object->set_map_and_elements(*new_map, *elems); |
| 11226 |
| 11227 if (FLAG_trace_elements_transitions) { |
| 11228 PrintElementsTransition(stdout, object, elements_kind, old_elements, |
| 11229 object->GetElementsKind(), elems); |
11253 } | 11230 } |
11254 | 11231 |
11255 FixedArrayBase* old_elements = elements(); | 11232 if (object->IsJSArray()) { |
11256 ElementsAccessor* accessor = ElementsAccessor::ForKind(FAST_DOUBLE_ELEMENTS); | 11233 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length)); |
11257 { MaybeObject* maybe_obj = | |
11258 accessor->CopyElements(this, elems, elements_kind); | |
11259 if (maybe_obj->IsFailure()) return maybe_obj; | |
11260 } | 11234 } |
11261 | |
11262 ValidateElements(); | |
11263 set_map_and_elements(new_map, elems); | |
11264 | |
11265 if (FLAG_trace_elements_transitions) { | |
11266 PrintElementsTransition(stdout, elements_kind, old_elements, | |
11267 GetElementsKind(), elems); | |
11268 } | |
11269 | |
11270 if (IsJSArray()) { | |
11271 JSArray::cast(this)->set_length(Smi::FromInt(length)); | |
11272 } | |
11273 | |
11274 return this; | |
11275 } | 11235 } |
11276 | 11236 |
11277 | 11237 |
11278 // static | 11238 // static |
11279 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) { | 11239 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) { |
11280 ASSERT(capacity >= 0); | 11240 ASSERT(capacity >= 0); |
11281 array->GetIsolate()->factory()->NewJSArrayStorage( | 11241 array->GetIsolate()->factory()->NewJSArrayStorage( |
11282 array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE); | 11242 array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE); |
11283 } | 11243 } |
11284 | 11244 |
(...skipping 1371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12656 } | 12616 } |
12657 } | 12617 } |
12658 } | 12618 } |
12659 // All possible cases have been handled above. Add a return to avoid the | 12619 // All possible cases have been handled above. Add a return to avoid the |
12660 // complaints from the compiler. | 12620 // complaints from the compiler. |
12661 UNREACHABLE(); | 12621 UNREACHABLE(); |
12662 return isolate->factory()->null_value(); | 12622 return isolate->factory()->null_value(); |
12663 } | 12623 } |
12664 | 12624 |
12665 | 12625 |
12666 void JSObject::TransitionElementsKind(Handle<JSObject> object, | |
12667 ElementsKind to_kind) { | |
12668 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), | |
12669 object->TransitionElementsKind(to_kind)); | |
12670 } | |
12671 | |
12672 | |
12673 const double AllocationSite::kPretenureRatio = 0.85; | 12626 const double AllocationSite::kPretenureRatio = 0.85; |
12674 | 12627 |
12675 | 12628 |
12676 void AllocationSite::ResetPretenureDecision() { | 12629 void AllocationSite::ResetPretenureDecision() { |
12677 set_pretenure_decision(kUndecided); | 12630 set_pretenure_decision(kUndecided); |
12678 set_memento_found_count(0); | 12631 set_memento_found_count(0); |
12679 set_memento_create_count(0); | 12632 set_memento_create_count(0); |
12680 } | 12633 } |
12681 | 12634 |
12682 | 12635 |
(...skipping 11 matching lines...) Expand all Loading... |
12694 AllocationSite* current_site = AllocationSite::cast(current); | 12647 AllocationSite* current_site = AllocationSite::cast(current); |
12695 if (current_site->nested_site() == this) { | 12648 if (current_site->nested_site() == this) { |
12696 return true; | 12649 return true; |
12697 } | 12650 } |
12698 current = current_site->weak_next(); | 12651 current = current_site->weak_next(); |
12699 } | 12652 } |
12700 return false; | 12653 return false; |
12701 } | 12654 } |
12702 | 12655 |
12703 | 12656 |
12704 MaybeObject* AllocationSite::DigestTransitionFeedback(ElementsKind to_kind) { | 12657 void AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site, |
12705 Isolate* isolate = GetIsolate(); | 12658 ElementsKind to_kind) { |
| 12659 Isolate* isolate = site->GetIsolate(); |
12706 | 12660 |
12707 if (SitePointsToLiteral() && transition_info()->IsJSArray()) { | 12661 if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) { |
12708 JSArray* transition_info = JSArray::cast(this->transition_info()); | 12662 Handle<JSArray> transition_info = |
| 12663 handle(JSArray::cast(site->transition_info())); |
12709 ElementsKind kind = transition_info->GetElementsKind(); | 12664 ElementsKind kind = transition_info->GetElementsKind(); |
12710 // if kind is holey ensure that to_kind is as well. | 12665 // if kind is holey ensure that to_kind is as well. |
12711 if (IsHoleyElementsKind(kind)) { | 12666 if (IsHoleyElementsKind(kind)) { |
12712 to_kind = GetHoleyElementsKind(to_kind); | 12667 to_kind = GetHoleyElementsKind(to_kind); |
12713 } | 12668 } |
12714 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { | 12669 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { |
12715 // If the array is huge, it's not likely to be defined in a local | 12670 // If the array is huge, it's not likely to be defined in a local |
12716 // function, so we shouldn't make new instances of it very often. | 12671 // function, so we shouldn't make new instances of it very often. |
12717 uint32_t length = 0; | 12672 uint32_t length = 0; |
12718 CHECK(transition_info->length()->ToArrayIndex(&length)); | 12673 CHECK(transition_info->length()->ToArrayIndex(&length)); |
12719 if (length <= kMaximumArrayBytesToPretransition) { | 12674 if (length <= kMaximumArrayBytesToPretransition) { |
12720 if (FLAG_trace_track_allocation_sites) { | 12675 if (FLAG_trace_track_allocation_sites) { |
12721 bool is_nested = IsNestedSite(); | 12676 bool is_nested = site->IsNestedSite(); |
12722 PrintF( | 12677 PrintF( |
12723 "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n", | 12678 "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n", |
12724 reinterpret_cast<void*>(this), | 12679 reinterpret_cast<void*>(*site), |
12725 is_nested ? "(nested)" : "", | 12680 is_nested ? "(nested)" : "", |
12726 ElementsKindToString(kind), | 12681 ElementsKindToString(kind), |
12727 ElementsKindToString(to_kind)); | 12682 ElementsKindToString(to_kind)); |
12728 } | 12683 } |
12729 MaybeObject* result = transition_info->TransitionElementsKind(to_kind); | 12684 JSObject::TransitionElementsKind(transition_info, to_kind); |
12730 if (result->IsFailure()) return result; | 12685 site->dependent_code()->DeoptimizeDependentCodeGroup( |
12731 dependent_code()->DeoptimizeDependentCodeGroup( | |
12732 isolate, DependentCode::kAllocationSiteTransitionChangedGroup); | 12686 isolate, DependentCode::kAllocationSiteTransitionChangedGroup); |
12733 } | 12687 } |
12734 } | 12688 } |
12735 } else { | 12689 } else { |
12736 ElementsKind kind = GetElementsKind(); | 12690 ElementsKind kind = site->GetElementsKind(); |
12737 // if kind is holey ensure that to_kind is as well. | 12691 // if kind is holey ensure that to_kind is as well. |
12738 if (IsHoleyElementsKind(kind)) { | 12692 if (IsHoleyElementsKind(kind)) { |
12739 to_kind = GetHoleyElementsKind(to_kind); | 12693 to_kind = GetHoleyElementsKind(to_kind); |
12740 } | 12694 } |
12741 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { | 12695 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { |
12742 if (FLAG_trace_track_allocation_sites) { | 12696 if (FLAG_trace_track_allocation_sites) { |
12743 PrintF("AllocationSite: JSArray %p site updated %s->%s\n", | 12697 PrintF("AllocationSite: JSArray %p site updated %s->%s\n", |
12744 reinterpret_cast<void*>(this), | 12698 reinterpret_cast<void*>(*site), |
12745 ElementsKindToString(kind), | 12699 ElementsKindToString(kind), |
12746 ElementsKindToString(to_kind)); | 12700 ElementsKindToString(to_kind)); |
12747 } | 12701 } |
12748 SetElementsKind(to_kind); | 12702 site->SetElementsKind(to_kind); |
12749 dependent_code()->DeoptimizeDependentCodeGroup( | 12703 site->dependent_code()->DeoptimizeDependentCodeGroup( |
12750 isolate, DependentCode::kAllocationSiteTransitionChangedGroup); | 12704 isolate, DependentCode::kAllocationSiteTransitionChangedGroup); |
12751 } | 12705 } |
12752 } | 12706 } |
12753 return this; | |
12754 } | 12707 } |
12755 | 12708 |
12756 | 12709 |
12757 // static | 12710 // static |
12758 void AllocationSite::AddDependentCompilationInfo(Handle<AllocationSite> site, | 12711 void AllocationSite::AddDependentCompilationInfo(Handle<AllocationSite> site, |
12759 Reason reason, | 12712 Reason reason, |
12760 CompilationInfo* info) { | 12713 CompilationInfo* info) { |
12761 DependentCode::DependencyGroup group = site->ToDependencyGroup(reason); | 12714 DependentCode::DependencyGroup group = site->ToDependencyGroup(reason); |
12762 Handle<DependentCode> dep(site->dependent_code()); | 12715 Handle<DependentCode> dep(site->dependent_code()); |
12763 Handle<DependentCode> codes = | 12716 Handle<DependentCode> codes = |
12764 DependentCode::Insert(dep, group, info->object_wrapper()); | 12717 DependentCode::Insert(dep, group, info->object_wrapper()); |
12765 if (*codes != site->dependent_code()) site->set_dependent_code(*codes); | 12718 if (*codes != site->dependent_code()) site->set_dependent_code(*codes); |
12766 info->dependencies(group)->Add(Handle<HeapObject>(*site), info->zone()); | 12719 info->dependencies(group)->Add(Handle<HeapObject>(*site), info->zone()); |
12767 } | 12720 } |
12768 | 12721 |
12769 | 12722 |
12770 void JSObject::UpdateAllocationSite(Handle<JSObject> object, | 12723 void JSObject::UpdateAllocationSite(Handle<JSObject> object, |
12771 ElementsKind to_kind) { | 12724 ElementsKind to_kind) { |
12772 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), | 12725 if (!object->IsJSArray()) return; |
12773 object->UpdateAllocationSite(to_kind)); | 12726 |
| 12727 Heap* heap = object->GetHeap(); |
| 12728 if (!heap->InNewSpace(*object)) return; |
| 12729 |
| 12730 Handle<AllocationSite> site; |
| 12731 { |
| 12732 DisallowHeapAllocation no_allocation; |
| 12733 // Check if there is potentially a memento behind the object. If |
| 12734 // the last word of the momento is on another page we return |
| 12735 // immediatelly. |
| 12736 Address object_address = object->address(); |
| 12737 Address memento_address = object_address + JSArray::kSize; |
| 12738 Address last_memento_word_address = memento_address + kPointerSize; |
| 12739 if (!NewSpacePage::OnSamePage(object_address, |
| 12740 last_memento_word_address)) { |
| 12741 return; |
| 12742 } |
| 12743 |
| 12744 // Either object is the last object in the new space, or there is another |
| 12745 // object of at least word size (the header map word) following it, so |
| 12746 // suffices to compare ptr and top here. |
| 12747 Address top = heap->NewSpaceTop(); |
| 12748 ASSERT(memento_address == top || |
| 12749 memento_address + HeapObject::kHeaderSize <= top); |
| 12750 if (memento_address == top) return; |
| 12751 |
| 12752 HeapObject* candidate = HeapObject::FromAddress(memento_address); |
| 12753 if (candidate->map() != heap->allocation_memento_map()) return; |
| 12754 |
| 12755 AllocationMemento* memento = AllocationMemento::cast(candidate); |
| 12756 if (!memento->IsValid()) return; |
| 12757 |
| 12758 // Walk through to the Allocation Site |
| 12759 site = handle(memento->GetAllocationSite()); |
| 12760 } |
| 12761 AllocationSite::DigestTransitionFeedback(site, to_kind); |
12774 } | 12762 } |
12775 | 12763 |
12776 | 12764 |
12777 MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { | 12765 void JSObject::TransitionElementsKind(Handle<JSObject> object, |
12778 if (!IsJSArray()) return this; | 12766 ElementsKind to_kind) { |
12779 | 12767 ElementsKind from_kind = object->map()->elements_kind(); |
12780 Heap* heap = GetHeap(); | |
12781 if (!heap->InNewSpace(this)) return this; | |
12782 | |
12783 // Check if there is potentially a memento behind the object. If | |
12784 // the last word of the momento is on another page we return | |
12785 // immediatelly. | |
12786 Address object_address = address(); | |
12787 Address memento_address = object_address + JSArray::kSize; | |
12788 Address last_memento_word_address = memento_address + kPointerSize; | |
12789 if (!NewSpacePage::OnSamePage(object_address, | |
12790 last_memento_word_address)) { | |
12791 return this; | |
12792 } | |
12793 | |
12794 // Either object is the last object in the new space, or there is another | |
12795 // object of at least word size (the header map word) following it, so | |
12796 // suffices to compare ptr and top here. | |
12797 Address top = heap->NewSpaceTop(); | |
12798 ASSERT(memento_address == top || | |
12799 memento_address + HeapObject::kHeaderSize <= top); | |
12800 if (memento_address == top) return this; | |
12801 | |
12802 HeapObject* candidate = HeapObject::FromAddress(memento_address); | |
12803 if (candidate->map() != heap->allocation_memento_map()) return this; | |
12804 | |
12805 AllocationMemento* memento = AllocationMemento::cast(candidate); | |
12806 if (!memento->IsValid()) return this; | |
12807 | |
12808 // Walk through to the Allocation Site | |
12809 AllocationSite* site = memento->GetAllocationSite(); | |
12810 return site->DigestTransitionFeedback(to_kind); | |
12811 } | |
12812 | |
12813 | |
12814 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { | |
12815 ElementsKind from_kind = map()->elements_kind(); | |
12816 | 12768 |
12817 if (IsFastHoleyElementsKind(from_kind)) { | 12769 if (IsFastHoleyElementsKind(from_kind)) { |
12818 to_kind = GetHoleyElementsKind(to_kind); | 12770 to_kind = GetHoleyElementsKind(to_kind); |
12819 } | 12771 } |
12820 | 12772 |
12821 if (from_kind == to_kind) return this; | 12773 if (from_kind == to_kind) return; |
12822 // Don't update the site if to_kind isn't fast | 12774 // Don't update the site if to_kind isn't fast |
12823 if (IsFastElementsKind(to_kind)) { | 12775 if (IsFastElementsKind(to_kind)) { |
12824 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); | 12776 UpdateAllocationSite(object, to_kind); |
12825 if (maybe_failure->IsFailure()) return maybe_failure; | |
12826 } | 12777 } |
12827 | 12778 |
12828 Isolate* isolate = GetIsolate(); | 12779 Isolate* isolate = object->GetIsolate(); |
12829 if (elements() == isolate->heap()->empty_fixed_array() || | 12780 if (object->elements() == isolate->heap()->empty_fixed_array() || |
12830 (IsFastSmiOrObjectElementsKind(from_kind) && | 12781 (IsFastSmiOrObjectElementsKind(from_kind) && |
12831 IsFastSmiOrObjectElementsKind(to_kind)) || | 12782 IsFastSmiOrObjectElementsKind(to_kind)) || |
12832 (from_kind == FAST_DOUBLE_ELEMENTS && | 12783 (from_kind == FAST_DOUBLE_ELEMENTS && |
12833 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { | 12784 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { |
12834 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); | 12785 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); |
12835 // No change is needed to the elements() buffer, the transition | 12786 // No change is needed to the elements() buffer, the transition |
12836 // only requires a map change. | 12787 // only requires a map change. |
12837 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); | 12788 Handle<Map> new_map = GetElementsTransitionMap(object, to_kind); |
12838 Map* new_map; | 12789 MigrateToMap(object, new_map); |
12839 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
12840 // TODO(verwaest): Replace by MigrateToMap. | |
12841 set_map(new_map); | |
12842 if (FLAG_trace_elements_transitions) { | 12790 if (FLAG_trace_elements_transitions) { |
12843 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 12791 Handle<FixedArrayBase> elms(object->elements()); |
12844 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); | 12792 PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms); |
12845 } | 12793 } |
12846 return this; | 12794 return; |
12847 } | 12795 } |
12848 | 12796 |
12849 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 12797 Handle<FixedArrayBase> elms(object->elements()); |
12850 uint32_t capacity = static_cast<uint32_t>(elms->length()); | 12798 uint32_t capacity = static_cast<uint32_t>(elms->length()); |
12851 uint32_t length = capacity; | 12799 uint32_t length = capacity; |
12852 | 12800 |
12853 if (IsJSArray()) { | 12801 if (object->IsJSArray()) { |
12854 Object* raw_length = JSArray::cast(this)->length(); | 12802 Object* raw_length = Handle<JSArray>::cast(object)->length(); |
12855 if (raw_length->IsUndefined()) { | 12803 if (raw_length->IsUndefined()) { |
12856 // If length is undefined, then JSArray is being initialized and has no | 12804 // If length is undefined, then JSArray is being initialized and has no |
12857 // elements, assume a length of zero. | 12805 // elements, assume a length of zero. |
12858 length = 0; | 12806 length = 0; |
12859 } else { | 12807 } else { |
12860 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | 12808 CHECK(raw_length->ToArrayIndex(&length)); |
12861 } | 12809 } |
12862 } | 12810 } |
12863 | 12811 |
12864 if (IsFastSmiElementsKind(from_kind) && | 12812 if (IsFastSmiElementsKind(from_kind) && |
12865 IsFastDoubleElementsKind(to_kind)) { | 12813 IsFastDoubleElementsKind(to_kind)) { |
12866 MaybeObject* maybe_result = | 12814 SetFastDoubleElementsCapacityAndLength(object, capacity, length); |
12867 SetFastDoubleElementsCapacityAndLength(capacity, length); | 12815 object->ValidateElements(); |
12868 if (maybe_result->IsFailure()) return maybe_result; | 12816 return; |
12869 ValidateElements(); | |
12870 return this; | |
12871 } | 12817 } |
12872 | 12818 |
12873 if (IsFastDoubleElementsKind(from_kind) && | 12819 if (IsFastDoubleElementsKind(from_kind) && |
12874 IsFastObjectElementsKind(to_kind)) { | 12820 IsFastObjectElementsKind(to_kind)) { |
12875 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( | 12821 SetFastElementsCapacityAndLength(object, capacity, length, |
12876 capacity, length, kDontAllowSmiElements); | 12822 kDontAllowSmiElements); |
12877 if (maybe_result->IsFailure()) return maybe_result; | 12823 object->ValidateElements(); |
12878 ValidateElements(); | 12824 return; |
12879 return this; | |
12880 } | 12825 } |
12881 | 12826 |
12882 // This method should never be called for any other case than the ones | 12827 // This method should never be called for any other case than the ones |
12883 // handled above. | 12828 // handled above. |
12884 UNREACHABLE(); | 12829 UNREACHABLE(); |
12885 return GetIsolate()->heap()->null_value(); | |
12886 } | 12830 } |
12887 | 12831 |
12888 | 12832 |
12889 // static | 12833 // static |
12890 bool Map::IsValidElementsTransition(ElementsKind from_kind, | 12834 bool Map::IsValidElementsTransition(ElementsKind from_kind, |
12891 ElementsKind to_kind) { | 12835 ElementsKind to_kind) { |
12892 // Transitions can't go backwards. | 12836 // Transitions can't go backwards. |
12893 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { | 12837 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { |
12894 return false; | 12838 return false; |
12895 } | 12839 } |
(...skipping 3523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16419 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16363 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16420 static const char* error_messages_[] = { | 16364 static const char* error_messages_[] = { |
16421 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16365 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16422 }; | 16366 }; |
16423 #undef ERROR_MESSAGES_TEXTS | 16367 #undef ERROR_MESSAGES_TEXTS |
16424 return error_messages_[reason]; | 16368 return error_messages_[reason]; |
16425 } | 16369 } |
16426 | 16370 |
16427 | 16371 |
16428 } } // namespace v8::internal | 16372 } } // namespace v8::internal |
OLD | NEW |