Updates refactoring of CPU feature detection

with fix that uses cpuid for Intel/Linux.

R=asiva@google.com

Review URL: https://codereview.chromium.org//136303012

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@32980 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
zra@google.com
2014-02-24 19:28:30 +00:00
parent 042138c3bc
commit fd366da1cf
37 changed files with 1443 additions and 344 deletions
+3 -93
View File
@@ -6,6 +6,7 @@
#if defined(TARGET_ARCH_ARM)
#include "vm/assembler.h"
#include "vm/cpu.h"
#include "vm/longjump.h"
#include "vm/runtime_entry.h"
#include "vm/simulator.h"
@@ -22,97 +23,6 @@ namespace dart {
DEFINE_FLAG(bool, print_stop_message, true, "Print stop message.");
DECLARE_FLAG(bool, inline_alloc);
bool CPUFeatures::integer_division_supported_ = false;
bool CPUFeatures::neon_supported_ = false;
#if defined(DEBUG)
bool CPUFeatures::initialized_ = false;
#endif
bool CPUFeatures::integer_division_supported() {
DEBUG_ASSERT(initialized_);
return integer_division_supported_;
}
bool CPUFeatures::neon_supported() {
DEBUG_ASSERT(initialized_);
return neon_supported_;
}
// If we are using the simulator, allow tests to enable/disable support for
// integer division.
#if defined(USING_SIMULATOR)
void CPUFeatures::set_integer_division_supported(bool supported) {
integer_division_supported_ = supported;
}
void CPUFeatures::set_neon_supported(bool supported) {
neon_supported_ = supported;
}
#endif
// Probe /proc/cpuinfo for features of the ARM processor.
#if !defined(USING_SIMULATOR)
static bool CPUInfoContainsString(const char* search_string) {
const char* file_name = "/proc/cpuinfo";
// This is written as a straight shot one pass parser
// and not using STL string and ifstream because,
// on Linux, it's reading from a (non-mmap-able)
// character special device.
FILE* f = NULL;
const char* what = search_string;
if (NULL == (f = fopen(file_name, "r")))
return false;
int k;
while (EOF != (k = fgetc(f))) {
if (k == *what) {
++what;
while ((*what != '\0') && (*what == fgetc(f))) {
++what;
}
if (*what == '\0') {
fclose(f);
return true;
} else {
what = search_string;
}
}
}
fclose(f);
// Did not find string in the proc file.
return false;
}
#endif
void CPUFeatures::InitOnce() {
#if defined(USING_SIMULATOR)
integer_division_supported_ = true;
neon_supported_ = true;
#else
ASSERT(CPUInfoContainsString("ARMv7")); // Implements ARMv7.
ASSERT(CPUInfoContainsString("vfp")); // Has floating point unit.
// Has integer division.
if (CPUInfoContainsString("QCT APQ8064")) {
// Special case for Qualcomm Krait CPUs in Nexus 4 and 7.
integer_division_supported_ = true;
} else {
integer_division_supported_ = CPUInfoContainsString("idiva");
}
neon_supported_ = CPUInfoContainsString("neon");
#endif // defined(USING_SIMULATOR)
#if defined(DEBUG)
initialized_ = true;
#endif
}
// Instruction encoding bits.
enum {
@@ -549,7 +459,7 @@ void Assembler::umlal(Register rd_lo, Register rd_hi,
void Assembler::EmitDivOp(Condition cond, int32_t opcode,
Register rd, Register rn, Register rm) {
ASSERT(CPUFeatures::integer_division_supported());
ASSERT(TargetCPUFeatures::integer_division_supported());
ASSERT(rd != kNoRegister);
ASSERT(rn != kNoRegister);
ASSERT(rm != kNoRegister);
@@ -2457,7 +2367,7 @@ void Assembler::TestImmediate(Register rn, int32_t imm, Condition cond) {
void Assembler::IntegerDivide(Register result, Register left, Register right,
DRegister tmpl, DRegister tmpr) {
ASSERT(tmpl != tmpr);
if (CPUFeatures::integer_division_supported()) {
if (TargetCPUFeatures::integer_division_supported()) {
sdiv(result, left, right);
} else {
SRegister stmpl = static_cast<SRegister>(2 * tmpl);
-20
View File
@@ -63,26 +63,6 @@ class Label : public ValueObject {
DISALLOW_COPY_AND_ASSIGN(Label);
};
class CPUFeatures : public AllStatic {
public:
static void InitOnce();
static bool double_truncate_round_supported() { return false; }
static bool integer_division_supported();
static bool neon_supported();
#if defined(USING_SIMULATOR)
static void set_integer_division_supported(bool supported);
static void set_neon_supported(bool supported);
#endif
private:
static bool integer_division_supported_;
static bool neon_supported_;
#if defined(DEBUG)
static bool initialized_;
#endif
};
// Encodes Addressing Mode 1 - Data-processing operands.
class ShifterOperand : public ValueObject {
public:
+61 -60
View File
@@ -6,6 +6,7 @@
#if defined(TARGET_ARCH_ARM)
#include "vm/assembler.h"
#include "vm/cpu.h"
#include "vm/os.h"
#include "vm/unit_test.h"
#include "vm/virtual_memory.h"
@@ -1457,7 +1458,7 @@ ASSEMBLER_TEST_RUN(VstmsVldms_off, test) {
ASSEMBLER_TEST_GENERATE(Udiv, assembler) {
if (CPUFeatures::integer_division_supported()) {
if (TargetCPUFeatures::integer_division_supported()) {
__ mov(R0, ShifterOperand(27));
__ mov(R1, ShifterOperand(9));
__ udiv(R2, R0, R1);
@@ -1477,7 +1478,7 @@ ASSEMBLER_TEST_RUN(Udiv, test) {
ASSEMBLER_TEST_GENERATE(Sdiv, assembler) {
if (CPUFeatures::integer_division_supported()) {
if (TargetCPUFeatures::integer_division_supported()) {
__ mov(R0, ShifterOperand(27));
__ LoadImmediate(R1, -9);
__ sdiv(R2, R0, R1);
@@ -1497,7 +1498,7 @@ ASSEMBLER_TEST_RUN(Sdiv, test) {
ASSEMBLER_TEST_GENERATE(Udiv_zero, assembler) {
if (CPUFeatures::integer_division_supported()) {
if (TargetCPUFeatures::integer_division_supported()) {
__ mov(R0, ShifterOperand(27));
__ mov(R1, ShifterOperand(0));
__ udiv(R2, R0, R1);
@@ -1517,7 +1518,7 @@ ASSEMBLER_TEST_RUN(Udiv_zero, test) {
ASSEMBLER_TEST_GENERATE(Sdiv_zero, assembler) {
if (CPUFeatures::integer_division_supported()) {
if (TargetCPUFeatures::integer_division_supported()) {
__ mov(R0, ShifterOperand(27));
__ mov(R1, ShifterOperand(0));
__ udiv(R2, R0, R1);
@@ -1537,7 +1538,7 @@ ASSEMBLER_TEST_RUN(Sdiv_zero, test) {
ASSEMBLER_TEST_GENERATE(Udiv_corner, assembler) {
if (CPUFeatures::integer_division_supported()) {
if (TargetCPUFeatures::integer_division_supported()) {
__ LoadImmediate(R0, 0x80000000);
__ LoadImmediate(R1, 0xffffffff);
__ udiv(R2, R0, R1);
@@ -1557,7 +1558,7 @@ ASSEMBLER_TEST_RUN(Udiv_corner, test) {
ASSEMBLER_TEST_GENERATE(Sdiv_corner, assembler) {
if (CPUFeatures::integer_division_supported()) {
if (TargetCPUFeatures::integer_division_supported()) {
__ LoadImmediate(R0, 0x80000000);
__ LoadImmediate(R1, 0xffffffff);
__ sdiv(R2, R0, R1);
@@ -1579,12 +1580,12 @@ ASSEMBLER_TEST_RUN(Sdiv_corner, test) {
ASSEMBLER_TEST_GENERATE(IntDiv_supported, assembler) {
#if defined(USING_SIMULATOR)
bool orig = CPUFeatures::integer_division_supported();
CPUFeatures::set_integer_division_supported(true);
bool orig = TargetCPUFeatures::integer_division_supported();
HostCPUFeatures::set_integer_division_supported(true);
__ mov(R0, ShifterOperand(27));
__ mov(R1, ShifterOperand(9));
__ IntegerDivide(R0, R0, R1, D0, D1);
CPUFeatures::set_integer_division_supported(orig);
HostCPUFeatures::set_integer_division_supported(orig);
__ bx(LR);
#else
__ mov(R0, ShifterOperand(27));
@@ -1604,12 +1605,12 @@ ASSEMBLER_TEST_RUN(IntDiv_supported, test) {
ASSEMBLER_TEST_GENERATE(IntDiv_unsupported, assembler) {
#if defined(USING_SIMULATOR)
bool orig = CPUFeatures::integer_division_supported();
CPUFeatures::set_integer_division_supported(false);
bool orig = TargetCPUFeatures::integer_division_supported();
HostCPUFeatures::set_integer_division_supported(false);
__ mov(R0, ShifterOperand(27));
__ mov(R1, ShifterOperand(9));
__ IntegerDivide(R0, R0, R1, D0, D1);
CPUFeatures::set_integer_division_supported(orig);
HostCPUFeatures::set_integer_division_supported(orig);
__ bx(LR);
#else
__ mov(R0, ShifterOperand(27));
@@ -1644,7 +1645,7 @@ ASSEMBLER_TEST_RUN(Muls, test) {
ASSEMBLER_TEST_GENERATE(Vaddqi8, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -1688,7 +1689,7 @@ ASSEMBLER_TEST_RUN(Vaddqi8, test) {
ASSEMBLER_TEST_GENERATE(Vaddqi16, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -1732,7 +1733,7 @@ ASSEMBLER_TEST_RUN(Vaddqi16, test) {
ASSEMBLER_TEST_GENERATE(Vaddqi32, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -1776,7 +1777,7 @@ ASSEMBLER_TEST_RUN(Vaddqi32, test) {
ASSEMBLER_TEST_GENERATE(Vaddqi64, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -1808,7 +1809,7 @@ ASSEMBLER_TEST_RUN(Vaddqi64, test) {
ASSEMBLER_TEST_GENERATE(Vsubqi8, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -1852,7 +1853,7 @@ ASSEMBLER_TEST_RUN(Vsubqi8, test) {
ASSEMBLER_TEST_GENERATE(Vsubqi16, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -1896,7 +1897,7 @@ ASSEMBLER_TEST_RUN(Vsubqi16, test) {
ASSEMBLER_TEST_GENERATE(Vsubqi32, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -1940,7 +1941,7 @@ ASSEMBLER_TEST_RUN(Vsubqi32, test) {
ASSEMBLER_TEST_GENERATE(Vsubqi64, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -1972,7 +1973,7 @@ ASSEMBLER_TEST_RUN(Vsubqi64, test) {
ASSEMBLER_TEST_GENERATE(Vmulqi8, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -2016,7 +2017,7 @@ ASSEMBLER_TEST_RUN(Vmulqi8, test) {
ASSEMBLER_TEST_GENERATE(Vmulqi16, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -2060,7 +2061,7 @@ ASSEMBLER_TEST_RUN(Vmulqi16, test) {
ASSEMBLER_TEST_GENERATE(Vmulqi32, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -2104,7 +2105,7 @@ ASSEMBLER_TEST_RUN(Vmulqi32, test) {
ASSEMBLER_TEST_GENERATE(Vaddqs, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S0, 1.0);
__ LoadSImmediate(S1, 2.0);
__ LoadSImmediate(S2, 3.0);
@@ -2139,7 +2140,7 @@ ASSEMBLER_TEST_RUN(Vaddqs, test) {
ASSEMBLER_TEST_GENERATE(Vsubqs, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S0, 1.0);
__ LoadSImmediate(S1, 2.0);
__ LoadSImmediate(S2, 3.0);
@@ -2174,7 +2175,7 @@ ASSEMBLER_TEST_RUN(Vsubqs, test) {
ASSEMBLER_TEST_GENERATE(Vmulqs, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S0, 1.0);
__ LoadSImmediate(S1, 2.0);
__ LoadSImmediate(S2, 3.0);
@@ -2209,7 +2210,7 @@ ASSEMBLER_TEST_RUN(Vmulqs, test) {
ASSEMBLER_TEST_GENERATE(VtblX, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
// Index.
__ LoadImmediate(R0, 0x03020100);
__ vmovsr(S0, R0);
@@ -2252,7 +2253,7 @@ ASSEMBLER_TEST_RUN(VtblX, test) {
ASSEMBLER_TEST_GENERATE(VtblY, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
// Index.
__ LoadImmediate(R0, 0x07060504);
__ vmovsr(S0, R0);
@@ -2295,7 +2296,7 @@ ASSEMBLER_TEST_RUN(VtblY, test) {
ASSEMBLER_TEST_GENERATE(VtblZ, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
// Index.
__ LoadImmediate(R0, 0x0b0a0908);
__ vmovsr(S0, R0);
@@ -2338,7 +2339,7 @@ ASSEMBLER_TEST_RUN(VtblZ, test) {
ASSEMBLER_TEST_GENERATE(VtblW, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
// Index.
__ LoadImmediate(R0, 0x0f0e0d0c);
__ vmovsr(S0, R0);
@@ -2381,7 +2382,7 @@ ASSEMBLER_TEST_RUN(VtblW, test) {
ASSEMBLER_TEST_GENERATE(Veorq, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
// Q0
__ LoadImmediate(R0, 0xaaaaaaab);
__ vmovsr(S0, R0);
@@ -2423,7 +2424,7 @@ ASSEMBLER_TEST_RUN(Veorq, test) {
ASSEMBLER_TEST_GENERATE(Vornq, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
// Q0
__ LoadImmediate(R0, 0xfffffff0);
__ vmovsr(S0, R0);
@@ -2465,7 +2466,7 @@ ASSEMBLER_TEST_RUN(Vornq, test) {
ASSEMBLER_TEST_GENERATE(Vorrq, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
// Q0
__ LoadImmediate(R0, 0xaaaaaaaa);
__ vmovsr(S0, R0);
@@ -2507,7 +2508,7 @@ ASSEMBLER_TEST_RUN(Vorrq, test) {
ASSEMBLER_TEST_GENERATE(Vandq, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
// Q0
__ LoadImmediate(R0, 0xaaaaaaab);
__ vmovsr(S0, R0);
@@ -2549,7 +2550,7 @@ ASSEMBLER_TEST_RUN(Vandq, test) {
ASSEMBLER_TEST_GENERATE(Vmovq, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
// Q0
__ LoadSImmediate(S0, 1.0);
__ vmovs(S1, S0);
@@ -2587,7 +2588,7 @@ ASSEMBLER_TEST_RUN(Vmovq, test) {
ASSEMBLER_TEST_GENERATE(Vdupb, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadImmediate(R0, 0x00000000);
__ LoadImmediate(R1, 0x00ff0000);
__ vmovsr(S4, R0);
@@ -2620,7 +2621,7 @@ ASSEMBLER_TEST_RUN(Vdupb, test) {
ASSEMBLER_TEST_GENERATE(Vduph, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadImmediate(R0, 0xffff0000);
__ LoadImmediate(R1, 0x00000000);
__ vmovsr(S4, R0);
@@ -2653,7 +2654,7 @@ ASSEMBLER_TEST_RUN(Vduph, test) {
ASSEMBLER_TEST_GENERATE(Vdupw, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadImmediate(R0, 0x00000000);
__ LoadImmediate(R1, 0xffffffff);
__ vmovsr(S4, R0);
@@ -2686,7 +2687,7 @@ ASSEMBLER_TEST_RUN(Vdupw, test) {
ASSEMBLER_TEST_GENERATE(Vzipqw, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S0, 0.0);
__ LoadSImmediate(S1, 1.0);
__ LoadSImmediate(S2, 2.0);
@@ -2720,7 +2721,7 @@ ASSEMBLER_TEST_RUN(Vzipqw, test) {
ASSEMBLER_TEST_GENERATE(Vceqqi32, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -2764,7 +2765,7 @@ ASSEMBLER_TEST_RUN(Vceqqi32, test) {
ASSEMBLER_TEST_GENERATE(Vceqqs, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S0, 1.0);
__ LoadSImmediate(S1, 2.0);
__ LoadSImmediate(S2, 3.0);
@@ -2800,7 +2801,7 @@ ASSEMBLER_TEST_RUN(Vceqqs, test) {
ASSEMBLER_TEST_GENERATE(Vcgeqi32, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -2844,7 +2845,7 @@ ASSEMBLER_TEST_RUN(Vcgeqi32, test) {
ASSEMBLER_TEST_GENERATE(Vcugeqi32, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -2888,7 +2889,7 @@ ASSEMBLER_TEST_RUN(Vcugeqi32, test) {
ASSEMBLER_TEST_GENERATE(Vcgeqs, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S0, 1.0);
__ LoadSImmediate(S1, 2.0);
__ LoadSImmediate(S2, 3.0);
@@ -2924,7 +2925,7 @@ ASSEMBLER_TEST_RUN(Vcgeqs, test) {
ASSEMBLER_TEST_GENERATE(Vcgtqi32, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -2968,7 +2969,7 @@ ASSEMBLER_TEST_RUN(Vcgtqi32, test) {
ASSEMBLER_TEST_GENERATE(Vcugtqi32, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ mov(R0, ShifterOperand(1));
__ vmovsr(S0, R0);
__ mov(R0, ShifterOperand(2));
@@ -3012,7 +3013,7 @@ ASSEMBLER_TEST_RUN(Vcugtqi32, test) {
ASSEMBLER_TEST_GENERATE(Vcgtqs, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S0, 1.0);
__ LoadSImmediate(S1, 2.0);
__ LoadSImmediate(S2, 3.0);
@@ -3048,7 +3049,7 @@ ASSEMBLER_TEST_RUN(Vcgtqs, test) {
ASSEMBLER_TEST_GENERATE(Vminqs, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S0, 1.0);
__ LoadSImmediate(S1, 2.0);
__ LoadSImmediate(S2, 3.0);
@@ -3083,7 +3084,7 @@ ASSEMBLER_TEST_RUN(Vminqs, test) {
ASSEMBLER_TEST_GENERATE(Vmaxqs, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S0, 1.0);
__ LoadSImmediate(S1, 2.0);
__ LoadSImmediate(S2, 3.0);
@@ -3153,7 +3154,7 @@ static float arm_recip_estimate(float a) {
ASSEMBLER_TEST_GENERATE(Vrecpeqs, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S4, 147.0);
__ vmovs(S5, S4);
__ vmovs(S6, S4);
@@ -3178,7 +3179,7 @@ ASSEMBLER_TEST_RUN(Vrecpeqs, test) {
ASSEMBLER_TEST_GENERATE(Vrecpsqs, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S4, 5.0);
__ LoadSImmediate(S5, 2.0);
__ LoadSImmediate(S6, 3.0);
@@ -3208,7 +3209,7 @@ ASSEMBLER_TEST_RUN(Vrecpsqs, test) {
ASSEMBLER_TEST_GENERATE(Reciprocal, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S4, 147000.0);
__ vmovs(S5, S4);
__ vmovs(S6, S4);
@@ -3290,7 +3291,7 @@ static float arm_reciprocal_sqrt_estimate(float a) {
ASSEMBLER_TEST_GENERATE(Vrsqrteqs, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S4, 147.0);
__ vmovs(S5, S4);
__ vmovs(S6, S4);
@@ -3315,7 +3316,7 @@ ASSEMBLER_TEST_RUN(Vrsqrteqs, test) {
ASSEMBLER_TEST_GENERATE(Vrsqrtsqs, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S4, 5.0);
__ LoadSImmediate(S5, 2.0);
__ LoadSImmediate(S6, 3.0);
@@ -3345,7 +3346,7 @@ ASSEMBLER_TEST_RUN(Vrsqrtsqs, test) {
ASSEMBLER_TEST_GENERATE(ReciprocalSqrt, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S4, 147000.0);
__ vmovs(S5, S4);
__ vmovs(S6, S4);
@@ -3380,7 +3381,7 @@ ASSEMBLER_TEST_RUN(ReciprocalSqrt, test) {
ASSEMBLER_TEST_GENERATE(SIMDSqrt, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S4, 147000.0);
__ vmovs(S5, S4);
__ vmovs(S6, S4);
@@ -3425,7 +3426,7 @@ ASSEMBLER_TEST_RUN(SIMDSqrt, test) {
ASSEMBLER_TEST_GENERATE(SIMDSqrt2, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S4, 1.0);
__ LoadSImmediate(S5, 4.0);
__ LoadSImmediate(S6, 9.0);
@@ -3474,7 +3475,7 @@ ASSEMBLER_TEST_RUN(SIMDSqrt2, test) {
ASSEMBLER_TEST_GENERATE(SIMDDiv, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S4, 1.0);
__ LoadSImmediate(S5, 4.0);
__ LoadSImmediate(S6, 9.0);
@@ -3515,7 +3516,7 @@ ASSEMBLER_TEST_RUN(SIMDDiv, test) {
ASSEMBLER_TEST_GENERATE(Vabsqs, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S4, 1.0);
__ LoadSImmediate(S5, -1.0);
__ LoadSImmediate(S6, 1.0);
@@ -3544,7 +3545,7 @@ ASSEMBLER_TEST_RUN(Vabsqs, test) {
ASSEMBLER_TEST_GENERATE(Vnegqs, assembler) {
if (CPUFeatures::neon_supported()) {
if (TargetCPUFeatures::neon_supported()) {
__ LoadSImmediate(S4, 1.0);
__ LoadSImmediate(S5, -2.0);
__ LoadSImmediate(S6, 1.0);
+5 -57
View File
@@ -7,6 +7,7 @@
#include "vm/assembler.h"
#include "vm/code_generator.h"
#include "vm/cpu.h"
#include "vm/heap.h"
#include "vm/memory_region.h"
#include "vm/runtime_entry.h"
@@ -16,62 +17,9 @@
namespace dart {
DEFINE_FLAG(bool, print_stop_message, true, "Print stop message.");
DEFINE_FLAG(bool, use_sse41, true, "Use SSE 4.1 if available");
DECLARE_FLAG(bool, inline_alloc);
bool CPUFeatures::sse2_supported_ = false;
bool CPUFeatures::sse4_1_supported_ = false;
#ifdef DEBUG
bool CPUFeatures::initialized_ = false;
#endif
bool CPUFeatures::sse2_supported() {
DEBUG_ASSERT(initialized_);
return sse2_supported_;
}
bool CPUFeatures::sse4_1_supported() {
DEBUG_ASSERT(initialized_);
return sse4_1_supported_ && FLAG_use_sse41;
}
#define __ assembler.
void CPUFeatures::InitOnce() {
Assembler assembler;
__ pushl(EBP);
__ pushl(EBX);
__ movl(EBP, ESP);
// Get feature information in ECX:EDX and return it in EDX:EAX.
__ movl(EAX, Immediate(1));
__ cpuid();
__ movl(EAX, EDX);
__ movl(EDX, ECX);
__ movl(ESP, EBP);
__ popl(EBX);
__ popl(EBP);
__ ret();
const Code& code =
Code::Handle(Code::FinalizeCode("DetectCPUFeatures", &assembler));
Instructions& instructions = Instructions::Handle(code.instructions());
typedef uint64_t (*DetectCPUFeatures)();
uint64_t features =
reinterpret_cast<DetectCPUFeatures>(instructions.EntryPoint())();
sse2_supported_ = (features & kSSE2BitMask) != 0;
sse4_1_supported_ = (features & kSSE4_1BitMask) != 0;
#ifdef DEBUG
initialized_ = true;
#endif
}
#undef __
class DirectCallRelocation : public AssemblerFixup {
public:
void Process(const MemoryRegion& region, intptr_t position) {
@@ -1222,7 +1170,7 @@ void Assembler::andpd(XmmRegister dst, XmmRegister src) {
void Assembler::pextrd(Register dst, XmmRegister src, const Immediate& imm) {
ASSERT(CPUFeatures::sse4_1_supported());
ASSERT(TargetCPUFeatures::sse4_1_supported());
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0x66);
EmitUint8(0x0F);
@@ -1235,7 +1183,7 @@ void Assembler::pextrd(Register dst, XmmRegister src, const Immediate& imm) {
void Assembler::pmovsxdq(XmmRegister dst, XmmRegister src) {
ASSERT(CPUFeatures::sse4_1_supported());
ASSERT(TargetCPUFeatures::sse4_1_supported());
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0x66);
EmitUint8(0x0F);
@@ -1246,7 +1194,7 @@ void Assembler::pmovsxdq(XmmRegister dst, XmmRegister src) {
void Assembler::pcmpeqq(XmmRegister dst, XmmRegister src) {
ASSERT(CPUFeatures::sse4_1_supported());
ASSERT(TargetCPUFeatures::sse4_1_supported());
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0x66);
EmitUint8(0x0F);
@@ -1266,7 +1214,7 @@ void Assembler::pxor(XmmRegister dst, XmmRegister src) {
void Assembler::roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode) {
ASSERT(CPUFeatures::sse4_1_supported());
ASSERT(TargetCPUFeatures::sse4_1_supported());
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0x66);
EmitUint8(0x0F);
-19
View File
@@ -286,25 +286,6 @@ class Label : public ValueObject {
};
class CPUFeatures : public AllStatic {
public:
static void InitOnce();
static bool sse2_supported();
static bool sse4_1_supported();
static bool double_truncate_round_supported() { return sse4_1_supported(); }
private:
static const uint64_t kSSE2BitMask = static_cast<uint64_t>(1) << 26;
static const uint64_t kSSE4_1BitMask = static_cast<uint64_t>(1) << 51;
static bool sse2_supported_;
static bool sse4_1_supported_;
#ifdef DEBUG
static bool initialized_;
#endif
};
class Assembler : public ValueObject {
public:
explicit Assembler(bool use_far_branches = false)
+9 -8
View File
@@ -6,6 +6,7 @@
#if defined(TARGET_ARCH_IA32)
#include "vm/assembler.h"
#include "vm/cpu.h"
#include "vm/os.h"
#include "vm/unit_test.h"
#include "vm/virtual_memory.h"
@@ -2808,7 +2809,7 @@ ASSEMBLER_TEST_RUN(Orpd, test) {
ASSEMBLER_TEST_GENERATE(Pextrd0, assembler) {
if (CPUFeatures::sse4_1_supported()) {
if (TargetCPUFeatures::sse4_1_supported()) {
__ movsd(XMM0, Address(ESP, kWordSize));
__ pextrd(EAX, XMM0, Immediate(0));
}
@@ -2817,7 +2818,7 @@ ASSEMBLER_TEST_GENERATE(Pextrd0, assembler) {
ASSEMBLER_TEST_RUN(Pextrd0, test) {
if (CPUFeatures::sse4_1_supported()) {
if (TargetCPUFeatures::sse4_1_supported()) {
typedef int32_t (*PextrdCode0)(double d);
int32_t res = reinterpret_cast<PextrdCode0>(test->entry())(123456789);
EXPECT_EQ(0x54000000, res);
@@ -2826,7 +2827,7 @@ ASSEMBLER_TEST_RUN(Pextrd0, test) {
ASSEMBLER_TEST_GENERATE(Pextrd1, assembler) {
if (CPUFeatures::sse4_1_supported()) {
if (TargetCPUFeatures::sse4_1_supported()) {
__ movsd(XMM0, Address(ESP, kWordSize));
__ pextrd(EAX, XMM0, Immediate(1));
}
@@ -2835,7 +2836,7 @@ ASSEMBLER_TEST_GENERATE(Pextrd1, assembler) {
ASSEMBLER_TEST_RUN(Pextrd1, test) {
if (CPUFeatures::sse4_1_supported()) {
if (TargetCPUFeatures::sse4_1_supported()) {
typedef int32_t (*PextrdCode1)(double d);
int32_t res = reinterpret_cast<PextrdCode1>(test->entry())(123456789);
EXPECT_EQ(0x419d6f34, res);
@@ -2844,7 +2845,7 @@ ASSEMBLER_TEST_RUN(Pextrd1, test) {
ASSEMBLER_TEST_GENERATE(Pmovsxdq, assembler) {
if (CPUFeatures::sse4_1_supported()) {
if (TargetCPUFeatures::sse4_1_supported()) {
__ movsd(XMM0, Address(ESP, kWordSize));
__ pmovsxdq(XMM0, XMM0);
__ pextrd(EAX, XMM0, Immediate(1));
@@ -2854,7 +2855,7 @@ ASSEMBLER_TEST_GENERATE(Pmovsxdq, assembler) {
ASSEMBLER_TEST_RUN(Pmovsxdq, test) {
if (CPUFeatures::sse4_1_supported()) {
if (TargetCPUFeatures::sse4_1_supported()) {
typedef int32_t (*PmovsxdqCode)(double d);
int32_t res = reinterpret_cast<PmovsxdqCode>(test->entry())(123456789);
EXPECT_EQ(0, res);
@@ -2863,7 +2864,7 @@ ASSEMBLER_TEST_RUN(Pmovsxdq, test) {
ASSEMBLER_TEST_GENERATE(Pcmpeqq, assembler) {
if (CPUFeatures::sse4_1_supported()) {
if (TargetCPUFeatures::sse4_1_supported()) {
__ movsd(XMM0, Address(ESP, kWordSize));
__ xorpd(XMM1, XMM1);
__ pcmpeqq(XMM0, XMM1);
@@ -2874,7 +2875,7 @@ ASSEMBLER_TEST_GENERATE(Pcmpeqq, assembler) {
ASSEMBLER_TEST_RUN(Pcmpeqq, test) {
if (CPUFeatures::sse4_1_supported()) {
if (TargetCPUFeatures::sse4_1_supported()) {
typedef int32_t (*PcmpeqqCode)(double d);
int32_t res = reinterpret_cast<PcmpeqqCode>(test->entry())(0);
EXPECT_EQ(-1, res);
-9
View File
@@ -135,15 +135,6 @@ class Label : public ValueObject {
};
class CPUFeatures : public AllStatic {
public:
static void InitOnce() { }
static bool double_truncate_round_supported() {
return false;
}
};
class Assembler : public ValueObject {
public:
explicit Assembler(bool use_far_branches = false)
+1
View File
@@ -6,6 +6,7 @@
#if defined(TARGET_ARCH_MIPS)
#include "vm/assembler.h"
#include "vm/cpu.h"
#include "vm/os.h"
#include "vm/unit_test.h"
#include "vm/virtual_memory.h"
+1 -47
View File
@@ -6,6 +6,7 @@
#if defined(TARGET_ARCH_X64)
#include "vm/assembler.h"
#include "vm/cpu.h"
#include "vm/heap.h"
#include "vm/memory_region.h"
#include "vm/runtime_entry.h"
@@ -15,56 +16,9 @@
namespace dart {
DEFINE_FLAG(bool, print_stop_message, true, "Print stop message.");
DEFINE_FLAG(bool, use_sse41, true, "Use SSE 4.1 if available");
DECLARE_FLAG(bool, inline_alloc);
bool CPUFeatures::sse4_1_supported_ = false;
#ifdef DEBUG
bool CPUFeatures::initialized_ = false;
#endif
bool CPUFeatures::sse4_1_supported() {
DEBUG_ASSERT(initialized_);
return sse4_1_supported_ && FLAG_use_sse41;
}
#define __ assembler.
void CPUFeatures::InitOnce() {
Assembler assembler;
__ pushq(RBP);
__ pushq(RBX);
__ movq(RBP, RSP);
// Get feature information in ECX:EDX and return it in RAX.
// Note that cpuid operates the same in 64-bit and 32-bit mode.
__ movq(RAX, Immediate(1));
__ cpuid();
__ movl(RAX, RCX); // Zero extended.
__ shlq(RAX, Immediate(32));
__ movl(RCX, RDX); // Zero extended.
__ orq(RAX, RCX);
__ movq(RSP, RBP);
__ popq(RBX);
__ popq(RBP);
__ ret();
const Code& code =
Code::Handle(Code::FinalizeCode("DetectCPUFeatures", &assembler));
Instructions& instructions = Instructions::Handle(code.instructions());
typedef uint64_t (*DetectCPUFeatures)();
uint64_t features =
reinterpret_cast<DetectCPUFeatures>(instructions.EntryPoint())();
sse4_1_supported_ = (features & kSSE4_1BitMask) != 0;
#ifdef DEBUG
initialized_ = true;
#endif
}
#undef __
Assembler::Assembler(bool use_far_branches)
: buffer_(),
object_pool_(GrowableObjectArray::Handle()),
-18
View File
@@ -317,24 +317,6 @@ class Label : public ValueObject {
};
class CPUFeatures : public AllStatic {
public:
static void InitOnce();
// x64 always has at least SSE2.
static bool sse2_supported() { return true; }
static bool sse4_1_supported();
static bool double_truncate_round_supported() { return sse4_1_supported(); }
private:
static const uint64_t kSSE4_1BitMask = static_cast<uint64_t>(1) << 51;
static bool sse4_1_supported_;
#ifdef DEBUG
static bool initialized_;
#endif
};
class Assembler : public ValueObject {
public:
explicit Assembler(bool use_far_branches = false);
+13
View File
@@ -5,6 +5,7 @@
#ifndef VM_CPU_H_
#define VM_CPU_H_
#include "vm/globals.h"
#include "vm/allocation.h"
namespace dart {
@@ -22,4 +23,16 @@ class CPU : public AllStatic {
} // namespace dart
#if defined(TARGET_ARCH_IA32)
#include "vm/cpu_ia32.h"
#elif defined(TARGET_ARCH_X64)
#include "vm/cpu_x64.h"
#elif defined(TARGET_ARCH_ARM)
#include "vm/cpu_arm.h"
#elif defined(TARGET_ARCH_MIPS)
#include "vm/cpu_mips.h"
#else
#error Unknown architecture.
#endif
#endif // VM_CPU_H_
+73 -2
View File
@@ -6,13 +6,15 @@
#if defined(TARGET_ARCH_ARM)
#include "vm/cpu.h"
#include "vm/cpuinfo.h"
#include "vm/simulator.h"
#if defined(HOST_ARCH_ARM)
#include <sys/syscall.h> /* NOLINT */
#include <unistd.h> /* NOLINT */
#endif
#include "vm/cpu.h"
namespace dart {
void CPU::FlushICache(uword start, uword size) {
@@ -48,6 +50,75 @@ const char* CPU::Id() {
"arm";
}
bool HostCPUFeatures::integer_division_supported_ = false;
bool HostCPUFeatures::neon_supported_ = false;
const char* HostCPUFeatures::hardware_ = NULL;
#if defined(DEBUG)
bool HostCPUFeatures::initialized_ = false;
#endif
#if defined(HOST_ARCH_ARM)
void HostCPUFeatures::InitOnce() {
CpuInfo::InitOnce();
hardware_ = CpuInfo::GetCpuModel();
// Implements ARMv7.
ASSERT(CpuInfo::FieldContains(kCpuInfoProcessor, "ARMv7"));
// Has floating point unit.
ASSERT(CpuInfo::FieldContains(kCpuInfoFeatures, "vfp"));
// Has integer division.
bool is_krait = CpuInfo::FieldContains(kCpuInfoModel, "QCT APQ8064");
if (is_krait) {
// Special case for Qualcomm Krait CPUs in Nexus 4 and 7.
integer_division_supported_ = true;
} else {
integer_division_supported_ =
CpuInfo::FieldContains(kCpuInfoFeatures, "idiva");
}
neon_supported_ = CpuInfo::FieldContains(kCpuInfoFeatures, "neon");
#if defined(DEBUG)
initialized_ = true;
#endif
}
void HostCPUFeatures::Cleanup() {
DEBUG_ASSERT(initialized_);
#if defined(DEBUG)
initialized_ = false;
#endif
ASSERT(hardware_ != NULL);
delete[] hardware_;
hardware_ = NULL;
CpuInfo::Cleanup();
}
#else
void HostCPUFeatures::InitOnce() {
CpuInfo::InitOnce();
hardware_ = CpuInfo::GetCpuModel();
integer_division_supported_ = true;
neon_supported_ = true;
#if defined(DEBUG)
initialized_ = true;
#endif
}
void HostCPUFeatures::Cleanup() {
DEBUG_ASSERT(initialized_);
#if defined(DEBUG)
initialized_ = false;
#endif
ASSERT(hardware_ != NULL);
delete[] hardware_;
hardware_ = NULL;
CpuInfo::Cleanup();
}
#endif // defined(HOST_ARCH_ARM)
} // namespace dart
#endif // defined TARGET_ARCH_ARM
+82
View File
@@ -0,0 +1,82 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_CPU_ARM_H_
#define VM_CPU_ARM_H_
#include "vm/allocation.h"
#include "vm/simulator.h"
namespace dart {
// TargetCPUFeatures gives CPU features for the architecture that we are
// generating code for. HostCPUFeatures gives the CPU features for the
// architecture that we are actually running on. When the architectures
// are the same, TargetCPUFeatures will query HostCPUFeatures. When they are
// different (i.e. we are running in a simulator), HostCPUFeatures will
// additionally mock the options needed for the target architecture so that
// they may be altered for testing.
class HostCPUFeatures: public AllStatic {
public:
static void InitOnce();
static void Cleanup();
static const char* hardware() {
DEBUG_ASSERT(initialized_);
return hardware_;
}
static bool integer_division_supported() {
DEBUG_ASSERT(initialized_);
return integer_division_supported_;
}
static bool neon_supported() {
DEBUG_ASSERT(initialized_);
return neon_supported_;
}
#if !defined(HOST_ARCH_ARM)
static void set_integer_division_supported(bool supported) {
DEBUG_ASSERT(initialized_);
integer_division_supported_ = supported;
}
static void set_neon_supported(bool supported) {
DEBUG_ASSERT(initialized_);
neon_supported_ = supported;
}
#endif // !defined(HOST_ARCH_ARM)
private:
static const char* hardware_;
static bool integer_division_supported_;
static bool neon_supported_;
#if defined(DEBUG)
static bool initialized_;
#endif
};
class TargetCPUFeatures : public AllStatic {
public:
static void InitOnce() {
HostCPUFeatures::InitOnce();
}
static void Cleanup() {
HostCPUFeatures::Cleanup();
}
static bool double_truncate_round_supported() {
return false;
}
static bool integer_division_supported() {
return HostCPUFeatures::integer_division_supported();
}
static bool neon_supported() {
return HostCPUFeatures::neon_supported();
}
static const char* hardware() {
return HostCPUFeatures::hardware();
}
};
} // namespace dart
#endif // VM_CPU_ARM_H_
+39 -1
View File
@@ -3,18 +3,22 @@
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_ARCH_IA32)
#include "vm/cpu.h"
#include "vm/assembler.h"
#include "vm/constants_ia32.h"
#include "vm/cpuinfo.h"
#include "vm/heap.h"
#include "vm/isolate.h"
#include "vm/object.h"
#include "vm/thread.h"
namespace dart {
DEFINE_FLAG(bool, use_sse41, true, "Use SSE 4.1 if available");
void CPU::FlushICache(uword start, uword size) {
// Nothing to be done here.
}
@@ -24,6 +28,40 @@ const char* CPU::Id() {
return "ia32";
}
bool HostCPUFeatures::sse2_supported_ = false;
bool HostCPUFeatures::sse4_1_supported_ = false;
const char* HostCPUFeatures::hardware_ = NULL;
#if defined(DEBUG)
bool HostCPUFeatures::initialized_ = false;
#endif
void HostCPUFeatures::InitOnce() {
CpuInfo::InitOnce();
hardware_ = CpuInfo::GetCpuModel();
sse2_supported_ = CpuInfo::FieldContains(kCpuInfoFeatures, "sse2");
sse4_1_supported_ =
CpuInfo::FieldContains(kCpuInfoFeatures, "sse4_1") ||
CpuInfo::FieldContains(kCpuInfoFeatures, "sse4.1");
#if defined(DEBUG)
initialized_ = true;
#endif
}
void HostCPUFeatures::Cleanup() {
DEBUG_ASSERT(initialized_);
#if defined(DEBUG)
initialized_ = false;
#endif
ASSERT(hardware_ != NULL);
delete[] hardware_;
hardware_ = NULL;
CpuInfo::Cleanup();
}
} // namespace dart
#endif // defined TARGET_ARCH_IA32
+67
View File
@@ -0,0 +1,67 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_CPU_IA32_H_
#define VM_CPU_IA32_H_
#include "vm/allocation.h"
#include "vm/flags.h"
namespace dart {
DECLARE_FLAG(bool, use_sse41);
class HostCPUFeatures : public AllStatic {
public:
static void InitOnce();
static void Cleanup();
static const char* hardware() {
DEBUG_ASSERT(initialized_);
return hardware_;
}
static bool sse2_supported() {
DEBUG_ASSERT(initialized_);
return sse2_supported_;
}
static bool sse4_1_supported() {
DEBUG_ASSERT(initialized_);
return sse4_1_supported_ && FLAG_use_sse41;
}
private:
static const uint64_t kSSE2BitMask = static_cast<uint64_t>(1) << 26;
static const uint64_t kSSE4_1BitMask = static_cast<uint64_t>(1) << 51;
static const char* hardware_;
static bool sse2_supported_;
static bool sse4_1_supported_;
#if defined(DEBUG)
static bool initialized_;
#endif
};
class TargetCPUFeatures : public AllStatic {
public:
static void InitOnce() {
HostCPUFeatures::InitOnce();
}
static void Cleanup() {
HostCPUFeatures::Cleanup();
}
static const char* hardware() {
return HostCPUFeatures::hardware();
}
static bool sse2_supported() {
return HostCPUFeatures::sse2_supported();
}
static bool sse4_1_supported() {
return HostCPUFeatures::sse4_1_supported();
}
static bool double_truncate_round_supported() {
return sse4_1_supported();
}
};
} // namespace dart
#endif // VM_CPU_IA32_H_
+57 -2
View File
@@ -6,14 +6,16 @@
#if defined(TARGET_ARCH_MIPS)
#include "vm/cpu.h"
#include "vm/cpuinfo.h"
#include "vm/simulator.h"
#if defined(HOST_ARCH_MIPS)
#include <asm/cachectl.h> /* NOLINT */
#include <sys/syscall.h> /* NOLINT */
#include <unistd.h> /* NOLINT */
#endif
#include "vm/cpu.h"
namespace dart {
void CPU::FlushICache(uword start, uword size) {
@@ -37,6 +39,59 @@ const char* CPU::Id() {
"mips";
}
const char* HostCPUFeatures::hardware_ = NULL;
#if defined(DEBUG)
bool HostCPUFeatures::initialized_ = false;
#endif
#if defined(HOST_ARCH_MIPS)
void HostCPUFeatures::InitOnce() {
CpuInfo::InitOnce();
hardware_ = CpuInfo::GetCpuModel();
// Has a floating point unit.
ASSERT(CpuInfo::FieldContains(kCpuInfoModel, "FPU"));
#if defined(DEBUG)
initialized_ = true;
#endif
}
void HostCPUFeatures::Cleanup() {
DEBUG_ASSERT(initialized_);
#if defined(DEBUG)
initialized_ = false;
#endif
ASSERT(hardware_ != NULL);
delete[] hardware_;
hardware_ = NULL;
CpuInfo::Cleanup();
}
#else
void HostCPUFeatures::InitOnce() {
CpuInfo::InitOnce();
hardware_ = CpuInfo::GetCpuModel();
#if defined(DEBUG)
initialized_ = true;
#endif
}
void HostCPUFeatures::Cleanup() {
DEBUG_ASSERT(initialized_);
#if defined(DEBUG)
initialized_ = false;
#endif
ASSERT(hardware_ != NULL);
delete[] hardware_;
hardware_ = NULL;
CpuInfo::Cleanup();
}
#endif // defined(HOST_ARCH_MIPS)
} // namespace dart
#endif // defined TARGET_ARCH_MIPS
+54
View File
@@ -0,0 +1,54 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_CPU_MIPS_H_
#define VM_CPU_MIPS_H_
#include "vm/allocation.h"
namespace dart {
// TargetCPUFeatures gives CPU features for the architecture that we are
// generating code for. HostCPUFeatures gives the CPU features for the
// architecture that we are actually running on. When the architectures
// are the same, TargetCPUFeatures will query HostCPUFeatures. When they are
// different (i.e. we are running in a simulator), HostCPUFeatures will
// additionally mock the options needed for the target architecture so that
// they may be altered for testing.
class HostCPUFeatures: public AllStatic {
public:
static void InitOnce();
static void Cleanup();
static const char* hardware() {
DEBUG_ASSERT(initialized_);
return hardware_;
}
private:
static const char* hardware_;
#if defined(DEBUG)
static bool initialized_;
#endif
};
class TargetCPUFeatures : public AllStatic {
public:
static void InitOnce() {
HostCPUFeatures::InitOnce();
}
static void Cleanup() {
HostCPUFeatures::Cleanup();
}
static const char* hardware() {
return HostCPUFeatures::hardware();
}
static bool double_truncate_round_supported() {
return false;
}
};
} // namespace dart
#endif // VM_CPU_MIPS_H_
+37
View File
@@ -8,13 +8,18 @@
#include "vm/cpu.h"
#include "vm/assembler.h"
#include "vm/constants_x64.h"
#include "vm/cpuinfo.h"
#include "vm/heap.h"
#include "vm/isolate.h"
#include "vm/object.h"
namespace dart {
DEFINE_FLAG(bool, use_sse41, true, "Use SSE 4.1 if available");
void CPU::FlushICache(uword start, uword size) {
// Nothing to be done here.
}
@@ -24,6 +29,38 @@ const char* CPU::Id() {
return "x64";
}
bool HostCPUFeatures::sse2_supported_ = true;
bool HostCPUFeatures::sse4_1_supported_ = false;
const char* HostCPUFeatures::hardware_ = NULL;
#if defined(DEBUG)
bool HostCPUFeatures::initialized_ = false;
#endif
void HostCPUFeatures::InitOnce() {
CpuInfo::InitOnce();
hardware_ = CpuInfo::GetCpuModel();
sse4_1_supported_ =
CpuInfo::FieldContains(kCpuInfoFeatures, "sse4_1") ||
CpuInfo::FieldContains(kCpuInfoFeatures, "sse4.1");
#if defined(DEBUG)
initialized_ = true;
#endif
}
void HostCPUFeatures::Cleanup() {
DEBUG_ASSERT(initialized_);
#if defined(DEBUG)
initialized_ = false;
#endif
ASSERT(hardware_ != NULL);
delete[] hardware_;
hardware_ = NULL;
CpuInfo::Cleanup();
}
} // namespace dart
#endif // defined TARGET_ARCH_X64
+67
View File
@@ -0,0 +1,67 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_CPU_X64_H_
#define VM_CPU_X64_H_
#include "vm/allocation.h"
#include "vm/flags.h"
namespace dart {
DECLARE_FLAG(bool, use_sse41);
class HostCPUFeatures : public AllStatic {
public:
static void InitOnce();
static void Cleanup();
static const char* hardware() {
DEBUG_ASSERT(initialized_);
return hardware_;
}
static bool sse2_supported() {
DEBUG_ASSERT(initialized_);
return sse2_supported_;
}
static bool sse4_1_supported() {
DEBUG_ASSERT(initialized_);
return sse4_1_supported_ && FLAG_use_sse41;
}
private:
static const uint64_t kSSE2BitMask = static_cast<uint64_t>(1) << 26;
static const uint64_t kSSE4_1BitMask = static_cast<uint64_t>(1) << 51;
static const char* hardware_;
static bool sse2_supported_;
static bool sse4_1_supported_;
#if defined(DEBUG)
static bool initialized_;
#endif
};
class TargetCPUFeatures : public AllStatic {
public:
static void InitOnce() {
HostCPUFeatures::InitOnce();
}
static void Cleanup() {
HostCPUFeatures::Cleanup();
}
static const char* hardware() {
return HostCPUFeatures::hardware();
}
static bool sse2_supported() {
return HostCPUFeatures::sse2_supported();
}
static bool sse4_1_supported() {
return HostCPUFeatures::sse4_1_supported();
}
static bool double_truncate_round_supported() {
return false;
}
};
} // namespace dart
#endif // VM_CPU_X64_H_
+116
View File
@@ -0,0 +1,116 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if !defined(TARGET_OS_MACOS)
#include "vm/cpuid.h"
#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
// GetCpuId() on Windows, __get_cpuid() on Linux
#if defined(TARGET_OS_WINDOWS)
#include <intrin.h> // NOLINT
#else
#include <cpuid.h> // NOLINT
#endif
#endif
namespace dart {
bool CpuId::sse2_ = false;
bool CpuId::sse41_ = false;
const char* CpuId::id_string_ = NULL;
const char* CpuId::brand_string_ = NULL;
#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
void CpuId::GetCpuId(int32_t level, uint32_t info[4]) {
#if defined(TARGET_OS_WINDOWS)
// The documentation for __cpuid is at:
// http://msdn.microsoft.com/en-us/library/hskdteyh(v=vs.90).aspx
__cpuid(reinterpret_cast<int*>(info), level);
#else
__get_cpuid(level, &info[0], &info[1], &info[2], &info[3]);
#endif
}
void CpuId::InitOnce() {
uint32_t info[4] = {-1};
GetCpuId(0, info);
char* id_string = new char[3 * sizeof(int32_t)];
// Yes, these are supposed to be out of order.
*reinterpret_cast<uint32_t*>(id_string) = info[1];
*reinterpret_cast<uint32_t*>(id_string + 4) = info[3];
*reinterpret_cast<uint32_t*>(id_string + 8) = info[2];
CpuId::id_string_ = id_string;
GetCpuId(1, info);
CpuId::sse41_ = (info[2] & (1 << 19)) != 0;
CpuId::sse2_ = (info[3] & (1 << 26)) != 0;
char* brand_string = new char[3 * 4 * sizeof(uint32_t)];
for (uint32_t i = 0x80000002; i <= 0x80000004; i++) {
uint32_t off = (i - 0x80000002U) * 4 * sizeof(uint32_t);
GetCpuId(i, info);
*reinterpret_cast<int32_t*>(brand_string + off) = info[0];
*reinterpret_cast<int32_t*>(brand_string + off + 4) = info[1];
*reinterpret_cast<int32_t*>(brand_string + off + 8) = info[2];
*reinterpret_cast<int32_t*>(brand_string + off + 12) = info[3];
}
CpuId::brand_string_ = brand_string;
}
void CpuId::Cleanup() {
ASSERT(id_string_ != NULL);
delete[] id_string_;
id_string_ = NULL;
ASSERT(brand_string_ != NULL);
delete[] brand_string_;
brand_string_ = NULL;
}
const char* CpuId::id_string() {
return strdup(id_string_);
}
const char* CpuId::brand_string() {
return strdup(brand_string_);
}
const char* CpuId::field(CpuInfoIndices idx) {
switch (idx) {
case kCpuInfoProcessor:
return id_string();
case kCpuInfoModel:
return brand_string();
case kCpuInfoHardware:
return brand_string();
case kCpuInfoFeatures: {
if (sse2() && sse41()) {
return strdup("sse2 sse4.1");
} else if (sse2()) {
return strdup("sse2");
} else if (sse41()) {
return strdup("sse4.1");
} else {
return strdup("");
}
}
default: {
UNREACHABLE();
return NULL;
}
}
}
#endif // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
} // namespace dart
#endif // !defined(TARGET_OS_MACOS)
+48
View File
@@ -0,0 +1,48 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_CPUID_H_
#define VM_CPUID_H_
#include "vm/globals.h"
#if !defined(TARGET_OS_MACOS)
#include "vm/allocation.h"
#include "vm/cpuinfo.h"
namespace dart {
class CpuId : public AllStatic {
public:
#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
static void InitOnce();
static void Cleanup();
// Caller must free the result of field.
static const char* field(CpuInfoIndices idx);
#else
static void InitOnce() {}
static void Cleanup() {}
static const char* field(CpuInfoIndices idx) { return NULL; }
#endif
static bool sse2() { return sse2_; }
static bool sse41() { return sse41_; }
// Caller must free the result of id_string and brand_string.
static const char* id_string();
static const char* brand_string();
private:
static bool sse2_;
static bool sse41_;
static const char* id_string_;
static const char* brand_string_;
static void GetCpuId(int32_t level, uint32_t info[4]);
};
} // namespace dart
#endif // !defined(TARGET_OS_MACOS)
#endif // VM_CPUID_H_
+75
View File
@@ -0,0 +1,75 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_CPUINFO_H_
#define VM_CPUINFO_H_
#include "platform/assert.h"
#include "vm/allocation.h"
namespace dart {
// Indices into cpuinfo field name arrays.
enum CpuInfoIndices {
kCpuInfoProcessor = 0,
kCpuInfoModel = 1,
kCpuInfoHardware = 2,
kCpuInfoFeatures = 3,
kCpuInfoMax = 4,
};
// For Intel architectures, the method to use to get CPU information.
enum CpuInfoMethod {
// Use the cpuid instruction.
kCpuInfoCpuId,
// Use system calls.
kCpuInfoSystem,
// Use whatever the default is for a particular OS:
// Linux, Windows -> CpuId,
// Android, MacOS -> System.
kCpuInfoDefault,
};
class CpuInfo : public AllStatic {
public:
static void InitOnce();
static void Cleanup();
static const char* FieldName(CpuInfoIndices idx) {
ASSERT((idx >= 0) && (idx < kCpuInfoMax));
return fields_[idx];
}
// Returns true if the cpuinfo field contains the string.
static bool FieldContains(CpuInfoIndices idx, const char* search_string);
static bool FieldContainsByString(
const char* field, const char* search_string);
// Returns true if the cpuinfo field [field] exists and is non-empty.
static bool HasField(const char* field);
// Returns the field. Caller is responsible for freeing the result.
static const char* ExtractField(CpuInfoIndices idx);
static const char* ExtractFieldByString(const char* field);
// Returns the field describing the CPU model. Caller is responsible for
// freeing the result.
static const char* GetCpuModel() {
ASSERT(HasField(FieldName(kCpuInfoModel)));
return ExtractField(kCpuInfoModel);
}
private:
// The method to use to acquire info about the CPU.
static CpuInfoMethod method_;
// Cpuinfo field names.
static const char* fields_[kCpuInfoMax];
};
} // namespace dart
#endif // VM_CPUINFO_H_
+81
View File
@@ -0,0 +1,81 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_OS_ANDROID)
#include "vm/cpuinfo.h"
#include "vm/proccpuinfo.h"
#include "platform/assert.h"
namespace dart {
CpuInfoMethod CpuInfo::method_ = kCpuInfoDefault;
const char* CpuInfo::fields_[kCpuInfoMax] = {0};
void CpuInfo::InitOnce() {
// Initialize our read from /proc/cpuinfo.
method_ = kCpuInfoSystem;
ProcCpuInfo::InitOnce();
#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
fields_[kCpuInfoProcessor] = "vendor_id";
fields_[kCpuInfoModel] = "model name";
fields_[kCpuInfoHardware] = "model name";
fields_[kCpuInfoFeatures] = "flags";
#elif defined(HOST_ARCH_ARM)
fields_[kCpuInfoProcessor] = "Processor";
fields_[kCpuInfoModel] = "Hardware";
fields_[kCpuInfoHardware] = "Hardware";
fields_[kCpuInfoFeatures] = "Features";
#elif defined(HOST_ARCH_MIPS)
fields_[kCpuInfoProcessor] = "system type";
fields_[kCpuInfoModel] = "cpu model";
fields_[kCpuInfoHardware] = "cpu model";
fields_[kCpuInfoFeatures] = "ASEs implemented";
#else
#error Unrecognized target architecture
#endif
}
void CpuInfo::Cleanup() {
ProcCpuInfo::Cleanup();
}
bool CpuInfo::FieldContains(CpuInfoIndices idx, const char* search_string) {
ASSERT(method_ != kCpuInfoDefault);
return ProcCpuInfo::FieldContains(FieldName(idx), search_string);
}
bool CpuInfo::FieldContainsByString(const char* field,
const char* search_string) {
ASSERT(method_ != kCpuInfoDefault);
return ProcCpuInfo::FieldContains(field, search_string);
}
const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
ASSERT(method_ != kCpuInfoDefault);
return ProcCpuInfo::ExtractField(FieldName(idx));
}
const char* CpuInfo::ExtractFieldByString(const char* field) {
ASSERT(method_ != kCpuInfoDefault);
return ProcCpuInfo::ExtractField(field);
}
bool CpuInfo::HasField(const char* field) {
ASSERT(method_ != kCpuInfoDefault);
return ProcCpuInfo::HasField(field);
}
} // namespace dart
#endif // defined(TARGET_OS_ANDROID)
+128
View File
@@ -0,0 +1,128 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_OS_LINUX)
#include "vm/cpuinfo.h"
#include "vm/cpuid.h"
#include "vm/proccpuinfo.h"
#include "platform/assert.h"
// As with Windows, on IA32 and X64, we use the cpuid instruction.
// The analogous instruction is privileged on ARM and MIPS, so we resort to
// reading from /proc/cpuinfo.
namespace dart {
CpuInfoMethod CpuInfo::method_ = kCpuInfoDefault;
const char* CpuInfo::fields_[kCpuInfoMax] = {0};
void CpuInfo::InitOnce() {
#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
fields_[kCpuInfoProcessor] = "vendor_id";
fields_[kCpuInfoModel] = "model name";
fields_[kCpuInfoHardware] = "model name";
fields_[kCpuInfoFeatures] = "flags";
method_ = kCpuInfoCpuId;
CpuId::InitOnce();
#elif defined(HOST_ARCH_ARM)
fields_[kCpuInfoProcessor] = "Processor";
fields_[kCpuInfoModel] = "model name";
fields_[kCpuInfoHardware] = "Hardware";
fields_[kCpuInfoFeatures] = "Features";
method_ = kCpuInfoSystem;
ProcCpuInfo::InitOnce();
#elif defined(HOST_ARCH_MIPS)
fields_[kCpuInfoProcessor] = "system type";
fields_[kCpuInfoModel] = "cpu model";
fields_[kCpuInfoHardware] = "cpu model";
fields_[kCpuInfoFeatures] = "ASEs implemented";
method_ = kCpuInfoSystem;
ProcCpuInfo::InitOnce();
#else
#error Unrecognized target architecture
#endif
}
void CpuInfo::Cleanup() {
if (method_ == kCpuInfoCpuId) {
CpuId::Cleanup();
} else {
ASSERT(method_ == kCpuInfoSystem);
ProcCpuInfo::Cleanup();
}
}
bool CpuInfo::FieldContains(CpuInfoIndices idx, const char* search_string) {
if (method_ == kCpuInfoCpuId) {
return strstr(CpuId::field(idx), search_string);
} else {
ASSERT(method_ == kCpuInfoSystem);
return ProcCpuInfo::FieldContains(FieldName(idx), search_string);
}
}
bool CpuInfo::FieldContainsByString(const char* field,
const char* search_string) {
if (method_ == kCpuInfoCpuId) {
for (int i = 0; i < kCpuInfoMax; i++) {
if (strcmp(field, fields_[i]) == 0) {
return FieldContains(static_cast<CpuInfoIndices>(i), search_string);
}
}
UNIMPLEMENTED();
return false;
} else {
ASSERT(method_ == kCpuInfoSystem);
return ProcCpuInfo::FieldContains(field, search_string);
}
}
const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
if (method_ == kCpuInfoCpuId) {
return CpuId::field(idx);
} else {
ASSERT(method_ == kCpuInfoSystem);
return ProcCpuInfo::ExtractField(FieldName(idx));
}
}
const char* CpuInfo::ExtractFieldByString(const char* field) {
if (method_ == kCpuInfoCpuId) {
for (int i = 0; i < kCpuInfoMax; i++) {
if (strcmp(field, fields_[i]) == 0) {
return ExtractField(static_cast<CpuInfoIndices>(i));
}
}
UNIMPLEMENTED();
return NULL;
} else {
ASSERT(method_ == kCpuInfoSystem);
return ProcCpuInfo::ExtractField(field);
}
}
bool CpuInfo::HasField(const char* field) {
if (method_ == kCpuInfoCpuId) {
return (strcmp(field, fields_[kCpuInfoProcessor]) == 0) ||
(strcmp(field, fields_[kCpuInfoModel]) == 0) ||
(strcmp(field, fields_[kCpuInfoHardware]) == 0) ||
(strcmp(field, fields_[kCpuInfoFeatures]) == 0);
} else {
ASSERT(method_ == kCpuInfoSystem);
return ProcCpuInfo::HasField(field);
}
}
} // namespace dart
#endif // defined(TARGET_OS_LINUX)
+93
View File
@@ -0,0 +1,93 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_OS_MACOS)
#include "vm/cpuinfo.h"
#include <errno.h> // NOLINT
#include <sys/types.h> // NOLINT
#include <sys/sysctl.h> // NOLINT
#include "platform/assert.h"
namespace dart {
CpuInfoMethod CpuInfo::method_ = kCpuInfoDefault;
const char* CpuInfo::fields_[kCpuInfoMax] = {0};
void CpuInfo::InitOnce() {
method_ = kCpuInfoSystem;
fields_[kCpuInfoProcessor] = "machdep.cpu.vendor";
fields_[kCpuInfoModel] = "machdep.cpu.brand_string";
fields_[kCpuInfoHardware] = "machdep.cpu.brand_string";
fields_[kCpuInfoFeatures] = "machdep.cpu.features";
}
void CpuInfo::Cleanup() {}
bool CpuInfo::FieldContainsByString(const char* field,
const char* search_string) {
ASSERT(method_ != kCpuInfoDefault);
ASSERT(search_string != NULL);
char dest[1024];
size_t dest_len = 1024;
ASSERT(HasField(field));
if (sysctlbyname(field, dest, &dest_len, NULL, 0) != 0) {
UNREACHABLE();
return false;
}
return (strcasestr(dest, search_string) != NULL);
}
bool CpuInfo::FieldContains(CpuInfoIndices idx, const char* search_string) {
ASSERT(method_ != kCpuInfoDefault);
return FieldContainsByString(FieldName(idx), search_string);
}
const char* CpuInfo::ExtractFieldByString(const char* field) {
ASSERT(method_ != kCpuInfoDefault);
ASSERT(field != NULL);
size_t result_len;
ASSERT(HasField(field));
if (sysctlbyname(field, NULL, &result_len, NULL, 0) != 0) {
UNREACHABLE();
return 0;
}
char* result = new char[result_len];
if (sysctlbyname(field, result, &result_len, NULL, 0) != 0) {
UNREACHABLE();
return 0;
}
return result;
}
const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
ASSERT(method_ != kCpuInfoDefault);
return ExtractFieldByString(FieldName(idx));
}
bool CpuInfo::HasField(const char* field) {
ASSERT(method_ != kCpuInfoDefault);
ASSERT(field != NULL);
int ret = sysctlbyname(field, NULL, NULL, NULL, 0);
return (ret != ENOENT);
}
} // namespace dart
#endif // defined(TARGET_OS_MACOS)
+19
View File
@@ -0,0 +1,19 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/assert.h"
#include "vm/cpuinfo.h"
#include "vm/globals.h"
#include "vm/unit_test.h"
namespace dart {
UNIT_TEST_CASE(GetCpuModelTest) {
CpuInfo::InitOnce();
const char* cpumodel = CpuInfo::GetCpuModel();
EXPECT_NE(strlen(cpumodel), 0UL);
CpuInfo::Cleanup();
}
} // namespace dart
+87
View File
@@ -0,0 +1,87 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_OS_WINDOWS)
#include "vm/cpuinfo.h"
#include "vm/cpuid.h"
// __cpuid()
#include <intrin.h> // NOLINT
#include <string.h> // NOLINT
#include "platform/assert.h"
namespace dart {
CpuInfoMethod CpuInfo::method_ = kCpuInfoDefault;
const char* CpuInfo::fields_[kCpuInfoMax] = {0};
void CpuInfo::InitOnce() {
method_ = kCpuInfoCpuId;
// Initialize the CpuId information.
CpuId::InitOnce();
fields_[kCpuInfoProcessor] = "Processor";
fields_[kCpuInfoModel] = "Hardware";
fields_[kCpuInfoHardware] = "Hardware";
fields_[kCpuInfoFeatures] = "Features";
}
void CpuInfo::Cleanup() {
CpuId::Cleanup();
}
bool CpuInfo::FieldContains(CpuInfoIndices idx, const char* search_string) {
ASSERT(method_ != kCpuInfoDefault);
return strstr(CpuId::field(idx), search_string);
}
bool CpuInfo::FieldContainsByString(const char* field,
const char* search_string) {
ASSERT(method_ != kCpuInfoDefault);
for (int i = 0; i < kCpuInfoMax; i++) {
if (strcmp(field, fields_[i]) == 0) {
return FieldContains(static_cast<CpuInfoIndices>(i), search_string);
}
}
UNIMPLEMENTED();
return false;
}
const char* CpuInfo::ExtractField(CpuInfoIndices idx) {
ASSERT(method_ != kCpuInfoDefault);
return CpuId::field(idx);
}
const char* CpuInfo::ExtractFieldByString(const char* field) {
ASSERT(method_ != kCpuInfoDefault);
for (int i = 0; i < kCpuInfoMax; i++) {
if (strcmp(field, fields_[i]) == 0) {
return ExtractField(static_cast<CpuInfoIndices>(i));
}
}
UNIMPLEMENTED();
return NULL;
}
bool CpuInfo::HasField(const char* field) {
ASSERT(method_ != kCpuInfoDefault);
return (strcmp(field, fields_[kCpuInfoProcessor]) == 0) ||
(strcmp(field, fields_[kCpuInfoModel]) == 0) ||
(strcmp(field, fields_[kCpuInfoHardware]) == 0) ||
(strcmp(field, fields_[kCpuInfoFeatures]) == 0);
}
} // namespace dart
#endif // defined(TARGET_OS_WINDOWS)
+4 -2
View File
@@ -5,6 +5,7 @@
#include "vm/dart.h"
#include "vm/code_observers.h"
#include "vm/cpu.h"
#include "vm/dart_api_state.h"
#include "vm/dart_entry.h"
#include "vm/flags.h"
@@ -123,10 +124,10 @@ const char* Dart::InitOnce(Dart_IsolateCreateCallback create,
Symbols::InitOnce(vm_isolate_);
Scanner::InitOnce();
Object::CreateInternalMetaData();
CPUFeatures::InitOnce();
TargetCPUFeatures::InitOnce();
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
// Dart VM requires at least SSE2.
if (!CPUFeatures::sse2_supported()) {
if (!TargetCPUFeatures::sse2_supported()) {
return "SSE2 is required.";
}
#endif
@@ -178,6 +179,7 @@ const char* Dart::Cleanup() {
Profiler::Shutdown();
CodeObservers::DeleteAll();
TargetCPUFeatures::Cleanup();
return NULL;
}
+5 -2
View File
@@ -9,6 +9,7 @@
#include "vm/ast_printer.h"
#include "vm/compiler.h"
#include "vm/cpu.h"
#include "vm/dart_entry.h"
#include "vm/deopt_instructions.h"
#include "vm/il_printer.h"
@@ -44,7 +45,7 @@ bool FlowGraphCompiler::SupportsUnboxedMints() {
bool FlowGraphCompiler::SupportsUnboxedFloat32x4() {
return CPUFeatures::neon_supported() && FLAG_enable_simd_inline;
return TargetCPUFeatures::neon_supported() && FLAG_enable_simd_inline;
}
@@ -718,7 +719,9 @@ void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos,
void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
if (is_optimizing()) return;
if (is_optimizing()) {
return;
}
Definition* defn = instr->AsDefinition();
if ((defn != NULL) && defn->is_used()) {
__ Push(defn->locs()->out().reg());
+2 -1
View File
@@ -9,6 +9,7 @@
#include "vm/ast_printer.h"
#include "vm/compiler.h"
#include "vm/cpu.h"
#include "vm/dart_entry.h"
#include "vm/deopt_instructions.h"
#include "vm/il_printer.h"
@@ -43,7 +44,7 @@ FlowGraphCompiler::~FlowGraphCompiler() {
bool FlowGraphCompiler::SupportsUnboxedMints() {
// Support unboxed mints when SSE 4.1 is available.
return FLAG_unbox_mints && CPUFeatures::sse4_1_supported();
return FLAG_unbox_mints && TargetCPUFeatures::sse4_1_supported();
}
+2 -1
View File
@@ -6,6 +6,7 @@
#include "vm/bit_vector.h"
#include "vm/cha.h"
#include "vm/cpu.h"
#include "vm/dart_entry.h"
#include "vm/flow_graph_builder.h"
#include "vm/flow_graph_compiler.h"
@@ -2778,7 +2779,7 @@ bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
case MethodRecognizer::kDoubleTruncate:
case MethodRecognizer::kDoubleFloor:
case MethodRecognizer::kDoubleCeil:
if (!CPUFeatures::double_truncate_round_supported()) {
if (!TargetCPUFeatures::double_truncate_round_supported()) {
ReplaceWithMathCFunction(call, recognized_kind);
} else {
AddReceiverCheck(call);
+2 -1
View File
@@ -6,6 +6,7 @@
#include "vm/bigint_operations.h"
#include "vm/bit_vector.h"
#include "vm/cpu.h"
#include "vm/dart_entry.h"
#include "vm/flow_graph_allocator.h"
#include "vm/flow_graph_builder.h"
@@ -3108,7 +3109,7 @@ intptr_t InvokeMathCFunctionInstr::ArgumentCountFor(
case MethodRecognizer::kDoubleTruncate:
case MethodRecognizer::kDoubleFloor:
case MethodRecognizer::kDoubleCeil: {
ASSERT(!CPUFeatures::double_truncate_round_supported());
ASSERT(!TargetCPUFeatures::double_truncate_round_supported());
return 1;
}
case MethodRecognizer::kDoubleRound:
+156
View File
@@ -0,0 +1,156 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
#if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID)
#include "vm/proccpuinfo.h"
#include <ctype.h> // NOLINT
#include <string.h> // NOLINT
#include "platform/assert.h"
namespace dart {
char* ProcCpuInfo::data_ = NULL;
intptr_t ProcCpuInfo::datalen_ = 0;
void ProcCpuInfo::InitOnce() {
// Get the size of the cpuinfo file by reading it until the end. This is
// required because files under /proc do not always return a valid size
// when using fseek(0, SEEK_END) + ftell(). Nor can they be mmap()-ed.
static const char PATHNAME[] = "/proc/cpuinfo";
FILE* fp = fopen(PATHNAME, "r");
if (fp != NULL) {
for (;;) {
char buffer[256];
size_t n = fread(buffer, 1, sizeof(buffer), fp);
if (n == 0) {
break;
}
datalen_ += n;
}
fclose(fp);
}
// Read the contents of the cpuinfo file.
data_ = new char[datalen_ + 1];
fp = fopen(PATHNAME, "r");
if (fp != NULL) {
for (intptr_t offset = 0; offset < datalen_; ) {
size_t n = fread(data_ + offset, 1, datalen_ - offset, fp);
if (n == 0) {
break;
}
offset += n;
}
fclose(fp);
}
// Zero-terminate the data.
data_[datalen_] = '\0';
}
void ProcCpuInfo::Cleanup() {
ASSERT(data_);
delete[] data_;
data_ = NULL;
}
char* ProcCpuInfo::FieldStart(const char* field) {
// Look for first field occurrence, and ensure it starts the line.
size_t fieldlen = strlen(field);
char* p = data_;
for (;;) {
p = strstr(p, field);
if (p == NULL) {
return NULL;
}
if (p == data_ || p[-1] == '\n') {
break;
}
p += fieldlen;
}
// Skip to the first colon followed by a space.
p = strchr(p + fieldlen, ':');
if (p == NULL || !isspace(p[1])) {
return NULL;
}
p += 2;
return p;
}
bool ProcCpuInfo::FieldContains(const char* field, const char* search_string) {
ASSERT(data_ != NULL);
ASSERT(search_string != NULL);
char* p = FieldStart(field);
if (p == NULL) {
return false;
}
// Find the end of the line.
char* q = strchr(p, '\n');
if (q == NULL) {
q = data_ + datalen_;
}
char saved_end = *q;
*q = '\0';
bool ret = (strcasestr(p, search_string) != NULL);
*q = saved_end;
return ret;
}
// Extract the content of a the first occurrence of a given field in
// the content of the cpuinfo file and return it as a heap-allocated
// string that must be freed by the caller using delete[].
// Return NULL if not found.
const char* ProcCpuInfo::ExtractField(const char* field) {
ASSERT(field != NULL);
ASSERT(data_ != NULL);
char* p = FieldStart(field);
if (p == NULL) {
return NULL;
}
// Find the end of the line.
char* q = strchr(p, '\n');
if (q == NULL) {
q = data_ + datalen_;
}
intptr_t len = q - p;
char* result = new char[len + 1]; // plus one for null-terminator.
// Copy the line into result, leaving enough room for a null-terminator.
char saved_end = *q;
*q = '\0';
strncpy(result, p, len);
result[len] = '\0';
*q = saved_end;
return result;
}
bool ProcCpuInfo::HasField(const char* field) {
ASSERT(field != NULL);
ASSERT(data_ != NULL);
return (FieldStart(field) != NULL);
}
} // namespace dart
#endif // defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID)
+34
View File
@@ -0,0 +1,34 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_PROCCPUINFO_H_
#define VM_PROCCPUINFO_H_
#include "vm/globals.h"
#if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID)
#include "vm/allocation.h"
namespace dart {
class ProcCpuInfo : public AllStatic {
public:
static void InitOnce();
static void Cleanup();
static bool FieldContains(const char* field, const char* search_string);
static const char* ExtractField(const char* field);
static bool HasField(const char* field);
private:
static char* data_;
static intptr_t datalen_;
static char* FieldStart(const char* field);
};
} // namespace dart
#endif // defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID)
#endif // VM_PROCCPUINFO_H_
+10
View File
@@ -1048,6 +1048,15 @@ static bool HandleDebug(Isolate* isolate, JSONStream* js) {
}
static bool HandleCpu(Isolate* isolate, JSONStream* js) {
JSONObject jsobj(js);
jsobj.AddProperty("type", "CPU");
jsobj.AddProperty("targetCPU", CPU::Id());
jsobj.AddProperty("hostCPU", HostCPUFeatures::hardware());
return true;
}
static bool HandleCode(Isolate* isolate, JSONStream* js) {
REQUIRE_COLLECTION_ID("code");
uintptr_t pc;
@@ -1089,6 +1098,7 @@ static IsolateMessageHandlerEntry isolate_handlers[] = {
{ "classes", HandleClasses },
{ "code", HandleCode },
{ "coverage", HandleCoverage },
{ "cpu", HandleCpu },
{ "debug", HandleDebug },
{ "libraries", HandleLibraries },
{ "objecthistogram", HandleObjectHistogram},
+2 -1
View File
@@ -16,6 +16,7 @@
#include "vm/assembler.h"
#include "vm/constants_arm.h"
#include "vm/cpu.h"
#include "vm/disassembler.h"
#include "vm/native_arguments.h"
#include "vm/stack_frame.h"
@@ -2303,7 +2304,7 @@ void Simulator::DecodeType2(Instr* instr) {
void Simulator::DoDivision(Instr* instr) {
ASSERT(CPUFeatures::integer_division_supported());
ASSERT(TargetCPUFeatures::integer_division_supported());
Register rd = instr->DivRdField();
Register rn = instr->DivRnField();
Register rm = instr->DivRmField();
+10
View File
@@ -100,6 +100,14 @@
'cpu_mips.cc',
'cpu_test.cc',
'cpu_x64.cc',
'cpuid.h',
'cpuid.cc',
'cpuinfo.h',
'cpuinfo_android.cc',
'cpuinfo_linux.cc',
'cpuinfo_macos.cc',
'cpuinfo_test.cc',
'cpuinfo_win.cc',
'custom_isolate_test.cc',
'dart.cc',
'dart.h',
@@ -278,6 +286,8 @@
'port.cc',
'port.h',
'port_test.cc',
'proccpuinfo.h',
'proccpuinfo.cc',
'profiler.cc',
'profiler.h',
'profiler_test.cc',