| OLD | NEW | 
|    1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |    1 // Copyright 2006-2008 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 17 matching lines...) Expand all  Loading... | 
|   28 #ifndef V8_HEAP_INL_H_ |   28 #ifndef V8_HEAP_INL_H_ | 
|   29 #define V8_HEAP_INL_H_ |   29 #define V8_HEAP_INL_H_ | 
|   30  |   30  | 
|   31 #include "heap.h" |   31 #include "heap.h" | 
|   32 #include "objects.h" |   32 #include "objects.h" | 
|   33 #include "v8-counters.h" |   33 #include "v8-counters.h" | 
|   34  |   34  | 
|   35 namespace v8 { |   35 namespace v8 { | 
|   36 namespace internal { |   36 namespace internal { | 
|   37  |   37  | 
|   38 void Heap::UpdateOldSpaceLimits() { |  | 
|   39   intptr_t old_gen_size = PromotedSpaceSize(); |  | 
|   40   old_gen_promotion_limit_ = |  | 
|   41       old_gen_size + Max(kMinimumPromotionLimit, old_gen_size / 3); |  | 
|   42   old_gen_allocation_limit_ = |  | 
|   43       old_gen_size + Max(kMinimumAllocationLimit, old_gen_size / 2); |  | 
|   44   old_gen_exhausted_ = false; |  | 
|   45 } |  | 
|   46  |  | 
|   47  |  | 
|   48 int Heap::MaxObjectSizeInPagedSpace() { |   38 int Heap::MaxObjectSizeInPagedSpace() { | 
|   49   return Page::kMaxHeapObjectSize; |   39   return Page::kMaxHeapObjectSize; | 
|   50 } |   40 } | 
|   51  |   41  | 
|   52  |   42  | 
|   53 Object* Heap::AllocateSymbol(Vector<const char> str, |   43 MaybeObject* Heap::AllocateSymbol(Vector<const char> str, | 
|   54                              int chars, |   44                                   int chars, | 
|   55                              uint32_t hash_field) { |   45                                   uint32_t hash_field) { | 
|   56   unibrow::Utf8InputBuffer<> buffer(str.start(), |   46   unibrow::Utf8InputBuffer<> buffer(str.start(), | 
|   57                                     static_cast<unsigned>(str.length())); |   47                                     static_cast<unsigned>(str.length())); | 
|   58   return AllocateInternalSymbol(&buffer, chars, hash_field); |   48   return AllocateInternalSymbol(&buffer, chars, hash_field); | 
|   59 } |   49 } | 
|   60  |   50  | 
|   61  |   51  | 
|   62 Object* Heap::CopyFixedArray(FixedArray* src) { |   52 MaybeObject* Heap::CopyFixedArray(FixedArray* src) { | 
|   63   return CopyFixedArrayWithMap(src, src->map()); |   53   return CopyFixedArrayWithMap(src, src->map()); | 
|   64 } |   54 } | 
|   65  |   55  | 
|   66  |   56  | 
|   67 Object* Heap::AllocateRaw(int size_in_bytes, |   57 MaybeObject* Heap::AllocateRaw(int size_in_bytes, | 
|   68                           AllocationSpace space, |   58                                AllocationSpace space, | 
|   69                           AllocationSpace retry_space) { |   59                                AllocationSpace retry_space) { | 
|   70   ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); |   60   ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); | 
|   71   ASSERT(space != NEW_SPACE || |   61   ASSERT(space != NEW_SPACE || | 
|   72          retry_space == OLD_POINTER_SPACE || |   62          retry_space == OLD_POINTER_SPACE || | 
|   73          retry_space == OLD_DATA_SPACE || |   63          retry_space == OLD_DATA_SPACE || | 
|   74          retry_space == LO_SPACE); |   64          retry_space == LO_SPACE); | 
|   75 #ifdef DEBUG |   65 #ifdef DEBUG | 
|   76   if (FLAG_gc_interval >= 0 && |   66   if (FLAG_gc_interval >= 0 && | 
|   77       !disallow_allocation_failure_ && |   67       !disallow_allocation_failure_ && | 
|   78       Heap::allocation_timeout_-- <= 0) { |   68       Heap::allocation_timeout_-- <= 0) { | 
|   79     return Failure::RetryAfterGC(space); |   69     return Failure::RetryAfterGC(space); | 
|   80   } |   70   } | 
|   81   Counters::objs_since_last_full.Increment(); |   71   Counters::objs_since_last_full.Increment(); | 
|   82   Counters::objs_since_last_young.Increment(); |   72   Counters::objs_since_last_young.Increment(); | 
|   83 #endif |   73 #endif | 
|   84   Object* result; |   74   MaybeObject* result; | 
|   85   if (NEW_SPACE == space) { |   75   if (NEW_SPACE == space) { | 
|   86     result = new_space_.AllocateRaw(size_in_bytes); |   76     result = new_space_.AllocateRaw(size_in_bytes); | 
|   87     if (always_allocate() && result->IsFailure()) { |   77     if (always_allocate() && result->IsFailure()) { | 
|   88       space = retry_space; |   78       space = retry_space; | 
|   89     } else { |   79     } else { | 
|   90       return result; |   80       return result; | 
|   91     } |   81     } | 
|   92   } |   82   } | 
|   93  |   83  | 
|   94   if (OLD_POINTER_SPACE == space) { |   84   if (OLD_POINTER_SPACE == space) { | 
|   95     result = old_pointer_space_->AllocateRaw(size_in_bytes); |   85     result = old_pointer_space_->AllocateRaw(size_in_bytes); | 
|   96   } else if (OLD_DATA_SPACE == space) { |   86   } else if (OLD_DATA_SPACE == space) { | 
|   97     result = old_data_space_->AllocateRaw(size_in_bytes); |   87     result = old_data_space_->AllocateRaw(size_in_bytes); | 
|   98   } else if (CODE_SPACE == space) { |   88   } else if (CODE_SPACE == space) { | 
|   99     result = code_space_->AllocateRaw(size_in_bytes); |   89     result = code_space_->AllocateRaw(size_in_bytes); | 
|  100   } else if (LO_SPACE == space) { |   90   } else if (LO_SPACE == space) { | 
|  101     result = lo_space_->AllocateRaw(size_in_bytes); |   91     result = lo_space_->AllocateRaw(size_in_bytes); | 
|  102   } else if (CELL_SPACE == space) { |   92   } else if (CELL_SPACE == space) { | 
|  103     result = cell_space_->AllocateRaw(size_in_bytes); |   93     result = cell_space_->AllocateRaw(size_in_bytes); | 
|  104   } else { |   94   } else { | 
|  105     ASSERT(MAP_SPACE == space); |   95     ASSERT(MAP_SPACE == space); | 
|  106     result = map_space_->AllocateRaw(size_in_bytes); |   96     result = map_space_->AllocateRaw(size_in_bytes); | 
|  107   } |   97   } | 
|  108   if (result->IsFailure()) old_gen_exhausted_ = true; |   98   if (result->IsFailure()) old_gen_exhausted_ = true; | 
|  109   return result; |   99   return result; | 
|  110 } |  100 } | 
|  111  |  101  | 
|  112  |  102  | 
|  113 Object* Heap::NumberFromInt32(int32_t value) { |  103 MaybeObject* Heap::NumberFromInt32(int32_t value) { | 
|  114   if (Smi::IsValid(value)) return Smi::FromInt(value); |  104   if (Smi::IsValid(value)) return Smi::FromInt(value); | 
|  115   // Bypass NumberFromDouble to avoid various redundant checks. |  105   // Bypass NumberFromDouble to avoid various redundant checks. | 
|  116   return AllocateHeapNumber(FastI2D(value)); |  106   return AllocateHeapNumber(FastI2D(value)); | 
|  117 } |  107 } | 
|  118  |  108  | 
|  119  |  109  | 
|  120 Object* Heap::NumberFromUint32(uint32_t value) { |  110 MaybeObject* Heap::NumberFromUint32(uint32_t value) { | 
|  121   if ((int32_t)value >= 0 && Smi::IsValid((int32_t)value)) { |  111   if ((int32_t)value >= 0 && Smi::IsValid((int32_t)value)) { | 
|  122     return Smi::FromInt((int32_t)value); |  112     return Smi::FromInt((int32_t)value); | 
|  123   } |  113   } | 
|  124   // Bypass NumberFromDouble to avoid various redundant checks. |  114   // Bypass NumberFromDouble to avoid various redundant checks. | 
|  125   return AllocateHeapNumber(FastUI2D(value)); |  115   return AllocateHeapNumber(FastUI2D(value)); | 
|  126 } |  116 } | 
|  127  |  117  | 
|  128  |  118  | 
|  129 void Heap::FinalizeExternalString(String* string) { |  119 void Heap::FinalizeExternalString(String* string) { | 
|  130   ASSERT(string->IsExternalString()); |  120   ASSERT(string->IsExternalString()); | 
|  131   v8::String::ExternalStringResourceBase** resource_addr = |  121   v8::String::ExternalStringResourceBase** resource_addr = | 
|  132       reinterpret_cast<v8::String::ExternalStringResourceBase**>( |  122       reinterpret_cast<v8::String::ExternalStringResourceBase**>( | 
|  133           reinterpret_cast<byte*>(string) + |  123           reinterpret_cast<byte*>(string) + | 
|  134           ExternalString::kResourceOffset - |  124           ExternalString::kResourceOffset - | 
|  135           kHeapObjectTag); |  125           kHeapObjectTag); | 
|  136  |  126  | 
|  137   // Dispose of the C++ object if it has not already been disposed. |  127   // Dispose of the C++ object if it has not already been disposed. | 
|  138   if (*resource_addr != NULL) { |  128   if (*resource_addr != NULL) { | 
|  139     (*resource_addr)->Dispose(); |  129     (*resource_addr)->Dispose(); | 
|  140   } |  130   } | 
|  141  |  131  | 
|  142   // Clear the resource pointer in the string. |  132   // Clear the resource pointer in the string. | 
|  143   *resource_addr = NULL; |  133   *resource_addr = NULL; | 
|  144 } |  134 } | 
|  145  |  135  | 
|  146  |  136  | 
|  147 Object* Heap::AllocateRawMap() { |  137 MaybeObject* Heap::AllocateRawMap() { | 
|  148 #ifdef DEBUG |  138 #ifdef DEBUG | 
|  149   Counters::objs_since_last_full.Increment(); |  139   Counters::objs_since_last_full.Increment(); | 
|  150   Counters::objs_since_last_young.Increment(); |  140   Counters::objs_since_last_young.Increment(); | 
|  151 #endif |  141 #endif | 
|  152   Object* result = map_space_->AllocateRaw(Map::kSize); |  142   MaybeObject* result = map_space_->AllocateRaw(Map::kSize); | 
|  153   if (result->IsFailure()) old_gen_exhausted_ = true; |  143   if (result->IsFailure()) old_gen_exhausted_ = true; | 
|  154 #ifdef DEBUG |  144 #ifdef DEBUG | 
|  155   if (!result->IsFailure()) { |  145   if (!result->IsFailure()) { | 
|  156     // Maps have their own alignment. |  146     // Maps have their own alignment. | 
|  157     CHECK((reinterpret_cast<intptr_t>(result) & kMapAlignmentMask) == |  147     CHECK((reinterpret_cast<intptr_t>(result) & kMapAlignmentMask) == | 
|  158           static_cast<intptr_t>(kHeapObjectTag)); |  148           static_cast<intptr_t>(kHeapObjectTag)); | 
|  159   } |  149   } | 
|  160 #endif |  150 #endif | 
|  161   return result; |  151   return result; | 
|  162 } |  152 } | 
|  163  |  153  | 
|  164  |  154  | 
|  165 Object* Heap::AllocateRawCell() { |  155 MaybeObject* Heap::AllocateRawCell() { | 
|  166 #ifdef DEBUG |  156 #ifdef DEBUG | 
|  167   Counters::objs_since_last_full.Increment(); |  157   Counters::objs_since_last_full.Increment(); | 
|  168   Counters::objs_since_last_young.Increment(); |  158   Counters::objs_since_last_young.Increment(); | 
|  169 #endif |  159 #endif | 
|  170   Object* result = cell_space_->AllocateRaw(JSGlobalPropertyCell::kSize); |  160   MaybeObject* result = cell_space_->AllocateRaw(JSGlobalPropertyCell::kSize); | 
|  171   if (result->IsFailure()) old_gen_exhausted_ = true; |  161   if (result->IsFailure()) old_gen_exhausted_ = true; | 
|  172   return result; |  162   return result; | 
|  173 } |  163 } | 
|  174  |  164  | 
|  175  |  165  | 
|  176 bool Heap::InNewSpace(Object* object) { |  166 bool Heap::InNewSpace(Object* object) { | 
|  177   bool result = new_space_.Contains(object); |  167   bool result = new_space_.Contains(object); | 
|  178   ASSERT(!result ||                  // Either not in new space |  168   ASSERT(!result ||                  // Either not in new space | 
|  179          gc_state_ != NOT_IN_GC ||   // ... or in the middle of GC |  169          gc_state_ != NOT_IN_GC ||   // ... or in the middle of GC | 
|  180          InToSpace(object));         // ... or in to-space (where we allocate). |  170          InToSpace(object));         // ... or in to-space (where we allocate). | 
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  333   if (first_word.IsForwardingAddress()) { |  323   if (first_word.IsForwardingAddress()) { | 
|  334     *p = first_word.ToForwardingAddress(); |  324     *p = first_word.ToForwardingAddress(); | 
|  335     return; |  325     return; | 
|  336   } |  326   } | 
|  337  |  327  | 
|  338   // Call the slow part of scavenge object. |  328   // Call the slow part of scavenge object. | 
|  339   return ScavengeObjectSlow(p, object); |  329   return ScavengeObjectSlow(p, object); | 
|  340 } |  330 } | 
|  341  |  331  | 
|  342  |  332  | 
|  343 Object* Heap::PrepareForCompare(String* str) { |  333 MaybeObject* Heap::PrepareForCompare(String* str) { | 
|  344   // Always flatten small strings and force flattening of long strings |  334   // Always flatten small strings and force flattening of long strings | 
|  345   // after we have accumulated a certain amount we failed to flatten. |  335   // after we have accumulated a certain amount we failed to flatten. | 
|  346   static const int kMaxAlwaysFlattenLength = 32; |  336   static const int kMaxAlwaysFlattenLength = 32; | 
|  347   static const int kFlattenLongThreshold = 16*KB; |  337   static const int kFlattenLongThreshold = 16*KB; | 
|  348  |  338  | 
|  349   const int length = str->length(); |  339   const int length = str->length(); | 
|  350   Object* obj = str->TryFlatten(); |  340   MaybeObject* obj = str->TryFlatten(); | 
|  351   if (length <= kMaxAlwaysFlattenLength || |  341   if (length <= kMaxAlwaysFlattenLength || | 
|  352       unflattened_strings_length_ >= kFlattenLongThreshold) { |  342       unflattened_strings_length_ >= kFlattenLongThreshold) { | 
|  353     return obj; |  343     return obj; | 
|  354   } |  344   } | 
|  355   if (obj->IsFailure()) { |  345   if (obj->IsFailure()) { | 
|  356     unflattened_strings_length_ += length; |  346     unflattened_strings_length_ += length; | 
|  357   } |  347   } | 
|  358   return str; |  348   return str; | 
|  359 } |  349 } | 
|  360  |  350  | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  394   if (FLAG_gc_greedy) v8::internal::Heap::GarbageCollectionGreedyCheck() |  384   if (FLAG_gc_greedy) v8::internal::Heap::GarbageCollectionGreedyCheck() | 
|  395 #else |  385 #else | 
|  396 #define GC_GREEDY_CHECK() { } |  386 #define GC_GREEDY_CHECK() { } | 
|  397 #endif |  387 #endif | 
|  398  |  388  | 
|  399  |  389  | 
|  400 // Calls the FUNCTION_CALL function and retries it up to three times |  390 // Calls the FUNCTION_CALL function and retries it up to three times | 
|  401 // to guarantee that any allocations performed during the call will |  391 // to guarantee that any allocations performed during the call will | 
|  402 // succeed if there's enough memory. |  392 // succeed if there's enough memory. | 
|  403  |  393  | 
|  404 // Warning: Do not use the identifiers __object__ or __scope__ in a |  394 // Warning: Do not use the identifiers __object__, __maybe_object__ or | 
|  405 // call to this macro. |  395 // __scope__ in a call to this macro. | 
|  406  |  396  | 
|  407 #define CALL_AND_RETRY(FUNCTION_CALL, RETURN_VALUE, RETURN_EMPTY)         \ |  397 #define CALL_AND_RETRY(FUNCTION_CALL, RETURN_VALUE, RETURN_EMPTY)         \ | 
|  408   do {                                                                    \ |  398   do {                                                                    \ | 
|  409     GC_GREEDY_CHECK();                                                    \ |  399     GC_GREEDY_CHECK();                                                    \ | 
|  410     Object* __object__ = FUNCTION_CALL;                                   \ |  400     MaybeObject* __maybe_object__ = FUNCTION_CALL;                        \ | 
|  411     if (!__object__->IsFailure()) RETURN_VALUE;                           \ |  401     Object* __object__ = NULL;                                            \ | 
|  412     if (__object__->IsOutOfMemoryFailure()) {                             \ |  402     if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE;            \ | 
 |  403     if (__maybe_object__->IsOutOfMemory()) {                              \ | 
|  413       v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_0", true);\ |  404       v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_0", true);\ | 
|  414     }                                                                     \ |  405     }                                                                     \ | 
|  415     if (!__object__->IsRetryAfterGC()) RETURN_EMPTY;                      \ |  406     if (!__maybe_object__->IsRetryAfterGC()) RETURN_EMPTY;                \ | 
|  416     Heap::CollectGarbage(Failure::cast(__object__)->allocation_space());  \ |  407     Heap::CollectGarbage(Failure::cast(__maybe_object__)->                \ | 
|  417     __object__ = FUNCTION_CALL;                                           \ |  408                              allocation_space());                         \ | 
|  418     if (!__object__->IsFailure()) RETURN_VALUE;                           \ |  409     __maybe_object__ = FUNCTION_CALL;                                     \ | 
|  419     if (__object__->IsOutOfMemoryFailure()) {                             \ |  410     if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE;            \ | 
 |  411     if (__maybe_object__->IsOutOfMemory()) {                              \ | 
|  420       v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_1", true);\ |  412       v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_1", true);\ | 
|  421     }                                                                     \ |  413     }                                                                     \ | 
|  422     if (!__object__->IsRetryAfterGC()) RETURN_EMPTY;                      \ |  414     if (!__maybe_object__->IsRetryAfterGC()) RETURN_EMPTY;                \ | 
|  423     Counters::gc_last_resort_from_handles.Increment();                    \ |  415     Counters::gc_last_resort_from_handles.Increment();                    \ | 
|  424     Heap::CollectAllAvailableGarbage();                                   \ |  416     Heap::CollectAllGarbage(false);                                       \ | 
|  425     {                                                                     \ |  417     {                                                                     \ | 
|  426       AlwaysAllocateScope __scope__;                                      \ |  418       AlwaysAllocateScope __scope__;                                      \ | 
|  427       __object__ = FUNCTION_CALL;                                         \ |  419       __maybe_object__ = FUNCTION_CALL;                                   \ | 
|  428     }                                                                     \ |  420     }                                                                     \ | 
|  429     if (!__object__->IsFailure()) RETURN_VALUE;                           \ |  421     if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE;            \ | 
|  430     if (__object__->IsOutOfMemoryFailure() ||                             \ |  422     if (__maybe_object__->IsOutOfMemory() ||                              \ | 
|  431         __object__->IsRetryAfterGC()) {                                   \ |  423         __maybe_object__->IsRetryAfterGC()) {                             \ | 
|  432       /* TODO(1181417): Fix this. */                                      \ |  424       /* TODO(1181417): Fix this. */                                      \ | 
|  433       v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_2", true);\ |  425       v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_2", true);\ | 
|  434     }                                                                     \ |  426     }                                                                     \ | 
|  435     RETURN_EMPTY;                                                         \ |  427     RETURN_EMPTY;                                                         \ | 
|  436   } while (false) |  428   } while (false) | 
|  437  |  429  | 
|  438  |  430  | 
|  439 #define CALL_HEAP_FUNCTION(FUNCTION_CALL, TYPE)                \ |  431 #define CALL_HEAP_FUNCTION(FUNCTION_CALL, TYPE)                \ | 
|  440   CALL_AND_RETRY(FUNCTION_CALL,                                \ |  432   CALL_AND_RETRY(FUNCTION_CALL,                                \ | 
|  441                  return Handle<TYPE>(TYPE::cast(__object__)),  \ |  433                  return Handle<TYPE>(TYPE::cast(__object__)),  \ | 
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  503  |  495  | 
|  504  |  496  | 
|  505 void ExternalStringTable::ShrinkNewStrings(int position) { |  497 void ExternalStringTable::ShrinkNewStrings(int position) { | 
|  506   new_space_strings_.Rewind(position); |  498   new_space_strings_.Rewind(position); | 
|  507   Verify(); |  499   Verify(); | 
|  508 } |  500 } | 
|  509  |  501  | 
|  510 } }  // namespace v8::internal |  502 } }  // namespace v8::internal | 
|  511  |  503  | 
|  512 #endif  // V8_HEAP_INL_H_ |  504 #endif  // V8_HEAP_INL_H_ | 
| OLD | NEW |