src: allocate Buffer memory using ArrayBuffer allocator · nodejs/node@84e02b1 (original) (raw)

`@@ -54,17 +54,6 @@

`

54

54

`size_t length = end - start;

`

55

55

``

56

56

`namespace node {

`

57

``

-

58

``

`-

namespace {

`

59

``

-

60

``

`-

inline void* BufferMalloc(size_t length) {

`

61

``

`-

return per_process::cli_options->zero_fill_all_buffers ?

`

62

``

`-

node::UncheckedCalloc(length) :

`

63

``

`-

node::UncheckedMalloc(length);

`

64

``

`-

}

`

65

``

-

66

``

`-

} // namespace

`

67

``

-

68

57

`namespace Buffer {

`

69

58

``

70

59

`using v8::ArrayBuffer;

`

`@@ -260,7 +249,7 @@ MaybeLocal New(Isolate* isolate,

`

260

249

`char* data = nullptr;

`

261

250

``

262

251

`if (length > 0) {

`

263

``

`-

data = static_cast<char*>(BufferMalloc(length));

`

``

252

`+

data = UncheckedMalloc(length);

`

264

253

``

265

254

`if (data == nullptr) {

`

266

255

`THROW_ERR_MEMORY_ALLOCATION_FAILED(isolate);

`

`@@ -278,13 +267,7 @@ MaybeLocal New(Isolate* isolate,

`

278

267

` }

`

279

268

` }

`

280

269

``

281

``

`-

Local buf;

`

282

``

`-

if (New(isolate, data, actual).ToLocal(&buf))

`

283

``

`-

return scope.Escape(buf);

`

284

``

-

285

``

`-

// Object failed to be created. Clean up resources.

`

286

``

`-

free(data);

`

287

``

`-

return Local();

`

``

270

`+

return scope.EscapeMaybe(New(isolate, data, actual));

`

288

271

`}

`

289

272

``

290

273

``

`@@ -311,26 +294,16 @@ MaybeLocal New(Environment* env, size_t length) {

`

311

294

`return Local();

`

312

295

` }

`

313

296

``

314

``

`-

void* data;

`

``

297

`+

AllocatedBuffer ret(env);

`

315

298

`if (length > 0) {

`

316

``

`-

data = BufferMalloc(length);

`

317

``

`-

if (data == nullptr) {

`

``

299

`+

ret = env->AllocateManaged(length, false);

`

``

300

`+

if (ret.data() == nullptr) {

`

318

301

`THROW_ERR_MEMORY_ALLOCATION_FAILED(env);

`

319

302

`return Local();

`

320

303

` }

`

321

``

`-

} else {

`

322

``

`-

data = nullptr;

`

323

304

` }

`

324

305

``

325

``

`-

Local ab =

`

326

``

`-

ArrayBuffer::New(env->isolate(),

`

327

``

`-

data,

`

328

``

`-

length,

`

329

``

`-

ArrayBufferCreationMode::kInternalized);

`

330

``

`-

Local obj;

`

331

``

`-

if (Buffer::New(env, ab, 0, length).ToLocal(&obj))

`

332

``

`-

return scope.Escape(obj);

`

333

``

`-

return Local();

`

``

306

`+

return scope.EscapeMaybe(ret.ToBuffer());

`

334

307

`}

`

335

308

``

336

309

``

`@@ -357,28 +330,18 @@ MaybeLocal Copy(Environment* env, const char* data, size_t length) {

`

357

330

`return Local();

`

358

331

` }

`

359

332

``

360

``

`-

void* new_data;

`

``

333

`+

AllocatedBuffer ret(env);

`

361

334

`if (length > 0) {

`

362

335

`CHECK_NOT_NULL(data);

`

363

``

`-

new_data = node::UncheckedMalloc(length);

`

364

``

`-

if (new_data == nullptr) {

`

``

336

`+

ret = env->AllocateManaged(length, false);

`

``

337

`+

if (ret.data() == nullptr) {

`

365

338

`THROW_ERR_MEMORY_ALLOCATION_FAILED(env);

`

366

339

`return Local();

`

367

340

` }

`

368

``

`-

memcpy(new_data, data, length);

`

369

``

`-

} else {

`

370

``

`-

new_data = nullptr;

`

``

341

`+

memcpy(ret.data(), data, length);

`

371

342

` }

`

372

343

``

373

``

`-

Local ab =

`

374

``

`-

ArrayBuffer::New(env->isolate(),

`

375

``

`-

new_data,

`

376

``

`-

length,

`

377

``

`-

ArrayBufferCreationMode::kInternalized);

`

378

``

`-

Local obj;

`

379

``

`-

if (Buffer::New(env, ab, 0, length).ToLocal(&obj))

`

380

``

`-

return scope.Escape(obj);

`

381

``

`-

return Local();

`

``

344

`+

return scope.EscapeMaybe(ret.ToBuffer());

`

382

345

`}

`

