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 9324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9335 } | 9335 } |
9336 | 9336 |
9337 if (IsJSArray()) { | 9337 if (IsJSArray()) { |
9338 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 9338 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
9339 } | 9339 } |
9340 | 9340 |
9341 return this; | 9341 return this; |
9342 } | 9342 } |
9343 | 9343 |
9344 | 9344 |
9345 MaybeObject* JSArray::Initialize(int capacity) { | 9345 MaybeObject* JSArray::Initialize(int capacity, int length) { |
9346 Heap* heap = GetHeap(); | |
9347 ASSERT(capacity >= 0); | 9346 ASSERT(capacity >= 0); |
9348 set_length(Smi::FromInt(0)); | 9347 return GetHeap()->AllocateJSArrayStorage(this, length, capacity, |
9349 FixedArrayBase* new_elements; | 9348 INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE); |
9350 if (capacity == 0) { | |
9351 new_elements = heap->empty_fixed_array(); | |
9352 } else { | |
9353 ElementsKind elements_kind = GetElementsKind(); | |
9354 MaybeObject* maybe_obj; | |
9355 if (IsFastDoubleElementsKind(elements_kind)) { | |
9356 maybe_obj = heap->AllocateFixedDoubleArrayWithHoles(capacity); | |
9357 } else { | |
9358 maybe_obj = heap->AllocateFixedArrayWithHoles(capacity); | |
9359 } | |
9360 if (!maybe_obj->To(&new_elements)) return maybe_obj; | |
9361 } | |
9362 set_elements(new_elements); | |
9363 return this; | |
9364 } | 9349 } |
9365 | 9350 |
9366 | 9351 |
9367 void JSArray::Expand(int required_size) { | 9352 void JSArray::Expand(int required_size) { |
9368 GetIsolate()->factory()->SetElementsCapacityAndLength( | 9353 GetIsolate()->factory()->SetElementsCapacityAndLength( |
9369 Handle<JSArray>(this), required_size, required_size); | 9354 Handle<JSArray>(this), required_size, required_size); |
9370 } | 9355 } |
9371 | 9356 |
9372 | 9357 |
9373 // Returns false if the passed-in index is marked non-configurable, | 9358 // Returns false if the passed-in index is marked non-configurable, |
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10042 check_prototype); | 10027 check_prototype); |
10043 } | 10028 } |
10044 } | 10029 } |
10045 // Convert to fast double elements if appropriate. | 10030 // Convert to fast double elements if appropriate. |
10046 if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { | 10031 if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { |
10047 // Consider fixing the boilerplate as well if we have one. | 10032 // Consider fixing the boilerplate as well if we have one. |
10048 ElementsKind to_kind = IsHoleyElementsKind(elements_kind) | 10033 ElementsKind to_kind = IsHoleyElementsKind(elements_kind) |
10049 ? FAST_HOLEY_DOUBLE_ELEMENTS | 10034 ? FAST_HOLEY_DOUBLE_ELEMENTS |
10050 : FAST_DOUBLE_ELEMENTS; | 10035 : FAST_DOUBLE_ELEMENTS; |
10051 | 10036 |
10052 MaybeObject* trans = PossiblyTransitionArrayBoilerplate(to_kind); | 10037 MaybeObject* maybe_failure = UpdateAllocationSiteInfo(to_kind); |
10053 if (trans->IsFailure()) return trans; | 10038 if (maybe_failure->IsFailure()) return maybe_failure; |
10054 | 10039 |
10055 MaybeObject* maybe = | 10040 MaybeObject* maybe = |
10056 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); | 10041 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); |
10057 if (maybe->IsFailure()) return maybe; | 10042 if (maybe->IsFailure()) return maybe; |
10058 FixedDoubleArray::cast(elements())->set(index, value->Number()); | 10043 FixedDoubleArray::cast(elements())->set(index, value->Number()); |
10059 ValidateElements(); | 10044 ValidateElements(); |
10060 return value; | 10045 return value; |
10061 } | 10046 } |
10062 // Change elements kind from Smi-only to generic FAST if necessary. | 10047 // Change elements kind from Smi-only to generic FAST if necessary. |
10063 if (HasFastSmiElements() && !value->IsSmi()) { | 10048 if (HasFastSmiElements() && !value->IsSmi()) { |
10064 Map* new_map; | 10049 Map* new_map; |
10065 ElementsKind kind = HasFastHoleyElements() | 10050 ElementsKind kind = HasFastHoleyElements() |
10066 ? FAST_HOLEY_ELEMENTS | 10051 ? FAST_HOLEY_ELEMENTS |
10067 : FAST_ELEMENTS; | 10052 : FAST_ELEMENTS; |
10068 | 10053 |
10069 MaybeObject* trans = PossiblyTransitionArrayBoilerplate(kind); | 10054 MaybeObject* maybe_failure = UpdateAllocationSiteInfo(kind); |
10070 if (trans->IsFailure()) return trans; | 10055 if (maybe_failure->IsFailure()) return maybe_failure; |
10071 | 10056 |
10072 MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), | 10057 MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), |
10073 kind); | 10058 kind); |
10074 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 10059 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
10075 | 10060 |
10076 set_map(new_map); | 10061 set_map(new_map); |
10077 } | 10062 } |
10078 // Increase backing store capacity if that's been decided previously. | 10063 // Increase backing store capacity if that's been decided previously. |
10079 if (new_capacity != capacity) { | 10064 if (new_capacity != capacity) { |
10080 FixedArray* new_elements; | 10065 FixedArray* new_elements; |
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10607 | 10592 |
10608 | 10593 |
10609 Handle<Object> JSObject::TransitionElementsKind(Handle<JSObject> object, | 10594 Handle<Object> JSObject::TransitionElementsKind(Handle<JSObject> object, |
10610 ElementsKind to_kind) { | 10595 ElementsKind to_kind) { |
10611 CALL_HEAP_FUNCTION(object->GetIsolate(), | 10596 CALL_HEAP_FUNCTION(object->GetIsolate(), |
10612 object->TransitionElementsKind(to_kind), | 10597 object->TransitionElementsKind(to_kind), |
10613 Object); | 10598 Object); |
10614 } | 10599 } |
10615 | 10600 |
10616 | 10601 |
10617 // TODO(mvstanton): rename this method to reflect what it actually does. | 10602 MaybeObject* JSObject::UpdateAllocationSiteInfo(ElementsKind to_kind) { |
10618 // If a boilerplate object is discovered, then it will transition it. | |
10619 // If instead there is a elements kind, then update it as long as the | |
10620 // to_kind variable is more general than what we find, but don't | |
10621 // ever take the double->fastobject transition (that represents poisoning), | |
10622 // just ignore that case. | |
10623 MaybeObject* JSObject::PossiblyTransitionArrayBoilerplate( | |
10624 ElementsKind to_kind) { | |
10625 MaybeObject* ret = NULL; | |
10626 if (!FLAG_track_allocation_sites || !IsJSArray()) { | 10603 if (!FLAG_track_allocation_sites || !IsJSArray()) { |
10627 return ret; | 10604 return this; |
10628 } | 10605 } |
10629 | 10606 |
10630 AllocationSiteInfo* info = AllocationSiteInfo::FindForJSObject(this); | 10607 AllocationSiteInfo* info = AllocationSiteInfo::FindForJSObject(this); |
10631 if (info == NULL) { | 10608 if (info == NULL) { |
10632 return ret; | 10609 return this; |
10633 } | 10610 } |
10634 | 10611 |
10635 if (info->payload()->IsJSArray()) { | 10612 if (info->payload()->IsJSArray()) { |
10636 JSArray* payload = JSArray::cast(info->payload()); | 10613 JSArray* payload = JSArray::cast(info->payload()); |
10637 ElementsKind kind = payload->GetElementsKind(); | 10614 ElementsKind kind = payload->GetElementsKind(); |
10638 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { | 10615 if (AllocationSiteInfo::GetMode(kind, to_kind) == TRACK_ALLOCATION_SITE) { |
10639 // If the array is huge, it's not likely to be defined in a local | 10616 // If the array is huge, it's not likely to be defined in a local |
10640 // function, so we shouldn't make new instances of it very often. | 10617 // function, so we shouldn't make new instances of it very often. |
10641 uint32_t length = 0; | 10618 uint32_t length = 0; |
10642 CHECK(payload->length()->ToArrayIndex(&length)); | 10619 CHECK(payload->length()->ToArrayIndex(&length)); |
10643 if (length <= 8*1024) { | 10620 if (length <= AllocationSiteInfo::kMaximumArrayBytesToPretransition) { |
10644 ret = payload->TransitionElementsKind(to_kind); | |
10645 if (FLAG_trace_track_allocation_sites) { | 10621 if (FLAG_trace_track_allocation_sites) { |
10646 PrintF( | 10622 PrintF( |
10647 "AllocationSiteInfo: JSArray %p boilerplate updated %s->%s\n", | 10623 "AllocationSiteInfo: JSArray %p boilerplate updated %s->%s\n", |
10648 reinterpret_cast<void*>(this), | 10624 reinterpret_cast<void*>(this), |
10649 ElementsKindToString(kind), | 10625 ElementsKindToString(kind), |
10650 ElementsKindToString(to_kind)); | 10626 ElementsKindToString(to_kind)); |
10651 } | 10627 } |
| 10628 return payload->TransitionElementsKind(to_kind); |
10652 } | 10629 } |
10653 } | 10630 } |
10654 } else if (info->payload()->IsJSGlobalPropertyCell()) { | 10631 } else if (info->payload()->IsJSGlobalPropertyCell()) { |
10655 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(info->payload()); | 10632 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(info->payload()); |
10656 Object* cell_contents = cell->value(); | 10633 Object* cell_contents = cell->value(); |
10657 if (cell_contents->IsSmi()) { | 10634 if (cell_contents->IsSmi()) { |
10658 ElementsKind kind = static_cast<ElementsKind>( | 10635 ElementsKind kind = static_cast<ElementsKind>( |
10659 Smi::cast(cell_contents)->value()); | 10636 Smi::cast(cell_contents)->value()); |
10660 // Specifically exclude DOUBLE(HOLEY) -> FAST(HOLEY) | 10637 if (AllocationSiteInfo::GetMode(kind, to_kind) == TRACK_ALLOCATION_SITE) { |
10661 bool double_to_fast = IsFastDoubleElementsKind(kind) && | |
10662 IsFastObjectElementsKind(to_kind); | |
10663 if (IsMoreGeneralElementsKindTransition(kind, to_kind) && | |
10664 !double_to_fast) { | |
10665 if (FLAG_trace_track_allocation_sites) { | 10638 if (FLAG_trace_track_allocation_sites) { |
10666 PrintF("AllocationSiteInfo: JSArray %p info updated %s->%s\n", | 10639 PrintF("AllocationSiteInfo: JSArray %p info updated %s->%s\n", |
10667 reinterpret_cast<void*>(this), | 10640 reinterpret_cast<void*>(this), |
10668 ElementsKindToString(kind), | 10641 ElementsKindToString(kind), |
10669 ElementsKindToString(to_kind)); | 10642 ElementsKindToString(to_kind)); |
10670 } | 10643 } |
10671 cell->set_value(Smi::FromInt(to_kind)); | 10644 cell->set_value(Smi::FromInt(to_kind)); |
10672 } | 10645 } |
10673 } | 10646 } |
10674 } | 10647 } |
10675 return ret; | 10648 return this; |
10676 } | 10649 } |
10677 | 10650 |
10678 | 10651 |
10679 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { | 10652 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { |
10680 ASSERT(!map()->is_observed()); | 10653 ASSERT(!map()->is_observed()); |
10681 ElementsKind from_kind = map()->elements_kind(); | 10654 ElementsKind from_kind = map()->elements_kind(); |
10682 | 10655 |
10683 if (IsFastHoleyElementsKind(from_kind)) { | 10656 if (IsFastHoleyElementsKind(from_kind)) { |
10684 to_kind = GetHoleyElementsKind(to_kind); | 10657 to_kind = GetHoleyElementsKind(to_kind); |
10685 } | 10658 } |
10686 | 10659 |
10687 if (from_kind == to_kind) return this; | 10660 if (from_kind == to_kind) return this; |
10688 | 10661 |
10689 MaybeObject* trans = PossiblyTransitionArrayBoilerplate(to_kind); | 10662 MaybeObject* maybe_failure = UpdateAllocationSiteInfo(to_kind); |
10690 if (trans->IsFailure()) return trans; | 10663 if (maybe_failure->IsFailure()) return maybe_failure; |
10691 | 10664 |
10692 Isolate* isolate = GetIsolate(); | 10665 Isolate* isolate = GetIsolate(); |
10693 if (elements() == isolate->heap()->empty_fixed_array() || | 10666 if (elements() == isolate->heap()->empty_fixed_array() || |
10694 (IsFastSmiOrObjectElementsKind(from_kind) && | 10667 (IsFastSmiOrObjectElementsKind(from_kind) && |
10695 IsFastSmiOrObjectElementsKind(to_kind)) || | 10668 IsFastSmiOrObjectElementsKind(to_kind)) || |
10696 (from_kind == FAST_DOUBLE_ELEMENTS && | 10669 (from_kind == FAST_DOUBLE_ELEMENTS && |
10697 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { | 10670 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { |
10698 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); | 10671 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); |
10699 // No change is needed to the elements() buffer, the transition | 10672 // No change is needed to the elements() buffer, the transition |
10700 // only requires a map change. | 10673 // only requires a map change. |
(...skipping 3334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14035 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 14008 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
14036 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 14009 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
14037 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 14010 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
14038 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 14011 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
14039 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 14012 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
14040 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 14013 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
14041 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 14014 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
14042 } | 14015 } |
14043 | 14016 |
14044 } } // namespace v8::internal | 14017 } } // namespace v8::internal |
OLD | NEW |