src/hotspot/cpu/arm/vm_version_arm_64.cpp
author vlivanov
Fri, 26 May 2017 18:39:27 +0300
changeset 48557 2e867226b914
parent 47765 b7c7428eaab9
permissions -rw-r--r--
8174962: Better interface invocations Reviewed-by: jrose, coleenp, ahgross, acorn, iignatyev

/*
 * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#include "precompiled.hpp"
#include "jvm.h"
#include "asm/macroAssembler.inline.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/java.hpp"
#include "runtime/os.inline.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "vm_version_arm.hpp"
#include <sys/auxv.h>
#include <asm/hwcap.h>

#ifndef HWCAP_AES
#define HWCAP_AES 1 << 3
#endif

bool VM_Version::_is_initialized = false;
bool VM_Version::_has_simd = false;

extern "C" {
  typedef bool (*check_simd_t)();
}


#ifdef COMPILER2

#define __ _masm->

class VM_Version_StubGenerator: public StubCodeGenerator {
 public:

  VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}

  address generate_check_simd() {
    StubCodeMark mark(this, "VM_Version", "check_simd");
    address start = __ pc();

    __ vcnt(Stemp, Stemp);
    __ mov(R0, 1);
    __ ret(LR);

    return start;
  };
};

#undef __

#endif



extern "C" address check_simd_fault_instr;


void VM_Version::initialize() {
  ResourceMark rm;

  // Making this stub must be FIRST use of assembler
  const int stub_size = 128;
  BufferBlob* stub_blob = BufferBlob::create("get_cpu_info", stub_size);
  if (stub_blob == NULL) {
    vm_exit_during_initialization("Unable to allocate get_cpu_info stub");
  }

  if (UseFMA) {
    warning("FMA instructions are not available on this CPU");
    FLAG_SET_DEFAULT(UseFMA, false);
  }

  if (UseSHA) {
    warning("SHA instructions are not available on this CPU");
    FLAG_SET_DEFAULT(UseSHA, false);
  }

  if (UseSHA1Intrinsics) {
    warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU.");
    FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
  }

  if (UseSHA256Intrinsics) {
    warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU.");
    FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
  }

  if (UseSHA512Intrinsics) {
    warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU.");
    FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
  }

  if (UseCRC32Intrinsics) {
    if (!FLAG_IS_DEFAULT(UseCRC32Intrinsics))
      warning("CRC32 intrinsics are not available on this CPU");
    FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
  }

  if (UseCRC32CIntrinsics) {
    if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics))
      warning("CRC32C intrinsics are not available on this CPU");
    FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
  }

  if (UseAdler32Intrinsics) {
    warning("Adler32 intrinsics are not available on this CPU");
    FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
  }

  if (UseVectorizedMismatchIntrinsic) {
    warning("vectorizedMismatch intrinsic is not available on this CPU.");
    FLAG_SET_DEFAULT(UseVectorizedMismatchIntrinsic, false);
  }

  CodeBuffer c(stub_blob);

#ifdef COMPILER2
  VM_Version_StubGenerator g(&c);

  address check_simd_pc = g.generate_check_simd();
  if (check_simd_pc != NULL) {
    check_simd_t check_simd = CAST_TO_FN_PTR(check_simd_t, check_simd_pc);
    check_simd_fault_instr = (address)check_simd;
    _has_simd = check_simd();
  } else {
    assert(! _has_simd, "default _has_simd value must be 'false'");
  }
#endif

  unsigned long auxv = getauxval(AT_HWCAP);

  char buf[512];
  jio_snprintf(buf, sizeof(buf), "AArch64%s",
               ((auxv & HWCAP_AES) ? ", aes" : ""));

  _features_string = os::strdup(buf);

#ifdef COMPILER2
  if (auxv & HWCAP_AES) {
    if (FLAG_IS_DEFAULT(UseAES)) {
      FLAG_SET_DEFAULT(UseAES, true);
    }
    if (!UseAES) {
      if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
        warning("AES intrinsics require UseAES flag to be enabled. Intrinsics will be disabled.");
      }
      FLAG_SET_DEFAULT(UseAESIntrinsics, false);
    } else {
      if (FLAG_IS_DEFAULT(UseAESIntrinsics)) {
        FLAG_SET_DEFAULT(UseAESIntrinsics, true);
      }
    }
  } else
#endif
  if (UseAES || UseAESIntrinsics) {
    if (UseAES && !FLAG_IS_DEFAULT(UseAES)) {
      warning("AES instructions are not available on this CPU");
      FLAG_SET_DEFAULT(UseAES, false);
    }
    if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
      warning("AES intrinsics are not available on this CPU");
      FLAG_SET_DEFAULT(UseAESIntrinsics, false);
    }
  }

  if (UseAESCTRIntrinsics) {
    warning("AES/CTR intrinsics are not available on this CPU");
    FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false);
  }

  _supports_cx8 = true;
  _supports_atomic_getset4 = true;
  _supports_atomic_getadd4 = true;
  _supports_atomic_getset8 = true;
  _supports_atomic_getadd8 = true;

  // TODO-AARCH64 revise C2 flags

  if (has_simd()) {
    if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
      FLAG_SET_DEFAULT(UsePopCountInstruction, true);
    }
  }

  if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) {
    FLAG_SET_DEFAULT(AllocatePrefetchDistance, 128);
  }

#ifdef COMPILER2
  FLAG_SET_DEFAULT(UseFPUForSpilling, true);

  if (FLAG_IS_DEFAULT(MaxVectorSize)) {
    // FLAG_SET_DEFAULT(MaxVectorSize, has_simd() ? 16 : 8);
    // SIMD/NEON can use 16, but default is 8 because currently
    // larger than 8 will disable instruction scheduling
    FLAG_SET_DEFAULT(MaxVectorSize, 8);
  }

  if (MaxVectorSize > 16) {
    FLAG_SET_DEFAULT(MaxVectorSize, 8);
  }
#endif

  if (FLAG_IS_DEFAULT(Tier4CompileThreshold)) {
    Tier4CompileThreshold = 10000;
  }
  if (FLAG_IS_DEFAULT(Tier3InvocationThreshold)) {
    Tier3InvocationThreshold = 1000;
  }
  if (FLAG_IS_DEFAULT(Tier3CompileThreshold)) {
    Tier3CompileThreshold = 5000;
  }
  if (FLAG_IS_DEFAULT(Tier3MinInvocationThreshold)) {
    Tier3MinInvocationThreshold = 500;
  }

  FLAG_SET_DEFAULT(TypeProfileLevel, 0); // unsupported

  // This machine does not allow unaligned memory accesses
  if (UseUnalignedAccesses) {
    if (!FLAG_IS_DEFAULT(UseUnalignedAccesses))
      warning("Unaligned memory access is not available on this CPU");
    FLAG_SET_DEFAULT(UseUnalignedAccesses, false);
  }

  _is_initialized = true;
}

bool VM_Version::use_biased_locking() {
  // TODO-AARCH64 measure performance and revise

  // The cost of CAS on uniprocessor ARM v6 and later is low compared to the
  // overhead related to slightly longer Biased Locking execution path.
  // Testing shows no improvement when running with Biased Locking enabled
  // on an ARMv6 and higher uniprocessor systems.  The situation is different on
  // ARMv5 and MP systems.
  //
  // Therefore the Biased Locking is enabled on ARMv5 and ARM MP only.
  //
  return os::is_MP();
}