Commit 256de323 authored by olivf@chromium.org's avatar olivf@chromium.org

Ensure only whitelisted stubs have sse2 versions in the snapshot.

BUG=
R=mvstanton@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17123 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent fc952077
...@@ -50,6 +50,7 @@ bool CpuFeatures::initialized_ = false; ...@@ -50,6 +50,7 @@ bool CpuFeatures::initialized_ = false;
#endif #endif
unsigned CpuFeatures::supported_ = 0; unsigned CpuFeatures::supported_ = 0;
unsigned CpuFeatures::found_by_runtime_probing_only_ = 0; unsigned CpuFeatures::found_by_runtime_probing_only_ = 0;
unsigned CpuFeatures::cross_compile_ = 0;
unsigned CpuFeatures::cache_line_size_ = 64; unsigned CpuFeatures::cache_line_size_ = 64;
......
...@@ -64,23 +64,41 @@ class CpuFeatures : public AllStatic { ...@@ -64,23 +64,41 @@ class CpuFeatures : public AllStatic {
// Check whether a feature is supported by the target CPU. // Check whether a feature is supported by the target CPU.
static bool IsSupported(CpuFeature f) { static bool IsSupported(CpuFeature f) {
ASSERT(initialized_); ASSERT(initialized_);
return (supported_ & (1u << f)) != 0; return Check(f, supported_);
} }
static bool IsFoundByRuntimeProbingOnly(CpuFeature f) { static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
ASSERT(initialized_); ASSERT(initialized_);
return (found_by_runtime_probing_only_ & return Check(f, found_by_runtime_probing_only_);
(static_cast<uint64_t>(1) << f)) != 0;
} }
static bool IsSafeForSnapshot(CpuFeature f) { static bool IsSafeForSnapshot(CpuFeature f) {
return (IsSupported(f) && return Check(f, cross_compile_) ||
(IsSupported(f) &&
(!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f))); (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
} }
static unsigned cache_line_size() { return cache_line_size_; } static unsigned cache_line_size() { return cache_line_size_; }
static bool VerifyCrossCompiling() {
return cross_compile_ == 0;
}
static bool VerifyCrossCompiling(CpuFeature f) {
unsigned mask = flag2set(f);
return cross_compile_ == 0 ||
(cross_compile_ & mask) == mask;
}
private: private:
static bool Check(CpuFeature f, unsigned set) {
return (set & flag2set(f)) != 0;
}
static unsigned flag2set(CpuFeature f) {
return 1u << f;
}
#ifdef DEBUG #ifdef DEBUG
static bool initialized_; static bool initialized_;
#endif #endif
...@@ -88,6 +106,8 @@ class CpuFeatures : public AllStatic { ...@@ -88,6 +106,8 @@ class CpuFeatures : public AllStatic {
static unsigned found_by_runtime_probing_only_; static unsigned found_by_runtime_probing_only_;
static unsigned cache_line_size_; static unsigned cache_line_size_;
static unsigned cross_compile_;
friend class ExternalReference; friend class ExternalReference;
friend class PlatformFeatureScope; friend class PlatformFeatureScope;
DISALLOW_COPY_AND_ASSIGN(CpuFeatures); DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
......
...@@ -210,19 +210,14 @@ CpuFeatureScope::~CpuFeatureScope() { ...@@ -210,19 +210,14 @@ CpuFeatureScope::~CpuFeatureScope() {
// Implementation of PlatformFeatureScope // Implementation of PlatformFeatureScope
PlatformFeatureScope::PlatformFeatureScope(CpuFeature f) PlatformFeatureScope::PlatformFeatureScope(CpuFeature f)
: old_supported_(CpuFeatures::supported_), : old_cross_compile_(CpuFeatures::cross_compile_) {
old_found_by_runtime_probing_only_(
CpuFeatures::found_by_runtime_probing_only_) {
uint64_t mask = static_cast<uint64_t>(1) << f; uint64_t mask = static_cast<uint64_t>(1) << f;
CpuFeatures::supported_ |= mask; CpuFeatures::cross_compile_ |= mask;
CpuFeatures::found_by_runtime_probing_only_ &= ~mask;
} }
PlatformFeatureScope::~PlatformFeatureScope() { PlatformFeatureScope::~PlatformFeatureScope() {
CpuFeatures::supported_ = old_supported_; CpuFeatures::cross_compile_ = old_cross_compile_;
CpuFeatures::found_by_runtime_probing_only_ =
old_found_by_runtime_probing_only_;
} }
......
...@@ -142,8 +142,7 @@ class PlatformFeatureScope BASE_EMBEDDED { ...@@ -142,8 +142,7 @@ class PlatformFeatureScope BASE_EMBEDDED {
~PlatformFeatureScope(); ~PlatformFeatureScope();
private: private:
uint64_t old_supported_; uint64_t old_cross_compile_;
uint64_t old_found_by_runtime_probing_only_;
}; };
......
...@@ -129,6 +129,11 @@ Handle<Code> PlatformCodeStub::GenerateCode(Isolate* isolate) { ...@@ -129,6 +129,11 @@ Handle<Code> PlatformCodeStub::GenerateCode(Isolate* isolate) {
} }
void CodeStub::VerifyPlatformFeatures(Isolate* isolate) {
ASSERT(CpuFeatures::VerifyCrossCompiling());
}
Handle<Code> CodeStub::GetCode(Isolate* isolate) { Handle<Code> CodeStub::GetCode(Isolate* isolate) {
Factory* factory = isolate->factory(); Factory* factory = isolate->factory();
Heap* heap = isolate->heap(); Heap* heap = isolate->heap();
...@@ -141,6 +146,10 @@ Handle<Code> CodeStub::GetCode(Isolate* isolate) { ...@@ -141,6 +146,10 @@ Handle<Code> CodeStub::GetCode(Isolate* isolate) {
return Handle<Code>(code); return Handle<Code>(code);
} }
#ifdef DEBUG
VerifyPlatformFeatures(isolate);
#endif
{ {
HandleScope scope(isolate); HandleScope scope(isolate);
...@@ -297,8 +306,6 @@ void BinaryOpStub::GenerateAheadOfTime(Isolate* isolate) { ...@@ -297,8 +306,6 @@ void BinaryOpStub::GenerateAheadOfTime(Isolate* isolate) {
// expensive at runtime. When solved we should be able to add most binops to // expensive at runtime. When solved we should be able to add most binops to
// the snapshot instead of hand-picking them. // the snapshot instead of hand-picking them.
// Generated list of commonly used stubs // Generated list of commonly used stubs
Generate(Token::ADD, GENERIC, STRING, STRING, NO_OVERWRITE, isolate);
Generate(Token::ADD, GENERIC, STRING, STRING, OVERWRITE_RIGHT, isolate);
Generate(Token::ADD, INT32, INT32, INT32, NO_OVERWRITE, isolate); Generate(Token::ADD, INT32, INT32, INT32, NO_OVERWRITE, isolate);
Generate(Token::ADD, INT32, INT32, INT32, OVERWRITE_LEFT, isolate); Generate(Token::ADD, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
Generate(Token::ADD, INT32, INT32, NUMBER, NO_OVERWRITE, isolate); Generate(Token::ADD, INT32, INT32, NUMBER, NO_OVERWRITE, isolate);
...@@ -326,12 +333,6 @@ void BinaryOpStub::GenerateAheadOfTime(Isolate* isolate) { ...@@ -326,12 +333,6 @@ void BinaryOpStub::GenerateAheadOfTime(Isolate* isolate) {
Generate(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate); Generate(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT, isolate);
Generate(Token::ADD, SMI, SMI, INT32, OVERWRITE_LEFT, isolate); Generate(Token::ADD, SMI, SMI, INT32, OVERWRITE_LEFT, isolate);
Generate(Token::ADD, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate); Generate(Token::ADD, SMI, SMI, SMI, OVERWRITE_RIGHT, isolate);
Generate(Token::ADD, STRING, GENERIC, STRING, NO_OVERWRITE, isolate);
Generate(Token::ADD, STRING, GENERIC, STRING, OVERWRITE_LEFT, isolate);
Generate(Token::ADD, STRING, GENERIC, STRING, OVERWRITE_RIGHT, isolate);
Generate(Token::ADD, STRING, STRING, STRING, NO_OVERWRITE, isolate);
Generate(Token::ADD, STRING, STRING, STRING, OVERWRITE_LEFT, isolate);
Generate(Token::ADD, STRING, STRING, STRING, OVERWRITE_RIGHT, isolate);
Generate(Token::BIT_AND, INT32, INT32, INT32, NO_OVERWRITE, isolate); Generate(Token::BIT_AND, INT32, INT32, INT32, NO_OVERWRITE, isolate);
Generate(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_LEFT, isolate); Generate(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_LEFT, isolate);
Generate(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_RIGHT, isolate); Generate(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_RIGHT, isolate);
......
...@@ -209,6 +209,7 @@ class CodeStub BASE_EMBEDDED { ...@@ -209,6 +209,7 @@ class CodeStub BASE_EMBEDDED {
// Generates the assembler code for the stub. // Generates the assembler code for the stub.
virtual Handle<Code> GenerateCode(Isolate* isolate) = 0; virtual Handle<Code> GenerateCode(Isolate* isolate) = 0;
virtual void VerifyPlatformFeatures(Isolate* isolate);
// Returns whether the code generated for this stub needs to be allocated as // Returns whether the code generated for this stub needs to be allocated as
// a fixed (non-moveable) code object. // a fixed (non-moveable) code object.
...@@ -1043,6 +1044,10 @@ class BinaryOpStub: public HydrogenCodeStub { ...@@ -1043,6 +1044,10 @@ class BinaryOpStub: public HydrogenCodeStub {
return MONOMORPHIC; return MONOMORPHIC;
} }
virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
}
virtual Code::ExtraICState GetExtraICState() { virtual Code::ExtraICState GetExtraICState() {
bool sse_field = Max(result_state_, Max(left_state_, right_state_)) > SMI && bool sse_field = Max(result_state_, Max(left_state_, right_state_)) > SMI &&
CpuFeatures::IsSafeForSnapshot(SSE2); CpuFeatures::IsSafeForSnapshot(SSE2);
...@@ -1348,6 +1353,11 @@ class CEntryStub : public PlatformCodeStub { ...@@ -1348,6 +1353,11 @@ class CEntryStub : public PlatformCodeStub {
virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE; virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
static void GenerateAheadOfTime(Isolate* isolate); static void GenerateAheadOfTime(Isolate* isolate);
protected:
virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
};
private: private:
void GenerateCore(MacroAssembler* masm, void GenerateCore(MacroAssembler* masm,
Label* throw_normal_exception, Label* throw_normal_exception,
...@@ -1766,6 +1776,11 @@ class DoubleToIStub : public PlatformCodeStub { ...@@ -1766,6 +1776,11 @@ class DoubleToIStub : public PlatformCodeStub {
virtual bool SometimesSetsUpAFrame() { return false; } virtual bool SometimesSetsUpAFrame() { return false; }
protected:
virtual void VerifyPlatformFeatures(Isolate* isolate) V8_OVERRIDE {
ASSERT(CpuFeatures::VerifyCrossCompiling(SSE2));
}
private: private:
static const int kBitsPerRegisterNumber = 6; static const int kBitsPerRegisterNumber = 6;
STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters); STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
......
...@@ -53,6 +53,7 @@ bool CpuFeatures::initialized_ = false; ...@@ -53,6 +53,7 @@ bool CpuFeatures::initialized_ = false;
#endif #endif
uint64_t CpuFeatures::supported_ = 0; uint64_t CpuFeatures::supported_ = 0;
uint64_t CpuFeatures::found_by_runtime_probing_only_ = 0; uint64_t CpuFeatures::found_by_runtime_probing_only_ = 0;
uint64_t CpuFeatures::cross_compile_ = 0;
ExternalReference ExternalReference::cpu_features() { ExternalReference ExternalReference::cpu_features() {
......
...@@ -535,31 +535,52 @@ class CpuFeatures : public AllStatic { ...@@ -535,31 +535,52 @@ class CpuFeatures : public AllStatic {
// Check whether a feature is supported by the target CPU. // Check whether a feature is supported by the target CPU.
static bool IsSupported(CpuFeature f) { static bool IsSupported(CpuFeature f) {
ASSERT(initialized_); ASSERT(initialized_);
if (Check(f, cross_compile_)) return true;
if (f == SSE2 && !FLAG_enable_sse2) return false; if (f == SSE2 && !FLAG_enable_sse2) return false;
if (f == SSE3 && !FLAG_enable_sse3) return false; if (f == SSE3 && !FLAG_enable_sse3) return false;
if (f == SSE4_1 && !FLAG_enable_sse4_1) return false; if (f == SSE4_1 && !FLAG_enable_sse4_1) return false;
if (f == CMOV && !FLAG_enable_cmov) return false; if (f == CMOV && !FLAG_enable_cmov) return false;
return (supported_ & (static_cast<uint64_t>(1) << f)) != 0; return Check(f, supported_);
} }
static bool IsFoundByRuntimeProbingOnly(CpuFeature f) { static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
ASSERT(initialized_); ASSERT(initialized_);
return (found_by_runtime_probing_only_ & return Check(f, found_by_runtime_probing_only_);
(static_cast<uint64_t>(1) << f)) != 0;
} }
static bool IsSafeForSnapshot(CpuFeature f) { static bool IsSafeForSnapshot(CpuFeature f) {
return (IsSupported(f) && return Check(f, cross_compile_) ||
(IsSupported(f) &&
(!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f))); (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
} }
static bool VerifyCrossCompiling() {
return cross_compile_ == 0;
}
static bool VerifyCrossCompiling(CpuFeature f) {
uint64_t mask = flag2set(f);
return cross_compile_ == 0 ||
(cross_compile_ & mask) == mask;
}
private: private:
static bool Check(CpuFeature f, uint64_t set) {
return (set & flag2set(f)) != 0;
}
static uint64_t flag2set(CpuFeature f) {
return static_cast<uint64_t>(1) << f;
}
#ifdef DEBUG #ifdef DEBUG
static bool initialized_; static bool initialized_;
#endif #endif
static uint64_t supported_; static uint64_t supported_;
static uint64_t found_by_runtime_probing_only_; static uint64_t found_by_runtime_probing_only_;
static uint64_t cross_compile_;
friend class ExternalReference; friend class ExternalReference;
friend class PlatformFeatureScope; friend class PlatformFeatureScope;
DISALLOW_COPY_AND_ASSIGN(CpuFeatures); DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
......
...@@ -48,6 +48,7 @@ bool CpuFeatures::initialized_ = false; ...@@ -48,6 +48,7 @@ bool CpuFeatures::initialized_ = false;
#endif #endif
unsigned CpuFeatures::supported_ = 0; unsigned CpuFeatures::supported_ = 0;
unsigned CpuFeatures::found_by_runtime_probing_only_ = 0; unsigned CpuFeatures::found_by_runtime_probing_only_ = 0;
unsigned CpuFeatures::cross_compile_ = 0;
ExternalReference ExternalReference::cpu_features() { ExternalReference ExternalReference::cpu_features() {
......
...@@ -411,27 +411,47 @@ class CpuFeatures : public AllStatic { ...@@ -411,27 +411,47 @@ class CpuFeatures : public AllStatic {
// Check whether a feature is supported by the target CPU. // Check whether a feature is supported by the target CPU.
static bool IsSupported(CpuFeature f) { static bool IsSupported(CpuFeature f) {
ASSERT(initialized_); ASSERT(initialized_);
return (supported_ & (1u << f)) != 0; return Check(f, supported_);
} }
static bool IsFoundByRuntimeProbingOnly(CpuFeature f) { static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
ASSERT(initialized_); ASSERT(initialized_);
return (found_by_runtime_probing_only_ & return Check(f, found_by_runtime_probing_only_);
(static_cast<uint64_t>(1) << f)) != 0;
} }
static bool IsSafeForSnapshot(CpuFeature f) { static bool IsSafeForSnapshot(CpuFeature f) {
return (IsSupported(f) && return Check(f, cross_compile_) ||
(IsSupported(f) &&
(!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f))); (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
} }
static bool VerifyCrossCompiling() {
return cross_compile_ == 0;
}
static bool VerifyCrossCompiling(CpuFeature f) {
unsigned mask = flag2set(f);
return cross_compile_ == 0 ||
(cross_compile_ & mask) == mask;
}
private: private:
static bool Check(CpuFeature f, unsigned set) {
return (set & flag2set(f)) != 0;
}
static unsigned flag2set(CpuFeature f) {
return 1u << f;
}
#ifdef DEBUG #ifdef DEBUG
static bool initialized_; static bool initialized_;
#endif #endif
static unsigned supported_; static unsigned supported_;
static unsigned found_by_runtime_probing_only_; static unsigned found_by_runtime_probing_only_;
static unsigned cross_compile_;
friend class ExternalReference; friend class ExternalReference;
friend class PlatformFeatureScope; friend class PlatformFeatureScope;
DISALLOW_COPY_AND_ASSIGN(CpuFeatures); DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
......
...@@ -44,7 +44,7 @@ bool CpuFeatures::initialized_ = false; ...@@ -44,7 +44,7 @@ bool CpuFeatures::initialized_ = false;
#endif #endif
uint64_t CpuFeatures::supported_ = CpuFeatures::kDefaultCpuFeatures; uint64_t CpuFeatures::supported_ = CpuFeatures::kDefaultCpuFeatures;
uint64_t CpuFeatures::found_by_runtime_probing_only_ = 0; uint64_t CpuFeatures::found_by_runtime_probing_only_ = 0;
uint64_t CpuFeatures::cross_compile_ = 0;
ExternalReference ExternalReference::cpu_features() { ExternalReference ExternalReference::cpu_features() {
ASSERT(CpuFeatures::initialized_); ASSERT(CpuFeatures::initialized_);
......
...@@ -471,26 +471,45 @@ class CpuFeatures : public AllStatic { ...@@ -471,26 +471,45 @@ class CpuFeatures : public AllStatic {
// Check whether a feature is supported by the target CPU. // Check whether a feature is supported by the target CPU.
static bool IsSupported(CpuFeature f) { static bool IsSupported(CpuFeature f) {
if (Check(f, cross_compile_)) return true;
ASSERT(initialized_); ASSERT(initialized_);
if (f == SSE3 && !FLAG_enable_sse3) return false; if (f == SSE3 && !FLAG_enable_sse3) return false;
if (f == SSE4_1 && !FLAG_enable_sse4_1) return false; if (f == SSE4_1 && !FLAG_enable_sse4_1) return false;
if (f == CMOV && !FLAG_enable_cmov) return false; if (f == CMOV && !FLAG_enable_cmov) return false;
if (f == SAHF && !FLAG_enable_sahf) return false; if (f == SAHF && !FLAG_enable_sahf) return false;
return (supported_ & (static_cast<uint64_t>(1) << f)) != 0; return Check(f, supported_);
} }
static bool IsFoundByRuntimeProbingOnly(CpuFeature f) { static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
ASSERT(initialized_); ASSERT(initialized_);
return (found_by_runtime_probing_only_ & return Check(f, found_by_runtime_probing_only_);
(static_cast<uint64_t>(1) << f)) != 0;
} }
static bool IsSafeForSnapshot(CpuFeature f) { static bool IsSafeForSnapshot(CpuFeature f) {
return (IsSupported(f) && return Check(f, cross_compile_) ||
(IsSupported(f) &&
(!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f))); (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
} }
static bool VerifyCrossCompiling() {
return cross_compile_ == 0;
}
static bool VerifyCrossCompiling(CpuFeature f) {
uint64_t mask = flag2set(f);
return cross_compile_ == 0 ||
(cross_compile_ & mask) == mask;
}
private: private:
static bool Check(CpuFeature f, uint64_t set) {
return (set & flag2set(f)) != 0;
}
static uint64_t flag2set(CpuFeature f) {
return static_cast<uint64_t>(1) << f;
}
// Safe defaults include CMOV for X64. It is always available, if // Safe defaults include CMOV for X64. It is always available, if
// anyone checks, but they shouldn't need to check. // anyone checks, but they shouldn't need to check.
// The required user mode extensions in X64 are (from AMD64 ABI Table A.1): // The required user mode extensions in X64 are (from AMD64 ABI Table A.1):
...@@ -503,6 +522,8 @@ class CpuFeatures : public AllStatic { ...@@ -503,6 +522,8 @@ class CpuFeatures : public AllStatic {
static uint64_t supported_; static uint64_t supported_;
static uint64_t found_by_runtime_probing_only_; static uint64_t found_by_runtime_probing_only_;
static uint64_t cross_compile_;
friend class ExternalReference; friend class ExternalReference;
friend class PlatformFeatureScope; friend class PlatformFeatureScope;
DISALLOW_COPY_AND_ASSIGN(CpuFeatures); DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment