@@ -211,6 +211,8 @@ CodeGenNumberThreadAllocator::Integrate()
211
211
212
212
while (!pendingIntegrationChunkBlock.Empty ())
213
213
{
214
+ // REVIEW: the above number block integration can be moved into this loop
215
+
214
216
TRACK_ALLOC_INFO (recycler, CodeGenNumberChunk, Recycler, 0 , (size_t )-1 );
215
217
216
218
BlockRecord& record = pendingIntegrationChunkBlock.Head ();
@@ -287,3 +289,235 @@ CodeGenNumberAllocator::Finalize()
287
289
this ->currentChunkNumberCount = 0 ;
288
290
return finalizedChunk;
289
291
}
292
+
293
+
294
+ Js::JavascriptNumber* XProcNumberPageSegmentImpl::AllocateNumber (HANDLE hProcess, double value, Js::StaticType* numberTypeStatic, void * javascriptNumberVtbl)
295
+ {
296
+ XProcNumberPageSegmentImpl* tail = this ;
297
+
298
+ if (this ->pageAddress != 0 )
299
+ {
300
+ while (tail->nextSegment )
301
+ {
302
+ tail = (XProcNumberPageSegmentImpl*)tail->nextSegment ;
303
+ }
304
+
305
+ if (tail->pageAddress + tail->committedEnd - tail->allocEndAddress >= sizeCat)
306
+ {
307
+ auto number = tail->allocEndAddress ;
308
+ tail->allocEndAddress += sizeCat;
309
+
310
+ Js::JavascriptNumber localNumber (value, numberTypeStatic, true );
311
+
312
+ // change vtable to the remote one
313
+ *(void **)&localNumber = javascriptNumberVtbl;
314
+
315
+ // initialize number by WriteProcessMemory
316
+ SIZE_T bytesWritten;
317
+ WriteProcessMemory (hProcess, (void *)number, &localNumber, sizeof (localNumber), &bytesWritten);
318
+
319
+ return (Js::JavascriptNumber*) number;
320
+ }
321
+
322
+ // alloc blocks
323
+ if ((void *)tail->committedEnd < tail->GetEndAddress ())
324
+ {
325
+ Assert ((unsigned int )((char *)tail->GetEndAddress () - (char *)tail->committedEnd ) >= tail->blockSize );
326
+ // TODO: implement guard pages (still necessary for OOP JIT?)
327
+ auto ret = ::VirtualAllocEx (hProcess, tail->GetCommitEndAddress (), tail->blockSize , MEM_COMMIT, PAGE_READWRITE);
328
+ if (!ret)
329
+ {
330
+ Js::Throw::OutOfMemory ();
331
+ }
332
+ tail->committedEnd += tail->blockSize ;
333
+ return AllocateNumber (hProcess, value, numberTypeStatic, javascriptNumberVtbl);
334
+ }
335
+ }
336
+
337
+ // alloc new segment
338
+ void * pages = ::VirtualAllocEx (hProcess, nullptr , this ->pageCount * AutoSystemInfo::PageSize, MEM_RESERVE, PAGE_READWRITE);
339
+ if (pages == nullptr )
340
+ {
341
+ Js::Throw::OutOfMemory ();
342
+ }
343
+
344
+ if (tail->pageAddress == 0 )
345
+ {
346
+ tail = new (tail) XProcNumberPageSegmentImpl ();
347
+ tail->pageAddress = (int )pages;
348
+ tail->allocStartAddress = this ->pageAddress ;
349
+ tail->allocEndAddress = this ->pageAddress ;
350
+ tail->nextSegment = nullptr ;
351
+ return AllocateNumber (hProcess, value, numberTypeStatic, javascriptNumberVtbl);
352
+ }
353
+ else
354
+ {
355
+ XProcNumberPageSegmentImpl* seg = new (midl_user_allocate (sizeof (XProcNumberPageSegment))) XProcNumberPageSegmentImpl ();
356
+ tail->nextSegment = seg;
357
+ return seg->AllocateNumber (hProcess, value, numberTypeStatic, javascriptNumberVtbl);
358
+ }
359
+ }
360
+
361
+
362
+ XProcNumberPageSegmentImpl::XProcNumberPageSegmentImpl ()
363
+ {
364
+ this ->pageCount = Memory::IdleDecommitPageAllocator::DefaultMaxAllocPageCount;
365
+ this ->sizeCat = HeapInfo::GetAlignedSizeNoCheck (sizeof (Js::JavascriptNumber));
366
+ this ->blockSize = SmallAllocationBlockAttributes::PageCount*AutoSystemInfo::PageSize;
367
+ this ->blockIntegratedSize = 0 ;
368
+ this ->pageSegment = 0 ;
369
+ }
370
+
371
+ CodeGenNumberChunk* ::XProcNumberPageSegmentManager::RegisterSegments(XProcNumberPageSegment* segments)
372
+ {
373
+ Assert (segments->pageAddress && segments->allocStartAddress && segments->allocEndAddress );
374
+
375
+
376
+ XProcNumberPageSegmentImpl* segmentImpl = (XProcNumberPageSegmentImpl*)segments;
377
+
378
+ auto temp = segmentImpl;
379
+ CodeGenNumberChunk* chunk = nullptr ;
380
+ int numberCount = CodeGenNumberChunk::MaxNumberCount;
381
+ while (temp)
382
+ {
383
+ auto start = temp->allocStartAddress ;
384
+
385
+ if (temp->GetChunkAllocator () == nullptr )
386
+ {
387
+ temp->chunkAllocator = (intptr_t )HeapNew (CodeGenNumberThreadAllocator, this ->recycler );
388
+ }
389
+
390
+ while (start < temp->allocEndAddress )
391
+ {
392
+ if (numberCount == CodeGenNumberChunk::MaxNumberCount)
393
+ {
394
+ auto newChunk = temp->GetChunkAllocator ()->AllocChunk ();
395
+ newChunk->next = chunk;
396
+ chunk = newChunk;
397
+ numberCount = 0 ;
398
+ }
399
+ chunk->numbers [numberCount++] = (Js::JavascriptNumber*)start;
400
+ start += temp->sizeCat ;
401
+ }
402
+
403
+ temp->GetChunkAllocator ()->FlushAllocations ();
404
+
405
+ temp = (XProcNumberPageSegmentImpl*)temp->nextSegment ;
406
+ }
407
+
408
+ AutoCriticalSection autoCS (&cs);
409
+ if (this ->segmentsList == nullptr )
410
+ {
411
+ this ->segmentsList = segmentImpl;
412
+ }
413
+ else
414
+ {
415
+ auto temp = segmentsList;
416
+ while (temp->nextSegment )
417
+ {
418
+ temp = (XProcNumberPageSegmentImpl*)temp->nextSegment ;
419
+ }
420
+ temp->nextSegment = segmentImpl;
421
+ }
422
+
423
+ return chunk;
424
+ }
425
+
426
+ void XProcNumberPageSegmentManager::GetFreeSegment (XProcNumberPageSegment& seg)
427
+ {
428
+ AutoCriticalSection autoCS (&cs);
429
+
430
+ memset (&seg, 0 , sizeof (seg));
431
+
432
+ if (segmentsList == nullptr )
433
+ {
434
+ new (&seg) XProcNumberPageSegmentImpl ();
435
+ return ;
436
+ }
437
+
438
+ auto temp = segmentsList;
439
+ auto prev = &segmentsList;
440
+ while (temp)
441
+ {
442
+ if (temp->allocEndAddress != temp->pageAddress + (int )(temp->pageCount *AutoSystemInfo::PageSize)) // not full
443
+ {
444
+ *prev = (XProcNumberPageSegmentImpl*)temp->nextSegment ;
445
+
446
+ // remove from the list
447
+ memcpy (&seg, temp, sizeof (seg));
448
+ midl_user_free (temp);
449
+ return ;
450
+ }
451
+ prev = (XProcNumberPageSegmentImpl**)&temp->nextSegment ;
452
+ temp = (XProcNumberPageSegmentImpl*)temp->nextSegment ;
453
+ }
454
+ }
455
+
456
+ void XProcNumberPageSegmentManager::Integrate ()
457
+ {
458
+ AutoCriticalSection autoCS (&cs);
459
+
460
+ auto temp = this ->segmentsList ;
461
+ auto prev = &this ->segmentsList ;
462
+ while (temp)
463
+ {
464
+ if (temp->pageSegment == 0 )
465
+ {
466
+ auto leafPageAllocator = recycler->GetRecyclerLeafPageAllocator ();
467
+ DListBase<PageSegment> segmentList;
468
+ temp->pageSegment = (intptr_t )leafPageAllocator->AllocPageSegment (segmentList, leafPageAllocator,
469
+ (void *)temp->pageAddress , temp->pageCount , temp->committedEnd / AutoSystemInfo::PageSize);
470
+ leafPageAllocator->IntegrateSegments (segmentList, 1 , temp->pageCount );
471
+
472
+ this ->integratedSegmentCount ++;
473
+ }
474
+
475
+ if (!temp->GetChunkAllocator ()->pendingIntegrationChunkBlock .Empty ())
476
+ {
477
+ Assert (sizeof (CodeGenNumberChunk) == sizeof (Js::JavascriptNumber));
478
+ size_t minIntegrateSize = temp->blockSize *CodeGenNumberChunk::MaxNumberCount;
479
+ for (; temp->pageAddress + temp->blockIntegratedSize + minIntegrateSize < (unsigned int )temp->allocEndAddress ;
480
+ temp->blockIntegratedSize += minIntegrateSize)
481
+ {
482
+ TRACK_ALLOC_INFO (recycler, Js::JavascriptNumber, Recycler, 0 , (size_t )-1 );
483
+
484
+ if (!recycler->IntegrateBlock <LeafBit>((char *)temp->pageAddress + temp->blockIntegratedSize , (PageSegment*)temp->pageSegment , temp->sizeCat , sizeof (Js::JavascriptNumber)))
485
+ {
486
+ Js::Throw::OutOfMemory ();
487
+ }
488
+ }
489
+ }
490
+
491
+ temp->GetChunkAllocator ()->Integrate ();
492
+
493
+ if (temp->blockIntegratedSize >= temp->pageCount *AutoSystemInfo::PageSize)
494
+ {
495
+ // all pages are integrated, don't need this segment any more
496
+ *prev = (XProcNumberPageSegmentImpl*)temp->nextSegment ;
497
+ HeapDelete (temp->GetChunkAllocator ());
498
+ midl_user_free (temp);
499
+ temp = *prev;
500
+ }
501
+ else
502
+ {
503
+ prev = (XProcNumberPageSegmentImpl**)&temp->nextSegment ;
504
+ temp = (XProcNumberPageSegmentImpl*)temp->nextSegment ;
505
+ }
506
+
507
+ }
508
+ }
509
+
510
+ XProcNumberPageSegmentManager::~XProcNumberPageSegmentManager ()
511
+ {
512
+ auto temp = segmentsList;
513
+ while (temp)
514
+ {
515
+ auto next = temp->nextSegment ;
516
+ if (temp->chunkAllocator )
517
+ {
518
+ HeapDelete ((CodeGenNumberThreadAllocator*)temp->chunkAllocator );
519
+ }
520
+ midl_user_free (temp);
521
+ temp = (XProcNumberPageSegmentImpl*)next;
522
+ }
523
+ }
0 commit comments