<commit_before>#include "process.h"

using namespace vm;

namespace {

unsigned
mangledSize(int8_t c)
{
  switch (c) {
  case '_':
  case ';':
  case '[':
    return 2;

  case '$':
    return 6;

  default:
    return 1;
  }
}

unsigned
mangle(int8_t c, char* dst)
{
  switch (c) {
  case '/':
    dst[0] = '_';
    return 1;

  case '_':
    dst[0] = '_';
    dst[1] = '1';
    return 2;

  case ';':
    dst[0] = '_';
    dst[1] = '2';
    return 2;

  case '[':
    dst[0] = '_';
    dst[1] = '3';
    return 2;

  case '$':
    memcpy(dst, "_00024", 6);
    return 6;

  default:
    dst[0] = c;    
    return 1;
  }
}

unsigned
jniNameLength(Thread* t, object method, bool decorate)
{
  unsigned size = 5;

  object className = ::className(t, methodClass(t, method));
  for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) {
    size += mangledSize(byteArrayBody(t, className, i));
  }

  ++ size;

  object methodName = ::methodName(t, method);
  for (unsigned i = 0; i < byteArrayLength(t, methodName) - 1; ++i) {
    size += mangledSize(byteArrayBody(t, methodName, i));
  }

  if (decorate) {
    size += 2;

    object methodSpec = ::methodSpec(t, method);
    for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1
           and byteArrayBody(t, methodSpec, i) != ')'; ++i)
    {
      size += mangledSize(byteArrayBody(t, methodSpec, i));
    }
  }

  return size;
}

void
makeJNIName(Thread* t, char* name, object method, bool decorate)
{
  memcpy(name, "Java_", 5);
  name += 5;

  object className = ::className(t, methodClass(t, method));
  for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) {
    name += mangle(byteArrayBody(t, className, i), name);
  }

  *(name++) = '_';

  object methodName = ::methodName(t, method);
  for (unsigned i = 0; i < byteArrayLength(t, methodName) - 1; ++i) {
    name += mangle(byteArrayBody(t, methodName, i), name);
  }
  
  if (decorate) {
    *(name++) = '_';
    *(name++) = '_';

    object methodSpec = ::methodSpec(t, method);
    for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1
           and byteArrayBody(t, methodSpec, i) != ')'; ++i)
    {
      name += mangle(byteArrayBody(t, methodSpec, i), name);
    }
  }

  *(name++) = 0;
}

void*
resolveNativeMethod(Thread* t, const char* undecorated, const char* decorated)
{
  for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) {
    void* p = lib->resolve(undecorated);
    if (p) {
      return p;
    } else {
      p = lib->resolve(decorated);
      if (p) {
        return p;
      }
    }
  }

  return 0;
}

} // namespace

namespace vm {

void*
resolveNativeMethod2(Thread* t, object method)
{
  unsigned undecoratedSize = jniNameLength(t, method, false);
  char undecorated[undecoratedSize + 5]; // extra 5 is for code below
  makeJNIName(t, undecorated, method, false);

  unsigned decoratedSize = jniNameLength(t, method, true);
  char decorated[decoratedSize + 5]; // extra 5 is for code below
  makeJNIName(t, decorated, method, true);

  void* p = ::resolveNativeMethod(t, undecorated, decorated);
  if (p) {
    return p;
  }

#ifdef __MINGW32__
  // on windows, we also try the _%s@%d variant, since the SWT
  // libraries use it.
  unsigned footprint = methodParameterFootprint(t, method) + 1;
  if (methodFlags(t, method) & ACC_STATIC) {
    ++ footprint;
  }

  snprintf(undecorated + undecoratedSize - 1, 5, "@%d",
           footprint * BytesPerWord);

  snprintf(decorated + decoratedSize - 1, 5, "@%d",
           footprint * BytesPerWord);
<commit_msg>fix recent regression in native method lookup on Windows<commit_after>#include "process.h"

using namespace vm;

namespace {

unsigned
mangledSize(int8_t c)
{
  switch (c) {
  case '_':
  case ';':
  case '[':
    return 2;

  case '$':
    return 6;

  default:
    return 1;
  }
}

unsigned
mangle(int8_t c, char* dst)
{
  switch (c) {
  case '/':
    dst[0] = '_';
    return 1;

  case '_':
    dst[0] = '_';
    dst[1] = '1';
    return 2;

  case ';':
    dst[0] = '_';
    dst[1] = '2';
    return 2;

  case '[':
    dst[0] = '_';
    dst[1] = '3';
    return 2;

  case '$':
    memcpy(dst, "_00024", 6);
    return 6;

  default:
    dst[0] = c;    
    return 1;
  }
}

unsigned
jniNameLength(Thread* t, object method, bool decorate)
{
  unsigned size = 5;

  object className = ::className(t, methodClass(t, method));
  for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) {
    size += mangledSize(byteArrayBody(t, className, i));
  }

  ++ size;

  object methodName = ::methodName(t, method);
  for (unsigned i = 0; i < byteArrayLength(t, methodName) - 1; ++i) {
    size += mangledSize(byteArrayBody(t, methodName, i));
  }

  if (decorate) {
    size += 2;

    object methodSpec = ::methodSpec(t, method);
    for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1
           and byteArrayBody(t, methodSpec, i) != ')'; ++i)
    {
      size += mangledSize(byteArrayBody(t, methodSpec, i));
    }
  }

  return size;
}

void
makeJNIName(Thread* t, char* name, object method, bool decorate)
{
  memcpy(name, "Java_", 5);
  name += 5;

  object className = ::className(t, methodClass(t, method));
  for (unsigned i = 0; i < byteArrayLength(t, className) - 1; ++i) {
    name += mangle(byteArrayBody(t, className, i), name);
  }

  *(name++) = '_';

  object methodName = ::methodName(t, method);
  for (unsigned i = 0; i < byteArrayLength(t, methodName) - 1; ++i) {
    name += mangle(byteArrayBody(t, methodName, i), name);
  }
  
  if (decorate) {
    *(name++) = '_';
    *(name++) = '_';

    object methodSpec = ::methodSpec(t, method);
    for (unsigned i = 1; i < byteArrayLength(t, methodSpec) - 1
           and byteArrayBody(t, methodSpec, i) != ')'; ++i)
    {
      name += mangle(byteArrayBody(t, methodSpec, i), name);
    }
  }

  *(name++) = 0;
}

void*
resolveNativeMethod(Thread* t, const char* undecorated, const char* decorated)
{
  for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) {
    void* p = lib->resolve(undecorated);
    if (p) {
      return p;
    } else {
      p = lib->resolve(decorated);
      if (p) {
        return p;
      }
    }
  }

  return 0;
}

} // namespace

namespace vm {

void*
resolveNativeMethod2(Thread* t, object method)
{
  unsigned undecoratedSize = jniNameLength(t, method, false);
  char undecorated[undecoratedSize + 1 + 6]; // extra 6 is for code below
  makeJNIName(t, undecorated + 1, method, false);

  unsigned decoratedSize = jniNameLength(t, method, true);
  char decorated[decoratedSize + 1 + 6]; // extra 6 is for code below
  makeJNIName(t, decorated + 1, method, true);

  void* p = ::resolveNativeMethod(t, undecorated + 1, decorated + 1);
  if (p) {
    return p;
  }

#ifdef __MINGW32__
  // on windows, we also try the _%s@%d variant, since the SWT
  // libraries use it.
  unsigned footprint = methodParameterFootprint(t, method) + 1;
  if (methodFlags(t, method) & ACC_STATIC) {
    ++ footprint;
  }

  *undecorated = '_';
  snprintf(undecorated + undecoratedSize + 1, 5, "@%d",
           footprint * BytesPerWord);

  *decorated = '_';
  snprintf(decorated + decoratedSize + 1, 5, "@%d",
           footprint * BytesPerWord);

{'fraction_non_alphanumeric': 0.1626648160999306, 'fraction_numerical': 0.01693268563497571, 'mean_word_length': 2.9355543418896777, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1496302', 'n_tokens_mistral': 2762, 'n_tokens_neox': 2599, 'n_words': 696}