| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 42140a1 commit 16a005c
11 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -36,7 +36,7 @@ | |||
| 36 | 36 | ||
| 37 | 37 | # Reset this number to 0 on major V8 upgrades. | |
| 38 | 38 | # Increment by one for each non-official patch applied to deps/v8. | |
| 39 | - 'v8_embedder_string': '-node.57', | ||
| 39 | + 'v8_embedder_string': '-node.58', | ||
| 40 | 40 | ||
| 41 | 41 | ##### V8 defaults for Node.js ##### | |
| 42 | 42 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,9 +18,11 @@ namespace internal { | |||
| 18 | 18 | #ifdef ENABLE_SLOW_DCHECKS | |
| 19 | 19 | #define SLOW_DCHECK(condition) \ | |
| 20 | 20 | CHECK(!v8::internal::FLAG_enable_slow_asserts || (condition)) | |
| 21 | + #define SLOW_DCHECK_IMPLIES(lhs, rhs) SLOW_DCHECK(!(lhs) || (rhs)) | ||
| 21 | 22 | V8_EXPORT_PRIVATE extern bool FLAG_enable_slow_asserts; | |
| 22 | 23 | #else | |
| 23 | 24 | #define SLOW_DCHECK(condition) ((void)0) | |
| 25 | + #define SLOW_DCHECK_IMPLIES(v1, v2) ((void)0) | ||
| 24 | 26 | static const bool FLAG_enable_slow_asserts = false; | |
| 25 | 27 | #endif | |
| 26 | 28 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -55,17 +55,19 @@ void DescriptorArray::CopyEnumCacheFrom(DescriptorArray array) { | |||
| 55 | 55 | set_enum_cache(array.enum_cache()); | |
| 56 | 56 | } | |
| 57 | 57 | ||
| 58 | - InternalIndex DescriptorArray::Search(Name name, int valid_descriptors) { | ||
| 58 | + InternalIndex DescriptorArray::Search(Name name, int valid_descriptors, | ||
| 59 | + bool concurrent_search) { | ||
| 59 | 60 | DCHECK(name.IsUniqueName()); | |
| 60 | - return InternalIndex( | ||
| 61 | - internal::Search<VALID_ENTRIES>(this, name, valid_descriptors, nullptr)); | ||
| 61 | + return InternalIndex(internal::Search<VALID_ENTRIES>( | ||
| 62 | + this, name, valid_descriptors, nullptr, concurrent_search)); | ||
| 62 | 63 | } | |
| 63 | 64 | ||
| 64 | - InternalIndex DescriptorArray::Search(Name name, Map map) { | ||
| 65 | + InternalIndex DescriptorArray::Search(Name name, Map map, | ||
| 66 | + bool concurrent_search) { | ||
| 65 | 67 | DCHECK(name.IsUniqueName()); | |
| 66 | 68 | int number_of_own_descriptors = map.NumberOfOwnDescriptors(); | |
| 67 | 69 | if (number_of_own_descriptors == 0) return InternalIndex::NotFound(); | |
| 68 | - return Search(name, number_of_own_descriptors); | ||
| 70 | + return Search(name, number_of_own_descriptors, concurrent_search); | ||
| 69 | 71 | } | |
| 70 | 72 | ||
| 71 | 73 | InternalIndex DescriptorArray::SearchWithCache(Isolate* isolate, Name name, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -115,9 +115,13 @@ class DescriptorArray | |||
| 115 | 115 | // Sort the instance descriptors by the hash codes of their keys. | |
| 116 | 116 | V8_EXPORT_PRIVATE void Sort(); | |
| 117 | 117 | ||
| 118 | - // Search the instance descriptors for given name. | ||
| 119 | - V8_INLINE InternalIndex Search(Name name, int number_of_own_descriptors); | ||
| 120 | - V8_INLINE InternalIndex Search(Name name, Map map); | ||
| 118 | + // Search the instance descriptors for given name. {concurrent_search} signals | ||
| 119 | + // if we are doing the search on a background thread. If so, we will sacrifice | ||
| 120 | + // speed for thread-safety. | ||
| 121 | + V8_INLINE InternalIndex Search(Name name, int number_of_own_descriptors, | ||
| 122 | + bool concurrent_search = false); | ||
| 123 | + V8_INLINE InternalIndex Search(Name name, Map map, | ||
| 124 | + bool concurrent_search = false); | ||
| 121 | 125 | ||
| 122 | 126 | // As the above, but uses DescriptorLookupCache and updates it when | |
| 123 | 127 | // necessary. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -284,8 +284,9 @@ int LinearSearch(T* array, Name name, int valid_entries, | |||
| 284 | 284 | } | |
| 285 | 285 | ||
| 286 | 286 | template <SearchMode search_mode, typename T> | |
| 287 | - int Search(T* array, Name name, int valid_entries, int* out_insertion_index) { | ||
| 288 | - SLOW_DCHECK(array->IsSortedNoDuplicates()); | ||
| 287 | + int Search(T* array, Name name, int valid_entries, int* out_insertion_index, | ||
| 288 | + bool concurrent_search) { | ||
| 289 | + SLOW_DCHECK_IMPLIES(!concurrent_search, array->IsSortedNoDuplicates()); | ||
| 289 | 290 | ||
| 290 | 291 | if (valid_entries == 0) { | |
| 291 | 292 | if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { | |
@@ -294,14 +295,14 @@ int Search(T* array, Name name, int valid_entries, int* out_insertion_index) { | |||
| 294 | 295 | return T::kNotFound; | |
| 295 | 296 | } | |
| 296 | 297 | ||
| 297 | - // Fast case: do linear search for small arrays. | ||
| 298 | + // Do linear search for small arrays, and for searches in the background | ||
| 299 | + // thread. | ||
| 298 | 300 | const int kMaxElementsForLinearSearch = 8; | |
| 299 | - if (valid_entries <= kMaxElementsForLinearSearch) { | ||
| 301 | + if (valid_entries <= kMaxElementsForLinearSearch || concurrent_search) { | ||
| 300 | 302 | return LinearSearch<search_mode>(array, name, valid_entries, | |
| 301 | 303 | out_insertion_index); | |
| 302 | 304 | } | |
| 303 | 305 | ||
| 304 | - // Slow case: perform binary search. | ||
| 305 | 306 | return BinarySearch<search_mode>(array, name, valid_entries, | |
| 306 | 307 | out_insertion_index); | |
| 307 | 308 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -465,7 +465,8 @@ enum SearchMode { ALL_ENTRIES, VALID_ENTRIES }; | |||
| 465 | 465 | ||
| 466 | 466 | template <SearchMode search_mode, typename T> | |
| 467 | 467 | inline int Search(T* array, Name name, int valid_entries = 0, | |
| 468 | - int* out_insertion_index = nullptr); | ||
| 468 | + int* out_insertion_index = nullptr, | ||
| 469 | + bool concurrent_search = false); | ||
| 469 | 470 | ||
| 470 | 471 | // ByteArray represents fixed sized byte arrays. Used for the relocation info | |
| 471 | 472 | // that is attached to code objects. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -594,6 +594,7 @@ class Map : public HeapObject { | |||
| 594 | 594 | WriteBarrierMode mode = UPDATE_WRITE_BARRIER); | |
| 595 | 595 | ||
| 596 | 596 | // [instance descriptors]: describes the object. | |
| 597 | + DECL_GETTER(synchronized_instance_descriptors, DescriptorArray) | ||
| 597 | 598 | DECL_GETTER(instance_descriptors, DescriptorArray) | |
| 598 | 599 | V8_EXPORT_PRIVATE void SetInstanceDescriptors(Isolate* isolate, | |
| 599 | 600 | DescriptorArray descriptors, | |
@@ -976,7 +977,8 @@ class Map : public HeapObject { | |||
| 976 | 977 | MaybeHandle<Object> new_value); | |
| 977 | 978 | ||
| 978 | 979 | // Use the high-level instance_descriptors/SetInstanceDescriptors instead. | |
| 979 | - DECL_ACCESSORS(synchronized_instance_descriptors, DescriptorArray) | ||
| 980 | + inline void set_synchronized_instance_descriptors( | ||
| 981 | + DescriptorArray value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); | ||
| 980 | 982 | ||
| 981 | 983 | static const int kFastPropertiesSoftLimit = 12; | |
| 982 | 984 | static const int kMaxFastProperties = 128; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -196,6 +196,7 @@ v8_source_set("cctest_sources") { | |||
| 196 | 196 | "test-code-pages.cc", | |
| 197 | 197 | "test-code-stub-assembler.cc", | |
| 198 | 198 | "test-compiler.cc", | |
| 199 | + "test-concurrent-descriptor-array.cc", | ||
| 199 | 200 | "test-constantpool.cc", | |
| 200 | 201 | "test-conversions.cc", | |
| 201 | 202 | "test-cpu-profiler.cc", | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,128 @@ | |||
| 1 | + // Copyright 2020 the V8 project authors. All rights reserved. | ||
| 2 | + // Use of this source code is governed by a BSD-style license that can be | ||
| 3 | + // found in the LICENSE file. | ||
| 4 | + | ||
| 5 | + #include "src/api/api.h" | ||
| 6 | + #include "src/base/platform/semaphore.h" | ||
| 7 | + #include "src/handles/handles-inl.h" | ||
| 8 | + #include "src/handles/local-handles-inl.h" | ||
| 9 | + #include "src/handles/persistent-handles.h" | ||
| 10 | + #include "src/heap/heap.h" | ||
| 11 | + #include "src/heap/local-heap.h" | ||
| 12 | + #include "test/cctest/cctest.h" | ||
| 13 | + #include "test/cctest/heap/heap-utils.h" | ||
| 14 | + | ||
| 15 | + namespace v8 { | ||
| 16 | + namespace internal { | ||
| 17 | + | ||
| 18 | + static constexpr int kNumHandles = kHandleBlockSize * 2 + kHandleBlockSize / 2; | ||
| 19 | + | ||
| 20 | + namespace { | ||
| 21 | + | ||
| 22 | + class PersistentHandlesThread final : public v8::base::Thread { | ||
| 23 | + public: | ||
| 24 | + PersistentHandlesThread(Heap* heap, std::vector<Handle<JSObject>> handles, | ||
| 25 | + std::unique_ptr<PersistentHandles> ph, | ||
| 26 | + Handle<Name> name, base::Semaphore* sema_started) | ||
| 27 | + : v8::base::Thread(base::Thread::Options("ThreadWithLocalHeap")), | ||
| 28 | + heap_(heap), | ||
| 29 | + handles_(std::move(handles)), | ||
| 30 | + ph_(std::move(ph)), | ||
| 31 | + name_(name), | ||
| 32 | + sema_started_(sema_started) {} | ||
| 33 | + | ||
| 34 | + void Run() override { | ||
| 35 | + LocalHeap local_heap(heap_, std::move(ph_)); | ||
| 36 | + LocalHandleScope scope(&local_heap); | ||
| 37 | + Address object = handles_[0]->ptr(); | ||
| 38 | + | ||
| 39 | + for (int i = 0; i < kNumHandles; i++) { | ||
| 40 | + handles_.push_back( | ||
| 41 | + Handle<JSObject>::cast(local_heap.NewPersistentHandle(object))); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + sema_started_->Signal(); | ||
| 45 | + | ||
| 46 | + for (Handle<JSObject> handle : handles_) { | ||
| 47 | + // Lookup the named property on the {map}. | ||
| 48 | + CHECK(name_->IsUniqueName()); | ||
| 49 | + Handle<Map> map(handle->map(), &local_heap); | ||
| 50 | + | ||
| 51 | + Handle<DescriptorArray> descriptors( | ||
| 52 | + map->synchronized_instance_descriptors(), &local_heap); | ||
| 53 | + bool is_background_thread = true; | ||
| 54 | + InternalIndex const number = | ||
| 55 | + descriptors->Search(*name_, *map, is_background_thread); | ||
| 56 | + CHECK(number.is_found()); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + CHECK_EQ(handles_.size(), kNumHandles * 2); | ||
| 60 | + | ||
| 61 | + CHECK(!ph_); | ||
| 62 | + ph_ = local_heap.DetachPersistentHandles(); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + Heap* heap_; | ||
| 66 | + std::vector<Handle<JSObject>> handles_; | ||
| 67 | + std::unique_ptr<PersistentHandles> ph_; | ||
| 68 | + Handle<Name> name_; | ||
| 69 | + base::Semaphore* sema_started_; | ||
| 70 | + }; | ||
| 71 | + | ||
| 72 | + // Uses linear search on a flat object, with up to 8 elements. | ||
| 73 | + TEST(LinearSearchFlatObject) { | ||
| 74 | + CcTest::InitializeVM(); | ||
| 75 | + FLAG_local_heaps = true; | ||
| 76 | + Isolate* isolate = CcTest::i_isolate(); | ||
| 77 | + | ||
| 78 | + std::unique_ptr<PersistentHandles> ph = isolate->NewPersistentHandles(); | ||
| 79 | + std::vector<Handle<JSObject>> handles; | ||
| 80 | + | ||
| 81 | + auto factory = isolate->factory(); | ||
| 82 | + HandleScope handle_scope(isolate); | ||
| 83 | + | ||
| 84 | + Handle<JSFunction> function = | ||
| 85 | + factory->NewFunctionForTest(factory->empty_string()); | ||
| 86 | + Handle<JSObject> js_object = factory->NewJSObject(function); | ||
| 87 | + Handle<String> name = CcTest::MakeString("property"); | ||
| 88 | + Handle<Object> value = CcTest::MakeString("dummy_value"); | ||
| 89 | + // For the default constructor function no in-object properties are reserved | ||
| 90 | + // hence adding a single property will initialize the property-array. | ||
| 91 | + JSObject::DefinePropertyOrElementIgnoreAttributes(js_object, name, value, | ||
| 92 | + NONE) | ||
| 93 | + .Check(); | ||
| 94 | + | ||
| 95 | + Address object = js_object->ptr(); | ||
| 96 | + for (int i = 0; i < kNumHandles; i++) { | ||
| 97 | + handles.push_back(Handle<JSObject>::cast(ph->NewHandle(object))); | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + Handle<Name> persistent_name = Handle<Name>::cast(ph->NewHandle(name->ptr())); | ||
| 101 | + | ||
| 102 | + base::Semaphore sema_started(0); | ||
| 103 | + | ||
| 104 | + // Pass persistent handles to background thread. | ||
| 105 | + std::unique_ptr<PersistentHandlesThread> thread(new PersistentHandlesThread( | ||
| 106 | + isolate->heap(), std::move(handles), std::move(ph), persistent_name, | ||
| 107 | + &sema_started)); | ||
| 108 | + CHECK(thread->Start()); | ||
| 109 | + | ||
| 110 | + sema_started.Wait(); | ||
| 111 | + | ||
| 112 | + // Exercise descriptor in main thread too. | ||
| 113 | + for (int i = 0; i < 7; ++i) { | ||
| 114 | + Handle<String> filler_name = CcTest::MakeName("filler_property_", i); | ||
| 115 | + Handle<Object> filler_value = CcTest::MakeString("dummy_value"); | ||
| 116 | + JSObject::DefinePropertyOrElementIgnoreAttributes(js_object, filler_name, | ||
| 117 | + filler_value, NONE) | ||
| 118 | + .Check(); | ||
| 119 | + } | ||
| 120 | + CHECK_EQ(js_object->map().NumberOfOwnDescriptors(), 8); | ||
| 121 | + | ||
| 122 | + thread->Join(); | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + } // anonymous namespace | ||
| 126 | + | ||
| 127 | + } // namespace internal | ||
| 128 | + } // namespace v8 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -20,6 +20,8 @@ | |||
| 20 | 20 | namespace v8 { | |
| 21 | 21 | namespace internal { | |
| 22 | 22 | ||
| 23 | + namespace { | ||
| 24 | + | ||
| 23 | 25 | class LocalHandlesThread final : public v8::base::Thread { | |
| 24 | 26 | public: | |
| 25 | 27 | LocalHandlesThread(Heap* heap, Address object, base::Semaphore* sema_started, | |
@@ -92,5 +94,7 @@ TEST(CreateLocalHandles) { | |||
| 92 | 94 | thread->Join(); | |
| 93 | 95 | } | |
| 94 | 96 | ||
| 97 | + } // anonymous namespace | ||
| 98 | + | ||
| 95 | 99 | } // namespace internal | |
| 96 | 100 | } // namespace v8 | |
| Back | FazBrowse Home | New Git URL |
0 commit comments