383

346

``

384

347

``

`@@ -425,7 +388,8 @@ MaybeLocal New(Environment* env,

`

425

388

`return scope.Escape(ui.ToLocalChecked());

`

426

389

`}

`

427

390

``

428

``

-

``

391

`` +

// Warning: This function needs data to be allocated with malloc() and not

``

``

392

`+

// necessarily isolate's ArrayBuffer::Allocator.

`

429

393

`MaybeLocal New(Isolate* isolate, char* data, size_t length) {

`

430

394

` EscapableHandleScope handle_scope(isolate);

`

431

395

` Environment* env = Environment::GetCurrent(isolate);

`

`@@ -435,18 +399,37 @@ MaybeLocal New(Isolate* isolate, char* data, size_t length) {

`

435

399

`return MaybeLocal();

`

436

400

` }

`

437

401

` Local obj;

`

438

``

`-

if (Buffer::New(env, data, length).ToLocal(&obj))

`

``

402

`+

if (Buffer::New(env, data, length, true).ToLocal(&obj))

`

439

403

`return handle_scope.Escape(obj);

`

440

404

`return Local();

`

441

405

`}

`

442

406

``

443

``

-

444

``

`-

MaybeLocal New(Environment* env, char* data, size_t length) {

`

``

407

`+

// Warning: If this call comes through the public node_buffer.h API,

`

``

408

`` +

// the contract for this function is that data is allocated with malloc()

``

``

409

`+

// and not necessarily isolate's ArrayBuffer::Allocator.

`

``

410

`+

MaybeLocal New(Environment* env,

`

``

411

`+

char* data,

`

``

412

`+

size_t length,

`

``

413

`+

bool uses_malloc) {

`

445

414

`if (length > 0) {

`

446

415

`CHECK_NOT_NULL(data);

`

447

416

`CHECK(length <= kMaxLength);

`

448

417

` }

`

449

418

``

``

419

`+

if (uses_malloc) {

`

``

420

`+

if (env->isolate_data()->uses_node_allocator()) {

`

``

421

`+

// We don't know for sure that the allocator is malloc()-based, so we need

`

``

422

`+

// to fall back to the FreeCallback variant.

`

``

423

`+

auto free_callback = [](char* data, void* hint) { free(data); };

`

``

424

`+

return New(env, data, length, free_callback, nullptr);

`

``

425

`+

} else {

`

``

426

`+

// This is malloc()-based, so we can acquire it into our own

`

``

427

`+

// ArrayBufferAllocator.

`

``

428

`+

CHECK_NOT_NULL(env->isolate_data()->node_allocator());

`

``

429

`+

env->isolate_data()->node_allocator()->RegisterPointer(data, length);

`

``

430

`+

}

`

``

431

`+

}

`

``

432

+

450

433

` Local ab =

`

451

434

`ArrayBuffer::New(env->isolate(),

`

452

435

` data,

`

`@@ -1053,15 +1036,13 @@ static void EncodeUtf8String(const FunctionCallbackInfo& args) {

`

1053

1036

``

1054

1037

` Local str = args[0].As();

`

1055

1038

`size_t length = str->Utf8Length(isolate);

`

1056

``

`-

char* data = node::UncheckedMalloc(length);

`

``

1039

`+

AllocatedBuffer buf = env->AllocateManaged(length);

`

1057

1040

` str->WriteUtf8(isolate,

`

1058

``

`-

data,

`

``

1041

`+

buf.data(),

`

1059

1042

`` -1, // We are certain that data is sufficiently large

``

1060

1043

`nullptr,

`

1061

1044

` String::NO_NULL_TERMINATION | String::REPLACE_INVALID_UTF8);

`

1062

``

`-

auto array_buf = ArrayBuffer::New(

`

1063

``

`-

isolate, data, length, ArrayBufferCreationMode::kInternalized);

`

1064

``

`-

auto array = Uint8Array::New(array_buf, 0, length);

`

``

1045

`+

auto array = Uint8Array::New(buf.ToArrayBuffer(), 0, length);

`

1065

1046

` args.GetReturnValue().Set(array);

`

1066

1047

`}

`

1067

1048

``

`@@ -1123,7 +1104,8 @@ void Initialize(Local target,

`

1123

1104

``

1124

1105

`// It can be a nullptr when running inside an isolate where we

`

1125

1106

`// do not own the ArrayBuffer allocator.

`

1126

``

`-

if (uint32_t* zero_fill_field = env->isolate_data()->zero_fill_field()) {

`

``

1107

`+

if (ArrayBufferAllocator* allocator = env->isolate_data()->node_allocator()) {

`

``

1108

`+

uint32_t* zero_fill_field = allocator->zero_fill_field();

`

1127

1109

` Local array_buffer = ArrayBuffer::New(

`

1128

1110

` env->isolate(), zero_fill_field, sizeof(*zero_fill_field));

`

1129

1111

`CHECK(target

`