OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 22 matching lines...) Expand all Loading... |
33 #include "api.h" | 33 #include "api.h" |
34 #include "arguments.h" | 34 #include "arguments.h" |
35 #include "codegen.h" | 35 #include "codegen.h" |
36 #include "compilation-cache.h" | 36 #include "compilation-cache.h" |
37 #include "compiler.h" | 37 #include "compiler.h" |
38 #include "cpu.h" | 38 #include "cpu.h" |
39 #include "dateparser-inl.h" | 39 #include "dateparser-inl.h" |
40 #include "debug.h" | 40 #include "debug.h" |
41 #include "deoptimizer.h" | 41 #include "deoptimizer.h" |
42 #include "execution.h" | 42 #include "execution.h" |
| 43 #include "global-handles.h" |
43 #include "jsregexp.h" | 44 #include "jsregexp.h" |
44 #include "liveedit.h" | 45 #include "liveedit.h" |
45 #include "parser.h" | 46 #include "parser.h" |
46 #include "platform.h" | 47 #include "platform.h" |
47 #include "runtime.h" | 48 #include "runtime.h" |
48 #include "runtime-profiler.h" | 49 #include "runtime-profiler.h" |
49 #include "scopeinfo.h" | 50 #include "scopeinfo.h" |
50 #include "smart-pointer.h" | 51 #include "smart-pointer.h" |
51 #include "stub-cache.h" | 52 #include "stub-cache.h" |
52 #include "v8threads.h" | 53 #include "v8threads.h" |
(...skipping 7981 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8034 * The second parameter of the constructor, fast_elements, specifies | 8035 * The second parameter of the constructor, fast_elements, specifies |
8035 * whether the storage is a FixedArray or Dictionary. | 8036 * whether the storage is a FixedArray or Dictionary. |
8036 * | 8037 * |
8037 * An index limit is used to deal with the situation that a result array | 8038 * An index limit is used to deal with the situation that a result array |
8038 * length overflows 32-bit non-negative integer. | 8039 * length overflows 32-bit non-negative integer. |
8039 */ | 8040 */ |
8040 class ArrayConcatVisitor { | 8041 class ArrayConcatVisitor { |
8041 public: | 8042 public: |
8042 ArrayConcatVisitor(Handle<FixedArray> storage, | 8043 ArrayConcatVisitor(Handle<FixedArray> storage, |
8043 bool fast_elements) : | 8044 bool fast_elements) : |
8044 storage_(storage), | 8045 storage_(Handle<FixedArray>::cast(GlobalHandles::Create(*storage))), |
8045 index_offset_(0u), | 8046 index_offset_(0u), |
8046 fast_elements_(fast_elements) { } | 8047 fast_elements_(fast_elements) { } |
8047 | 8048 |
| 8049 ~ArrayConcatVisitor() { |
| 8050 clear_storage(); |
| 8051 } |
| 8052 |
8048 void visit(uint32_t i, Handle<Object> elm) { | 8053 void visit(uint32_t i, Handle<Object> elm) { |
8049 if (i >= JSObject::kMaxElementCount - index_offset_) return; | 8054 if (i >= JSObject::kMaxElementCount - index_offset_) return; |
8050 uint32_t index = index_offset_ + i; | 8055 uint32_t index = index_offset_ + i; |
8051 | 8056 |
8052 if (fast_elements_) { | 8057 if (fast_elements_) { |
8053 if (index < static_cast<uint32_t>(storage_->length())) { | 8058 if (index < static_cast<uint32_t>(storage_->length())) { |
8054 storage_->set(index, *elm); | 8059 storage_->set(index, *elm); |
8055 return; | 8060 return; |
8056 } | 8061 } |
8057 // Our initial estimate of length was foiled, possibly by | 8062 // Our initial estimate of length was foiled, possibly by |
8058 // getters on the arrays increasing the length of later arrays | 8063 // getters on the arrays increasing the length of later arrays |
8059 // during iteration. | 8064 // during iteration. |
8060 // This shouldn't happen in anything but pathological cases. | 8065 // This shouldn't happen in anything but pathological cases. |
8061 SetDictionaryMode(index); | 8066 SetDictionaryMode(index); |
8062 // Fall-through to dictionary mode. | 8067 // Fall-through to dictionary mode. |
8063 } | 8068 } |
8064 ASSERT(!fast_elements_); | 8069 ASSERT(!fast_elements_); |
8065 Handle<NumberDictionary> dict(storage_.cast<NumberDictionary>()); | 8070 Handle<NumberDictionary> dict(NumberDictionary::cast(*storage_)); |
8066 Handle<NumberDictionary> result = | 8071 Handle<NumberDictionary> result = |
8067 Factory::DictionaryAtNumberPut(dict, index, elm); | 8072 Factory::DictionaryAtNumberPut(dict, index, elm); |
8068 if (!result.is_identical_to(dict)) { | 8073 if (!result.is_identical_to(dict)) { |
8069 storage_ = Handle<FixedArray>::cast(result); | 8074 // Dictionary needed to grow. |
| 8075 clear_storage(); |
| 8076 set_storage(*result); |
8070 } | 8077 } |
8071 } | 8078 } |
8072 | 8079 |
8073 void increase_index_offset(uint32_t delta) { | 8080 void increase_index_offset(uint32_t delta) { |
8074 if (JSObject::kMaxElementCount - index_offset_ < delta) { | 8081 if (JSObject::kMaxElementCount - index_offset_ < delta) { |
8075 index_offset_ = JSObject::kMaxElementCount; | 8082 index_offset_ = JSObject::kMaxElementCount; |
8076 } else { | 8083 } else { |
8077 index_offset_ += delta; | 8084 index_offset_ += delta; |
8078 } | 8085 } |
8079 } | 8086 } |
(...skipping 11 matching lines...) Expand all Loading... |
8091 array->set_map(*map); | 8098 array->set_map(*map); |
8092 array->set_length(*length); | 8099 array->set_length(*length); |
8093 array->set_elements(*storage_); | 8100 array->set_elements(*storage_); |
8094 return array; | 8101 return array; |
8095 } | 8102 } |
8096 | 8103 |
8097 private: | 8104 private: |
8098 // Convert storage to dictionary mode. | 8105 // Convert storage to dictionary mode. |
8099 void SetDictionaryMode(uint32_t index) { | 8106 void SetDictionaryMode(uint32_t index) { |
8100 ASSERT(fast_elements_); | 8107 ASSERT(fast_elements_); |
8101 Handle<FixedArray> current_storage(storage_.ToHandle()); | 8108 Handle<FixedArray> current_storage(*storage_); |
8102 HandleCell<NumberDictionary> slow_storage( | 8109 Handle<NumberDictionary> slow_storage( |
8103 Factory::NewNumberDictionary(current_storage->length())); | 8110 Factory::NewNumberDictionary(current_storage->length())); |
8104 uint32_t current_length = static_cast<uint32_t>(current_storage->length()); | 8111 uint32_t current_length = static_cast<uint32_t>(current_storage->length()); |
8105 for (uint32_t i = 0; i < current_length; i++) { | 8112 for (uint32_t i = 0; i < current_length; i++) { |
8106 HandleScope loop_scope; | 8113 HandleScope loop_scope; |
8107 Handle<Object> element(current_storage->get(i)); | 8114 Handle<Object> element(current_storage->get(i)); |
8108 if (!element->IsTheHole()) { | 8115 if (!element->IsTheHole()) { |
8109 slow_storage = | 8116 Handle<NumberDictionary> new_storage = |
8110 Factory::DictionaryAtNumberPut(slow_storage.ToHandle(), i, element); | 8117 Factory::DictionaryAtNumberPut(slow_storage, i, element); |
| 8118 if (!new_storage.is_identical_to(slow_storage)) { |
| 8119 slow_storage = loop_scope.CloseAndEscape(new_storage); |
| 8120 } |
8111 } | 8121 } |
8112 } | 8122 } |
8113 storage_ = slow_storage.cast<FixedArray>(); | 8123 clear_storage(); |
| 8124 set_storage(*slow_storage); |
8114 fast_elements_ = false; | 8125 fast_elements_ = false; |
8115 } | 8126 } |
8116 | 8127 |
8117 HandleCell<FixedArray> storage_; | 8128 inline void clear_storage() { |
| 8129 GlobalHandles::Destroy(Handle<Object>::cast(storage_).location()); |
| 8130 } |
| 8131 |
| 8132 inline void set_storage(FixedArray* storage) { |
| 8133 storage_ = Handle<FixedArray>::cast(GlobalHandles::Create(storage)); |
| 8134 } |
| 8135 |
| 8136 Handle<FixedArray> storage_; // Always a global handle. |
8118 // Index after last seen index. Always less than or equal to | 8137 // Index after last seen index. Always less than or equal to |
8119 // JSObject::kMaxElementCount. | 8138 // JSObject::kMaxElementCount. |
8120 uint32_t index_offset_; | 8139 uint32_t index_offset_; |
8121 bool fast_elements_; | 8140 bool fast_elements_; |
8122 }; | 8141 }; |
8123 | 8142 |
8124 | 8143 |
8125 static uint32_t EstimateElementCount(Handle<JSArray> array) { | 8144 static uint32_t EstimateElementCount(Handle<JSArray> array) { |
8126 uint32_t length = static_cast<uint32_t>(array->length()->Number()); | 8145 uint32_t length = static_cast<uint32_t>(array->length()->Number()); |
8127 int element_count = 0; | 8146 int element_count = 0; |
(...skipping 3176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11304 } else { | 11323 } else { |
11305 // Handle last resort GC and make sure to allow future allocations | 11324 // Handle last resort GC and make sure to allow future allocations |
11306 // to grow the heap without causing GCs (if possible). | 11325 // to grow the heap without causing GCs (if possible). |
11307 Counters::gc_last_resort_from_js.Increment(); | 11326 Counters::gc_last_resort_from_js.Increment(); |
11308 Heap::CollectAllGarbage(false); | 11327 Heap::CollectAllGarbage(false); |
11309 } | 11328 } |
11310 } | 11329 } |
11311 | 11330 |
11312 | 11331 |
11313 } } // namespace v8::internal | 11332 } } // namespace v8::internal |
OLD | NEW |