// src/objects/ordered-hash-table.cc

template <class Derived, int entrysize>
template <template <typename> typename HandleType>
  requires(std::is_convertible_v<HandleType<Derived>, DirectHandle<Derived>>)
HandleType<Derived>::MaybeType OrderedHashTable<Derived, entrysize>::Rehash(
    Isolate* isolate, HandleType<Derived> table, int new_capacity) {
  DCHECK(!table->IsObsolete());

	// 새 테이블을 new_capacity의 크기로 할당
  typename HandleType<Derived>::MaybeType new_table_candidate =
      Derived::Allocate(isolate, new_capacity,
                        HeapLayout::InYoungGeneration(*table)
                            ? AllocationType::kYoung
                            : AllocationType::kOld);
                            
                            
  DirectHandle<Derived> new_table;
  if (!new_table_candidate.ToHandle(&new_table)) {
    return new_table_candidate;
  }
  

  // 새 테이블 초기화
  int new_buckets = new_table->NumberOfBuckets();
  int new_entry = 0;
  int removed_holes_index = 0;

  DisallowGarbageCollection no_gc;
  
	// 기존 테이블의 엔트리를 모두 순회함
  for (InternalIndex old_entry : table->IterateEntries()) {

	  // 현재 엔트리의 인덱스와 키 값을 가져옴
    int old_entry_raw = old_entry.as_int();
    Tagged<Object> key = table->KeyAt(old_entry);
    
    // 만약 삭제된 엔트리라면 재배치하지 않고 건너뛴다.
    if (IsHashTableHole(key, isolate)) {
      table->SetRemovedIndexAt(removed_holes_index++, old_entry_raw);
      continue;
    }

    // 유효한 엔트리를 새 테이블에 복사한다.
    // 키로부터 해시값을 구하고, 새 용량에 맞게 계산함
    Tagged<Object> hash = Object::GetHash(key);
    int bucket = Smi::ToInt(hash) & (new_buckets - 1);
    
    // 체인 헤드를 갱신
    Tagged<Object> chain_entry = new_table->get(HashTableStartIndex() + bucket);
    new_table->set(HashTableStartIndex() + bucket, Smi::FromInt(new_entry));
    
    // 실제 엔트리 번호를 배열 인덱스로변환
    int new_index = new_table->EntryToIndexRaw(new_entry);
    int old_index = table->EntryToIndexRaw(old_entry_raw);
    
    // 엔트리 내부 구성요소를 복사
    for (int i = 0; i < entrysize; ++i) {
      Tagged<Object> value = table->get(old_index + i);
      new_table->set(new_index + i, value);
    }
    
    // 체인 포인터 연결
    new_table->set(new_index + kChainOffset, chain_entry);
    ++new_entry;
  }

  DCHECK_EQ(table->NumberOfDeletedElements(), removed_holes_index);
	
	// 요소 개수 동기화
  new_table->SetNumberOfElements(table->NumberOfElements());
  
  // 기존 테이블에 연결
  if (table->NumberOfBuckets() > 0) {
    // Don't try to modify the empty canonical table which lives in RO space.
    table->SetNextTable(*new_table);
  }

	// 결과 반환
  return new_table_candidate;
}