| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent a6a74b8 commit 4d6b55a
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -30,7 +30,7 @@ const { | |||
| 30 | 30 | hexWrite, | |
| 31 | 31 | ucs2Write, | |
| 32 | 32 | utf8WriteStatic, | |
| 33 | - getZeroFillToggle, | ||
| 33 | + createUnsafeArrayBuffer, | ||
| 34 | 34 | } = internalBinding('buffer'); | |
| 35 | 35 | ||
| 36 | 36 | const { | |
@@ -39,13 +39,6 @@ const { | |||
| 39 | 39 | }, | |
| 40 | 40 | } = internalBinding('util'); | |
| 41 | 41 | ||
| 42 | - const { | ||
| 43 | - namespace: { | ||
| 44 | - isBuildingSnapshot, | ||
| 45 | - }, | ||
| 46 | - addAfterUserSerializeCallback, | ||
| 47 | - } = require('internal/v8/startup_snapshot'); | ||
| 48 | - | ||
| 49 | 42 | // Temporary buffers to convert numbers. | |
| 50 | 43 | const float32Array = new Float32Array(1); | |
| 51 | 44 | const uInt8Float32Array = new Uint8Array(float32Array.buffer); | |
@@ -1086,28 +1079,14 @@ function isMarkedAsUntransferable(obj) { | |||
| 1086 | 1079 | return obj[untransferable_object_private_symbol] !== undefined; | |
| 1087 | 1080 | } | |
| 1088 | 1081 | ||
| 1089 | - // A toggle used to access the zero fill setting of the array buffer allocator | ||
| 1090 | - // in C++. | ||
| 1091 | - // |zeroFill| can be undefined when running inside an isolate where we | ||
| 1092 | - // do not own the ArrayBuffer allocator. Zero fill is always on in that case. | ||
| 1093 | - let zeroFill; | ||
| 1094 | 1082 | function createUnsafeBuffer(size) { | |
| 1095 | - if (!zeroFill) { | ||
| 1096 | - zeroFill = getZeroFillToggle(); | ||
| 1097 | - if (isBuildingSnapshot()) { | ||
| 1098 | - // Reset the toggle so that after serialization, we'll re-create a real | ||
| 1099 | - // toggle connected to the C++ one via getZeroFillToggle(). | ||
| 1100 | - addAfterUserSerializeCallback(() => { | ||
| 1101 | - zeroFill = undefined; | ||
| 1102 | - }); | ||
| 1103 | - } | ||
| 1104 | - } | ||
| 1105 | - zeroFill[0] = 0; | ||
| 1106 | - try { | ||
| 1083 | + if (size <= 64) { | ||
| 1084 | + // Allocated in heap, doesn't call backing store anyway | ||
| 1085 | + // This is the same that the old impl did implicitly, but explicit now | ||
| 1107 | 1086 | return new FastBuffer(size); | |
| 1108 | - } finally { | ||
| 1109 | - zeroFill[0] = 1; | ||
| 1110 | 1087 | } | |
| 1088 | + | ||
| 1089 | + return new FastBuffer(createUnsafeArrayBuffer(size)); | ||
| 1111 | 1090 | } | |
| 1112 | 1091 | ||
| 1113 | 1092 | module.exports = { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -113,13 +113,8 @@ MaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context, | |||
| 113 | 113 | ||
| 114 | 114 | void* NodeArrayBufferAllocator::Allocate(size_t size) { | |
| 115 | 115 | void* ret; | |
| 116 | - if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers) { | ||
| 117 | - COUNT_GENERIC_USAGE("NodeArrayBufferAllocator.Allocate.ZeroFilled"); | ||
| 118 | - ret = allocator_->Allocate(size); | ||
| 119 | - } else { | ||
| 120 | - COUNT_GENERIC_USAGE("NodeArrayBufferAllocator.Allocate.Uninitialized"); | ||
| 121 | - ret = allocator_->AllocateUninitialized(size); | ||
| 122 | - } | ||
| 116 | + COUNT_GENERIC_USAGE("NodeArrayBufferAllocator.Allocate.ZeroFilled"); | ||
| 117 | + ret = allocator_->Allocate(size); | ||
| 123 | 118 | if (ret != nullptr) [[likely]] { | |
| 124 | 119 | total_mem_usage_.fetch_add(size, std::memory_order_relaxed); | |
| 125 | 120 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -80,7 +80,6 @@ using v8::Object; | |||
| 80 | 80 | using v8::SharedArrayBuffer; | |
| 81 | 81 | using v8::String; | |
| 82 | 82 | using v8::Uint32; | |
| 83 | - using v8::Uint32Array; | ||
| 84 | 83 | using v8::Uint8Array; | |
| 85 | 84 | using v8::Value; | |
| 86 | 85 | ||
@@ -1244,45 +1243,6 @@ void SetBufferPrototype(const FunctionCallbackInfo<Value>& args) { | |||
| 1244 | 1243 | realm->set_buffer_prototype_object(proto); | |
| 1245 | 1244 | } | |
| 1246 | 1245 | ||
| 1247 | - void GetZeroFillToggle(const FunctionCallbackInfo<Value>& args) { | ||
| 1248 | - Environment* env = Environment::GetCurrent(args); | ||
| 1249 | - NodeArrayBufferAllocator* allocator = env->isolate_data()->node_allocator(); | ||
| 1250 | - Local<ArrayBuffer> ab; | ||
| 1251 | - // It can be a nullptr when running inside an isolate where we | ||
| 1252 | - // do not own the ArrayBuffer allocator. | ||
| 1253 | - if (allocator == nullptr || env->isolate_data()->is_building_snapshot()) { | ||
| 1254 | - // Create a dummy Uint32Array - the JS land can only toggle the C++ land | ||
| 1255 | - // setting when the allocator uses our toggle. With this the toggle in JS | ||
| 1256 | - // land results in no-ops. | ||
| 1257 | - // When building a snapshot, just use a dummy toggle as well to avoid | ||
| 1258 | - // introducing the dynamic external reference. We'll re-initialize the | ||
| 1259 | - // toggle with a real one connected to the C++ allocator after snapshot | ||
| 1260 | - // deserialization. | ||
| 1261 | - | ||
| 1262 | - ab = ArrayBuffer::New(env->isolate(), sizeof(uint32_t)); | ||
| 1263 | - } else { | ||
| 1264 | - // TODO(joyeecheung): save ab->GetBackingStore()->Data() in the Node.js | ||
| 1265 | - // array buffer allocator and include it into the C++ toggle while the | ||
| 1266 | - // Environment is still alive. | ||
| 1267 | - uint32_t* zero_fill_field = allocator->zero_fill_field(); | ||
| 1268 | - std::unique_ptr<BackingStore> backing = | ||
| 1269 | - ArrayBuffer::NewBackingStore(zero_fill_field, | ||
| 1270 | - sizeof(*zero_fill_field), | ||
| 1271 | - [](void*, size_t, void*) {}, | ||
| 1272 | - nullptr); | ||
| 1273 | - ab = ArrayBuffer::New(env->isolate(), std::move(backing)); | ||
| 1274 | - } | ||
| 1275 | - | ||
| 1276 | - if (ab->SetPrivate(env->context(), | ||
| 1277 | - env->untransferable_object_private_symbol(), | ||
| 1278 | - True(env->isolate())) | ||
| 1279 | - .IsNothing()) { | ||
| 1280 | - return; | ||
| 1281 | - } | ||
| 1282 | - | ||
| 1283 | - args.GetReturnValue().Set(Uint32Array::New(ab, 0, 1)); | ||
| 1284 | - } | ||
| 1285 | - | ||
| 1286 | 1246 | static void Btoa(const FunctionCallbackInfo<Value>& args) { | |
| 1287 | 1247 | CHECK_EQ(args.Length(), 1); | |
| 1288 | 1248 | Environment* env = Environment::GetCurrent(args); | |
@@ -1449,6 +1409,57 @@ void CopyArrayBuffer(const FunctionCallbackInfo<Value>& args) { | |||
| 1449 | 1409 | memcpy(dest, src, bytes_to_copy); | |
| 1450 | 1410 | } | |
| 1451 | 1411 | ||
| 1412 | + // Converts a number parameter to size_t suitable for ArrayBuffer sizes | ||
| 1413 | + // Could be larger than uint32_t | ||
| 1414 | + // See v8::internal::TryNumberToSize and v8::internal::NumberToSize | ||
| 1415 | + inline size_t CheckNumberToSize(Local<Value> number) { | ||
| 1416 | + CHECK(number->IsNumber()); | ||
| 1417 | + double value = number.As<Number>()->Value(); | ||
| 1418 | + // See v8::internal::TryNumberToSize on this (and on < comparison) | ||
| 1419 | + double maxSize = static_cast<double>(std::numeric_limits<size_t>::max()); | ||
| 1420 | + CHECK(value >= 0 && value < maxSize); | ||
| 1421 | + size_t size = static_cast<size_t>(value); | ||
| 1422 | + #ifdef V8_ENABLE_SANDBOX | ||
| 1423 | + CHECK_LE(size, kMaxSafeBufferSizeForSandbox); | ||
| 1424 | + #endif | ||
| 1425 | + return size; | ||
| 1426 | + } | ||
| 1427 | + | ||
| 1428 | + void CreateUnsafeArrayBuffer(const FunctionCallbackInfo<Value>& args) { | ||
| 1429 | + Environment* env = Environment::GetCurrent(args); | ||
| 1430 | + if (args.Length() != 1) { | ||
| 1431 | + env->ThrowRangeError("Invalid array buffer length"); | ||
| 1432 | + return; | ||
| 1433 | + } | ||
| 1434 | + | ||
| 1435 | + size_t size = CheckNumberToSize(args[0]); | ||
| 1436 | + | ||
| 1437 | + Isolate* isolate = env->isolate(); | ||
| 1438 | + | ||
| 1439 | + Local<ArrayBuffer> buf; | ||
| 1440 | + | ||
| 1441 | + // 0-length, or zero-fill flag is set, or building snapshot | ||
| 1442 | + if (size == 0 || per_process::cli_options->zero_fill_all_buffers || | ||
| 1443 | + env->isolate_data()->is_building_snapshot()) { | ||
| 1444 | + buf = ArrayBuffer::New(isolate, size); | ||
| 1445 | + } else { | ||
| 1446 | + std::unique_ptr<BackingStore> store = ArrayBuffer::NewBackingStore( | ||
| 1447 | + isolate, | ||
| 1448 | + size, | ||
| 1449 | + BackingStoreInitializationMode::kUninitialized, | ||
| 1450 | + v8::BackingStoreOnFailureMode::kReturnNull); | ||
| 1451 | + | ||
| 1452 | + if (!store) { | ||
| 1453 | + env->ThrowRangeError("Array buffer allocation failed"); | ||
| 1454 | + return; | ||
| 1455 | + } | ||
| 1456 | + | ||
| 1457 | + buf = ArrayBuffer::New(isolate, std::move(store)); | ||
| 1458 | + } | ||
| 1459 | + | ||
| 1460 | + args.GetReturnValue().Set(buf); | ||
| 1461 | + } | ||
| 1462 | + | ||
| 1452 | 1463 | template <encoding encoding> | |
| 1453 | 1464 | uint32_t WriteOneByteString(const char* src, | |
| 1454 | 1465 | uint32_t src_len, | |
@@ -1576,6 +1587,8 @@ void Initialize(Local<Object> target, | |||
| 1576 | 1587 | SetMethodNoSideEffect(context, target, "indexOfString", IndexOfString); | |
| 1577 | 1588 | ||
| 1578 | 1589 | SetMethod(context, target, "copyArrayBuffer", CopyArrayBuffer); | |
| 1590 | + SetMethodNoSideEffect( | ||
| 1591 | + context, target, "createUnsafeArrayBuffer", CreateUnsafeArrayBuffer); | ||
| 1579 | 1592 | ||
| 1580 | 1593 | SetMethod(context, target, "swap16", Swap16); | |
| 1581 | 1594 | SetMethod(context, target, "swap32", Swap32); | |
@@ -1625,8 +1638,6 @@ void Initialize(Local<Object> target, | |||
| 1625 | 1638 | "utf8WriteStatic", | |
| 1626 | 1639 | SlowWriteString<UTF8>, | |
| 1627 | 1640 | &fast_write_string_utf8); | |
| 1628 | - | ||
| 1629 | - SetMethod(context, target, "getZeroFillToggle", GetZeroFillToggle); | ||
| 1630 | 1641 | } | |
| 1631 | 1642 | ||
| 1632 | 1643 | } // anonymous namespace | |
@@ -1675,9 +1686,9 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { | |||
| 1675 | 1686 | registry->Register(StringWrite<HEX>); | |
| 1676 | 1687 | registry->Register(StringWrite<UCS2>); | |
| 1677 | 1688 | registry->Register(StringWrite<UTF8>); | |
| 1678 | - registry->Register(GetZeroFillToggle); | ||
| 1679 | 1689 | ||
| 1680 | 1690 | registry->Register(CopyArrayBuffer); | |
| 1691 | + registry->Register(CreateUnsafeArrayBuffer); | ||
| 1681 | 1692 | ||
| 1682 | 1693 | registry->Register(Atob); | |
| 1683 | 1694 | registry->Register(Btoa); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -124,8 +124,6 @@ v8::MaybeLocal<v8::Object> InitializePrivateSymbols( | |||
| 124 | 124 | ||
| 125 | 125 | class NodeArrayBufferAllocator : public ArrayBufferAllocator { | |
| 126 | 126 | public: | |
| 127 | - inline uint32_t* zero_fill_field() { return &zero_fill_field_; } | ||
| 128 | - | ||
| 129 | 127 | void* Allocate(size_t size) override; // Defined in src/node.cc | |
| 130 | 128 | void* AllocateUninitialized(size_t size) override; | |
| 131 | 129 | void Free(void* data, size_t size) override; | |
@@ -142,7 +140,6 @@ class NodeArrayBufferAllocator : public ArrayBufferAllocator { | |||
| 142 | 140 | } | |
| 143 | 141 | ||
| 144 | 142 | private: | |
| 145 | - uint32_t zero_fill_field_ = 1; // Boolean but exposed as uint32 to JS land. | ||
| 146 | 143 | std::atomic<size_t> total_mem_usage_ {0}; | |
| 147 | 144 | ||
| 148 | 145 | // Delegate to V8's allocator for compatibility with the V8 memory cage. | |
| Back | FazBrowse Home | New Git URL |
0 commit comments