Commit df4f5234 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Allow a platform to indicate that some CPU features are always

available.  We use this to ensure that snapshots on MacOSX can
use SSE2 instructions.  Also clean up and assertify the
handling of things we can't do when we are generating a
snapshot.  Fix a bug in the new serialization tests where
they activated Snapshot::enable() too late after code had been
generated that assumed no snapshots.
Review URL: http://codereview.chromium.org/391051

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3301 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1560b898
...@@ -45,30 +45,31 @@ namespace internal { ...@@ -45,30 +45,31 @@ namespace internal {
// Safe default is no features. // Safe default is no features.
unsigned CpuFeatures::supported_ = 0; unsigned CpuFeatures::supported_ = 0;
unsigned CpuFeatures::enabled_ = 0; unsigned CpuFeatures::enabled_ = 0;
unsigned CpuFeatures::found_by_runtime_probing_ = 0;
void CpuFeatures::Probe() { void CpuFeatures::Probe() {
// If the compiler is allowed to use vfp then we can use vfp too in our // If the compiler is allowed to use vfp then we can use vfp too in our
// code generation. // code generation.
#if !defined(__arm__) || (defined(__VFP_FP__) && !defined(__SOFTFP__)) #if !defined(__arm__)
// The supported flags for VFP are set to true for the following // For the simulator=arm build, always use VFP since the arm simulator has
// conditions, even without runtime detection of VFP: // VFP support.
// (1) For the simulator=arm build, always use VFP since
// the arm simulator has VFP support.
// (2) If V8 is being compiled with GCC with the vfp option turned on,
// always use VFP since the build system assumes that V8 will run on
// a platform that has VFP hardware.
supported_ |= 1u << VFP3; supported_ |= 1u << VFP3;
#else #else
if (Serializer::enabled()) return; // No features if we might serialize. if (Serializer::enabled()) {
supported_ |= OS::CpuFeaturesImpliedByPlatform();
return; // No features if we might serialize.
}
if (OS::ArmCpuHasFeature(OS::VFP)) { if (OS::ArmCpuHasFeature(VFP3)) {
// This implementation also sets the VFP flags if // This implementation also sets the VFP flags if
// runtime detection of VFP returns true. // runtime detection of VFP returns true.
supported_ |= 1u << VFP3; supported_ |= 1u << VFP3;
found_by_runtime_probing_ |= 1u << VFP3;
} }
#endif #endif
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Implementation of Register and CRegister // Implementation of Register and CRegister
...@@ -605,6 +606,11 @@ static bool fits_shifter(uint32_t imm32, ...@@ -605,6 +606,11 @@ static bool fits_shifter(uint32_t imm32,
// encoded. // encoded.
static bool MustUseIp(RelocInfo::Mode rmode) { static bool MustUseIp(RelocInfo::Mode rmode) {
if (rmode == RelocInfo::EXTERNAL_REFERENCE) { if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
#ifdef DEBUG
if (!Serializer::enabled()) {
Serializer::TooLateToEnableNow();
}
#endif
return Serializer::enabled(); return Serializer::enabled();
} else if (rmode == RelocInfo::NONE) { } else if (rmode == RelocInfo::NONE) {
return false; return false;
...@@ -1363,6 +1369,7 @@ void Assembler::stc2(Coprocessor coproc, ...@@ -1363,6 +1369,7 @@ void Assembler::stc2(Coprocessor coproc,
stc(coproc, crd, rn, option, l, static_cast<Condition>(nv)); stc(coproc, crd, rn, option, l, static_cast<Condition>(nv));
} }
// Support for VFP. // Support for VFP.
void Assembler::fmdrr(const Register dst, void Assembler::fmdrr(const Register dst,
const Register src1, const Register src1,
...@@ -1373,7 +1380,7 @@ void Assembler::fmdrr(const Register dst, ...@@ -1373,7 +1380,7 @@ void Assembler::fmdrr(const Register dst,
// Instruction details available in ARM DDI 0406A, A8-646. // Instruction details available in ARM DDI 0406A, A8-646.
// cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) | // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
// Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
ASSERT(CpuFeatures::IsEnabled(VFP3));
ASSERT(!src1.is(pc) && !src2.is(pc)); ASSERT(!src1.is(pc) && !src2.is(pc));
emit(cond | 0xC*B24 | B22 | src2.code()*B16 | emit(cond | 0xC*B24 | B22 | src2.code()*B16 |
src1.code()*B12 | 0xB*B8 | B4 | dst.code()); src1.code()*B12 | 0xB*B8 | B4 | dst.code());
...@@ -1389,7 +1396,7 @@ void Assembler::fmrrd(const Register dst1, ...@@ -1389,7 +1396,7 @@ void Assembler::fmrrd(const Register dst1,
// Instruction details available in ARM DDI 0406A, A8-646. // Instruction details available in ARM DDI 0406A, A8-646.
// cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) | // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
// Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
ASSERT(CpuFeatures::IsEnabled(VFP3));
ASSERT(!dst1.is(pc) && !dst2.is(pc)); ASSERT(!dst1.is(pc) && !dst2.is(pc));
emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 | emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 |
dst1.code()*B12 | 0xB*B8 | B4 | src.code()); dst1.code()*B12 | 0xB*B8 | B4 | src.code());
...@@ -1404,7 +1411,7 @@ void Assembler::fmsr(const Register dst, ...@@ -1404,7 +1411,7 @@ void Assembler::fmsr(const Register dst,
// Instruction details available in ARM DDI 0406A, A8-642. // Instruction details available in ARM DDI 0406A, A8-642.
// cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) | // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
// Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
ASSERT(CpuFeatures::IsEnabled(VFP3));
ASSERT(!src.is(pc)); ASSERT(!src.is(pc));
emit(cond | 0xE*B24 | (dst.code() >> 1)*B16 | emit(cond | 0xE*B24 | (dst.code() >> 1)*B16 |
src.code()*B12 | 0xA*B8 | (0x1 & dst.code())*B7 | B4); src.code()*B12 | 0xA*B8 | (0x1 & dst.code())*B7 | B4);
...@@ -1419,7 +1426,7 @@ void Assembler::fmrs(const Register dst, ...@@ -1419,7 +1426,7 @@ void Assembler::fmrs(const Register dst,
// Instruction details available in ARM DDI 0406A, A8-642. // Instruction details available in ARM DDI 0406A, A8-642.
// cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) | // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
// Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
ASSERT(CpuFeatures::IsEnabled(VFP3));
ASSERT(!dst.is(pc)); ASSERT(!dst.is(pc));
emit(cond | 0xE*B24 | B20 | (src.code() >> 1)*B16 | emit(cond | 0xE*B24 | B20 | (src.code() >> 1)*B16 |
dst.code()*B12 | 0xA*B8 | (0x1 & src.code())*B7 | B4); dst.code()*B12 | 0xA*B8 | (0x1 & src.code())*B7 | B4);
...@@ -1434,7 +1441,7 @@ void Assembler::fsitod(const Register dst, ...@@ -1434,7 +1441,7 @@ void Assembler::fsitod(const Register dst,
// Instruction details available in ARM DDI 0406A, A8-576. // Instruction details available in ARM DDI 0406A, A8-576.
// cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) |opc2=000(18-16) | // cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) |opc2=000(18-16) |
// Vd(15-12) | 101(11-9) | sz(8)=1 | op(7)=1 | 1(6) | M=?(5) | 0(4) | Vm(3-0) // Vd(15-12) | 101(11-9) | sz(8)=1 | op(7)=1 | 1(6) | M=?(5) | 0(4) | Vm(3-0)
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(cond | 0xE*B24 | B23 | 0x3*B20 | B19 | emit(cond | 0xE*B24 | B23 | 0x3*B20 | B19 |
dst.code()*B12 | 0x5*B9 | B8 | B7 | B6 | dst.code()*B12 | 0x5*B9 | B8 | B7 | B6 |
(0x1 & src.code())*B5 | (src.code() >> 1)); (0x1 & src.code())*B5 | (src.code() >> 1));
...@@ -1449,7 +1456,7 @@ void Assembler::ftosid(const Register dst, ...@@ -1449,7 +1456,7 @@ void Assembler::ftosid(const Register dst,
// Instruction details available in ARM DDI 0406A, A8-576. // Instruction details available in ARM DDI 0406A, A8-576.
// cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) | opc2=101(18-16)| // cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) | opc2=101(18-16)|
// Vd(15-12) | 101(11-9) | sz(8)=1 | op(7)=? | 1(6) | M=?(5) | 0(4) | Vm(3-0) // Vd(15-12) | 101(11-9) | sz(8)=1 | op(7)=? | 1(6) | M=?(5) | 0(4) | Vm(3-0)
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(cond | 0xE*B24 | B23 |(0x1 & dst.code())*B22 | emit(cond | 0xE*B24 | B23 |(0x1 & dst.code())*B22 |
0x3*B20 | B19 | 0x5*B16 | (dst.code() >> 1)*B12 | 0x3*B20 | B19 | 0x5*B16 | (dst.code() >> 1)*B12 |
0x5*B9 | B8 | B7 | B6 | src.code()); 0x5*B9 | B8 | B7 | B6 | src.code());
...@@ -1466,7 +1473,7 @@ void Assembler::faddd(const Register dst, ...@@ -1466,7 +1473,7 @@ void Assembler::faddd(const Register dst,
// Instruction details available in ARM DDI 0406A, A8-536. // Instruction details available in ARM DDI 0406A, A8-536.
// cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) | // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
// Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0) // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0)
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 |
dst.code()*B12 | 0x5*B9 | B8 | src2.code()); dst.code()*B12 | 0x5*B9 | B8 | src2.code());
} }
...@@ -1482,7 +1489,7 @@ void Assembler::fsubd(const Register dst, ...@@ -1482,7 +1489,7 @@ void Assembler::fsubd(const Register dst,
// Instruction details available in ARM DDI 0406A, A8-784. // Instruction details available in ARM DDI 0406A, A8-784.
// cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) | // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) |
// Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 1(6) | M=?(5) | 0(4) | Vm(3-0) // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 1(6) | M=?(5) | 0(4) | Vm(3-0)
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 |
dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
} }
...@@ -1498,7 +1505,7 @@ void Assembler::fmuld(const Register dst, ...@@ -1498,7 +1505,7 @@ void Assembler::fmuld(const Register dst,
// Instruction details available in ARM DDI 0406A, A8-784. // Instruction details available in ARM DDI 0406A, A8-784.
// cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) | // cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) |
// Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0) // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0)
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 | emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 |
dst.code()*B12 | 0x5*B9 | B8 | src2.code()); dst.code()*B12 | 0x5*B9 | B8 | src2.code());
} }
...@@ -1514,7 +1521,7 @@ void Assembler::fdivd(const Register dst, ...@@ -1514,7 +1521,7 @@ void Assembler::fdivd(const Register dst,
// Instruction details available in ARM DDI 0406A, A8-584. // Instruction details available in ARM DDI 0406A, A8-584.
// cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) | // cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) |
// Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=? | 0(6) | M=?(5) | 0(4) | Vm(3-0) // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=? | 0(6) | M=?(5) | 0(4) | Vm(3-0)
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(cond | 0xE*B24 | B23 | src1.code()*B16 | emit(cond | 0xE*B24 | B23 | src1.code()*B16 |
dst.code()*B12 | 0x5*B9 | B8 | src2.code()); dst.code()*B12 | 0x5*B9 | B8 | src2.code());
} }
...@@ -1528,7 +1535,7 @@ void Assembler::fcmp(const Register src1, ...@@ -1528,7 +1535,7 @@ void Assembler::fcmp(const Register src1,
// Instruction details available in ARM DDI 0406A, A8-570. // Instruction details available in ARM DDI 0406A, A8-570.
// cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) | // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) |
// Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=? | 1(6) | M(5)=? | 0(4) | Vm(3-0) // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=? | 1(6) | M(5)=? | 0(4) | Vm(3-0)
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 |
src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code());
} }
...@@ -1538,7 +1545,7 @@ void Assembler::vmrs(Register dst, Condition cond) { ...@@ -1538,7 +1545,7 @@ void Assembler::vmrs(Register dst, Condition cond) {
// Instruction details available in ARM DDI 0406A, A8-652. // Instruction details available in ARM DDI 0406A, A8-652.
// cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) | // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) |
// Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0) // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
ASSERT(CpuFeatures::IsEnabled(VFP3));
emit(cond | 0xE*B24 | 0xF*B20 | B16 | emit(cond | 0xE*B24 | 0xF*B20 | B16 |
dst.code()*B12 | 0xA*B8 | B4); dst.code()*B12 | 0xA*B8 | B4);
} }
...@@ -1703,10 +1710,15 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { ...@@ -1703,10 +1710,15 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
} }
if (rinfo.rmode() != RelocInfo::NONE) { if (rinfo.rmode() != RelocInfo::NONE) {
// Don't record external references unless the heap will be serialized. // Don't record external references unless the heap will be serialized.
if (rmode == RelocInfo::EXTERNAL_REFERENCE && if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
!Serializer::enabled() && #ifdef DEBUG
!FLAG_debug_code) { if (!Serializer::enabled()) {
return; Serializer::TooLateToEnableNow();
}
#endif
if (!Serializer::enabled() && !FLAG_debug_code) {
return;
}
} }
ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
reloc_info_writer.Write(&rinfo); reloc_info_writer.Write(&rinfo);
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#define V8_ARM_ASSEMBLER_ARM_H_ #define V8_ARM_ASSEMBLER_ARM_H_
#include <stdio.h> #include <stdio.h>
#include "assembler.h" #include "assembler.h"
#include "serialize.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -427,26 +428,29 @@ class MemOperand BASE_EMBEDDED { ...@@ -427,26 +428,29 @@ class MemOperand BASE_EMBEDDED {
// Supported features must be enabled by a Scope before use. // Supported features must be enabled by a Scope before use.
class CpuFeatures : public AllStatic { class CpuFeatures : public AllStatic {
public: public:
enum Feature { VFP3 = 1 };
// Detect features of the target CPU. Set safe defaults if the serializer // Detect features of the target CPU. Set safe defaults if the serializer
// is enabled (snapshots must be portable). // is enabled (snapshots must be portable).
static void Probe(); static void Probe();
// Check whether a feature is supported by the target CPU. // Check whether a feature is supported by the target CPU.
static bool IsSupported(Feature f) { static bool IsSupported(CpuFeature f) {
if (f == VFP3 && !FLAG_enable_vfp3) return false; if (f == VFP3 && !FLAG_enable_vfp3) return false;
return (supported_ & (1u << f)) != 0; return (supported_ & (1u << f)) != 0;
} }
// Check whether a feature is currently enabled. // Check whether a feature is currently enabled.
static bool IsEnabled(Feature f) { static bool IsEnabled(CpuFeature f) {
return (enabled_ & (1u << f)) != 0; return (enabled_ & (1u << f)) != 0;
} }
// Enable a specified feature within a scope. // Enable a specified feature within a scope.
class Scope BASE_EMBEDDED { class Scope BASE_EMBEDDED {
#ifdef DEBUG #ifdef DEBUG
public: public:
explicit Scope(Feature f) { explicit Scope(CpuFeature f) {
ASSERT(CpuFeatures::IsSupported(f)); ASSERT(CpuFeatures::IsSupported(f));
ASSERT(!Serializer::enabled() ||
(found_by_runtime_probing_ & (1u << f)) == 0);
old_enabled_ = CpuFeatures::enabled_; old_enabled_ = CpuFeatures::enabled_;
CpuFeatures::enabled_ |= 1u << f; CpuFeatures::enabled_ |= 1u << f;
} }
...@@ -455,13 +459,14 @@ class CpuFeatures : public AllStatic { ...@@ -455,13 +459,14 @@ class CpuFeatures : public AllStatic {
unsigned old_enabled_; unsigned old_enabled_;
#else #else
public: public:
explicit Scope(Feature f) {} explicit Scope(CpuFeature f) {}
#endif #endif
}; };
private: private:
static unsigned supported_; static unsigned supported_;
static unsigned enabled_; static unsigned enabled_;
static unsigned found_by_runtime_probing_;
}; };
......
...@@ -4623,8 +4623,8 @@ static void EmitSmiNonsmiComparison(MacroAssembler* masm, ...@@ -4623,8 +4623,8 @@ static void EmitSmiNonsmiComparison(MacroAssembler* masm,
// Rhs is a smi, lhs is a number. // Rhs is a smi, lhs is a number.
__ push(lr); __ push(lr);
if (CpuFeatures::IsSupported(CpuFeatures::VFP3)) { if (CpuFeatures::IsSupported(VFP3)) {
CpuFeatures::Scope scope(CpuFeatures::VFP3); CpuFeatures::Scope scope(VFP3);
__ IntegerToDoubleConversionWithVFP3(r1, r3, r2); __ IntegerToDoubleConversionWithVFP3(r1, r3, r2);
} else { } else {
__ mov(r7, Operand(r1)); __ mov(r7, Operand(r1));
...@@ -4661,8 +4661,8 @@ static void EmitSmiNonsmiComparison(MacroAssembler* masm, ...@@ -4661,8 +4661,8 @@ static void EmitSmiNonsmiComparison(MacroAssembler* masm,
__ ldr(r2, FieldMemOperand(r1, HeapNumber::kValueOffset)); __ ldr(r2, FieldMemOperand(r1, HeapNumber::kValueOffset));
__ ldr(r3, FieldMemOperand(r1, HeapNumber::kValueOffset + kPointerSize)); __ ldr(r3, FieldMemOperand(r1, HeapNumber::kValueOffset + kPointerSize));
if (CpuFeatures::IsSupported(CpuFeatures::VFP3)) { if (CpuFeatures::IsSupported(VFP3)) {
CpuFeatures::Scope scope(CpuFeatures::VFP3); CpuFeatures::Scope scope(VFP3);
__ IntegerToDoubleConversionWithVFP3(r0, r1, r0); __ IntegerToDoubleConversionWithVFP3(r0, r1, r0);
} else { } else {
__ mov(r7, Operand(r0)); __ mov(r7, Operand(r0));
...@@ -4872,8 +4872,8 @@ void CompareStub::Generate(MacroAssembler* masm) { ...@@ -4872,8 +4872,8 @@ void CompareStub::Generate(MacroAssembler* masm) {
// fall through if neither is a NaN. Also binds rhs_not_nan. // fall through if neither is a NaN. Also binds rhs_not_nan.
EmitNanCheck(masm, &rhs_not_nan, cc_); EmitNanCheck(masm, &rhs_not_nan, cc_);
if (CpuFeatures::IsSupported(CpuFeatures::VFP3)) { if (CpuFeatures::IsSupported(VFP3)) {
CpuFeatures::Scope scope(CpuFeatures::VFP3); CpuFeatures::Scope scope(VFP3);
// ARMv7 VFP3 instructions to implement double precision comparison. // ARMv7 VFP3 instructions to implement double precision comparison.
__ fmdrr(d6, r0, r1); __ fmdrr(d6, r0, r1);
__ fmdrr(d7, r2, r3); __ fmdrr(d7, r2, r3);
...@@ -4989,8 +4989,8 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm, ...@@ -4989,8 +4989,8 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm,
// The new heap number is in r5. r6 and r7 are scratch. // The new heap number is in r5. r6 and r7 are scratch.
AllocateHeapNumber(masm, &slow, r5, r6, r7); AllocateHeapNumber(masm, &slow, r5, r6, r7);
if (CpuFeatures::IsSupported(CpuFeatures::VFP3)) { if (CpuFeatures::IsSupported(VFP3)) {
CpuFeatures::Scope scope(CpuFeatures::VFP3); CpuFeatures::Scope scope(VFP3);
__ IntegerToDoubleConversionWithVFP3(r0, r3, r2); __ IntegerToDoubleConversionWithVFP3(r0, r3, r2);
__ IntegerToDoubleConversionWithVFP3(r1, r1, r0); __ IntegerToDoubleConversionWithVFP3(r1, r1, r0);
} else { } else {
...@@ -5043,8 +5043,8 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm, ...@@ -5043,8 +5043,8 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm,
} }
if (CpuFeatures::IsSupported(CpuFeatures::VFP3)) { if (CpuFeatures::IsSupported(VFP3)) {
CpuFeatures::Scope scope(CpuFeatures::VFP3); CpuFeatures::Scope scope(VFP3);
__ IntegerToDoubleConversionWithVFP3(r0, r3, r2); __ IntegerToDoubleConversionWithVFP3(r0, r3, r2);
} else { } else {
// Write Smi from r0 to r3 and r2 in double format. // Write Smi from r0 to r3 and r2 in double format.
...@@ -5075,8 +5075,8 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm, ...@@ -5075,8 +5075,8 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm,
AllocateHeapNumber(masm, &slow, r5, r6, r7); AllocateHeapNumber(masm, &slow, r5, r6, r7);
} }
if (CpuFeatures::IsSupported(CpuFeatures::VFP3)) { if (CpuFeatures::IsSupported(VFP3)) {
CpuFeatures::Scope scope(CpuFeatures::VFP3); CpuFeatures::Scope scope(VFP3);
__ IntegerToDoubleConversionWithVFP3(r1, r1, r0); __ IntegerToDoubleConversionWithVFP3(r1, r1, r0);
} else { } else {
// Write Smi from r1 to r1 and r0 in double format. // Write Smi from r1 to r1 and r0 in double format.
...@@ -5096,12 +5096,12 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm, ...@@ -5096,12 +5096,12 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm,
// r3: Right value (sign, exponent, top of mantissa). // r3: Right value (sign, exponent, top of mantissa).
// r5: Address of heap number for result. // r5: Address of heap number for result.
if (CpuFeatures::IsSupported(CpuFeatures::VFP3) && if (CpuFeatures::IsSupported(VFP3) &&
((Token::MUL == operation) || ((Token::MUL == operation) ||
(Token::DIV == operation) || (Token::DIV == operation) ||
(Token::ADD == operation) || (Token::ADD == operation) ||
(Token::SUB == operation))) { (Token::SUB == operation))) {
CpuFeatures::Scope scope(CpuFeatures::VFP3); CpuFeatures::Scope scope(VFP3);
// ARMv7 VFP3 instructions to implement // ARMv7 VFP3 instructions to implement
// double precision, add, subtract, multiply, divide. // double precision, add, subtract, multiply, divide.
__ fmdrr(d6, r0, r1); __ fmdrr(d6, r0, r1);
...@@ -5195,7 +5195,7 @@ static void GetInt32(MacroAssembler* masm, ...@@ -5195,7 +5195,7 @@ static void GetInt32(MacroAssembler* masm,
__ sub(scratch2, scratch2, Operand(zero_exponent), SetCC); __ sub(scratch2, scratch2, Operand(zero_exponent), SetCC);
// Dest already has a Smi zero. // Dest already has a Smi zero.
__ b(lt, &done); __ b(lt, &done);
if (!CpuFeatures::IsSupported(CpuFeatures::VFP3)) { if (!CpuFeatures::IsSupported(VFP3)) {
// We have a shifted exponent between 0 and 30 in scratch2. // We have a shifted exponent between 0 and 30 in scratch2.
__ mov(dest, Operand(scratch2, LSR, HeapNumber::kExponentShift)); __ mov(dest, Operand(scratch2, LSR, HeapNumber::kExponentShift));
// We now have the exponent in dest. Subtract from 30 to get // We now have the exponent in dest. Subtract from 30 to get
...@@ -5203,8 +5203,8 @@ static void GetInt32(MacroAssembler* masm, ...@@ -5203,8 +5203,8 @@ static void GetInt32(MacroAssembler* masm,
__ rsb(dest, dest, Operand(30)); __ rsb(dest, dest, Operand(30));
} }
__ bind(&right_exponent); __ bind(&right_exponent);
if (CpuFeatures::IsSupported(CpuFeatures::VFP3)) { if (CpuFeatures::IsSupported(VFP3)) {
CpuFeatures::Scope scope(CpuFeatures::VFP3); CpuFeatures::Scope scope(VFP3);
// ARMv7 VFP3 instructions implementing double precision to integer // ARMv7 VFP3 instructions implementing double precision to integer
// conversion using round to zero. // conversion using round to zero.
__ ldr(scratch2, FieldMemOperand(source, HeapNumber::kMantissaOffset)); __ ldr(scratch2, FieldMemOperand(source, HeapNumber::kMantissaOffset));
......
...@@ -576,6 +576,17 @@ inline Dest bit_cast(const Source& source) { ...@@ -576,6 +576,17 @@ inline Dest bit_cast(const Source& source) {
} }
// Feature flags bit positions. They are mostly based on the CPUID spec.
// (We assign CPUID itself to one of the currently reserved bits --
// feel free to change this if needed.)
enum CpuFeature { SSE3 = 32, // x86
SSE2 = 26, // x86
CMOV = 15, // x86
RDTSC = 4, // x86
CPUID = 10, // x86
VFP3 = 1, // ARM
SAHF = 0}; // x86
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_GLOBALS_H_ #endif // V8_GLOBALS_H_
...@@ -49,6 +49,7 @@ namespace internal { ...@@ -49,6 +49,7 @@ namespace internal {
// Safe default is no features. // Safe default is no features.
uint64_t CpuFeatures::supported_ = 0; uint64_t CpuFeatures::supported_ = 0;
uint64_t CpuFeatures::enabled_ = 0; uint64_t CpuFeatures::enabled_ = 0;
uint64_t CpuFeatures::found_by_runtime_probing_ = 0;
// The Probe method needs executable memory, so it uses Heap::CreateCode. // The Probe method needs executable memory, so it uses Heap::CreateCode.
...@@ -56,7 +57,10 @@ uint64_t CpuFeatures::enabled_ = 0; ...@@ -56,7 +57,10 @@ uint64_t CpuFeatures::enabled_ = 0;
void CpuFeatures::Probe() { void CpuFeatures::Probe() {
ASSERT(Heap::HasBeenSetup()); ASSERT(Heap::HasBeenSetup());
ASSERT(supported_ == 0); ASSERT(supported_ == 0);
if (Serializer::enabled()) return; // No features if we might serialize. if (Serializer::enabled()) {
supported_ |= OS::CpuFeaturesImpliedByPlatform();
return; // No features if we might serialize.
}
Assembler assm(NULL, 0); Assembler assm(NULL, 0);
Label cpuid, done; Label cpuid, done;
...@@ -124,6 +128,10 @@ void CpuFeatures::Probe() { ...@@ -124,6 +128,10 @@ void CpuFeatures::Probe() {
typedef uint64_t (*F0)(); typedef uint64_t (*F0)();
F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry()); F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
supported_ = probe(); supported_ = probe();
found_by_runtime_probing_ = supported_;
uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
supported_ |= os_guarantees;
found_by_runtime_probing_ &= ~os_guarantees;
} }
...@@ -360,7 +368,7 @@ void Assembler::Align(int m) { ...@@ -360,7 +368,7 @@ void Assembler::Align(int m) {
void Assembler::cpuid() { void Assembler::cpuid() {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CPUID)); ASSERT(CpuFeatures::IsEnabled(CPUID));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0x0F); EMIT(0x0F);
...@@ -712,7 +720,7 @@ void Assembler::movzx_w(Register dst, const Operand& src) { ...@@ -712,7 +720,7 @@ void Assembler::movzx_w(Register dst, const Operand& src) {
void Assembler::cmov(Condition cc, Register dst, int32_t imm32) { void Assembler::cmov(Condition cc, Register dst, int32_t imm32) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV)); ASSERT(CpuFeatures::IsEnabled(CMOV));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
UNIMPLEMENTED(); UNIMPLEMENTED();
...@@ -723,7 +731,7 @@ void Assembler::cmov(Condition cc, Register dst, int32_t imm32) { ...@@ -723,7 +731,7 @@ void Assembler::cmov(Condition cc, Register dst, int32_t imm32) {
void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) { void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV)); ASSERT(CpuFeatures::IsEnabled(CMOV));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
UNIMPLEMENTED(); UNIMPLEMENTED();
...@@ -734,7 +742,7 @@ void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) { ...@@ -734,7 +742,7 @@ void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) {
void Assembler::cmov(Condition cc, Register dst, const Operand& src) { void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CMOV)); ASSERT(CpuFeatures::IsEnabled(CMOV));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
// Opcode: 0f 40 + cc /r // Opcode: 0f 40 + cc /r
...@@ -1316,7 +1324,7 @@ void Assembler::nop() { ...@@ -1316,7 +1324,7 @@ void Assembler::nop() {
void Assembler::rdtsc() { void Assembler::rdtsc() {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::RDTSC)); ASSERT(CpuFeatures::IsEnabled(RDTSC));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0x0F); EMIT(0x0F);
...@@ -1662,7 +1670,7 @@ void Assembler::fistp_s(const Operand& adr) { ...@@ -1662,7 +1670,7 @@ void Assembler::fistp_s(const Operand& adr) {
void Assembler::fisttp_s(const Operand& adr) { void Assembler::fisttp_s(const Operand& adr) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE3)); ASSERT(CpuFeatures::IsEnabled(SSE3));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0xDB); EMIT(0xDB);
...@@ -1923,7 +1931,7 @@ void Assembler::setcc(Condition cc, Register reg) { ...@@ -1923,7 +1931,7 @@ void Assembler::setcc(Condition cc, Register reg) {
void Assembler::cvttss2si(Register dst, const Operand& src) { void Assembler::cvttss2si(Register dst, const Operand& src) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2)); ASSERT(CpuFeatures::IsEnabled(SSE2));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0xF3); EMIT(0xF3);
...@@ -1934,7 +1942,7 @@ void Assembler::cvttss2si(Register dst, const Operand& src) { ...@@ -1934,7 +1942,7 @@ void Assembler::cvttss2si(Register dst, const Operand& src) {
void Assembler::cvttsd2si(Register dst, const Operand& src) { void Assembler::cvttsd2si(Register dst, const Operand& src) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2)); ASSERT(CpuFeatures::IsEnabled(SSE2));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0xF2); EMIT(0xF2);
...@@ -1945,7 +1953,7 @@ void Assembler::cvttsd2si(Register dst, const Operand& src) { ...@@ -1945,7 +1953,7 @@ void Assembler::cvttsd2si(Register dst, const Operand& src) {
void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) { void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2)); ASSERT(CpuFeatures::IsEnabled(SSE2));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0xF2); EMIT(0xF2);
...@@ -1956,7 +1964,7 @@ void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) { ...@@ -1956,7 +1964,7 @@ void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
void Assembler::addsd(XMMRegister dst, XMMRegister src) { void Assembler::addsd(XMMRegister dst, XMMRegister src) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2)); ASSERT(CpuFeatures::IsEnabled(SSE2));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0xF2); EMIT(0xF2);
...@@ -1967,7 +1975,7 @@ void Assembler::addsd(XMMRegister dst, XMMRegister src) { ...@@ -1967,7 +1975,7 @@ void Assembler::addsd(XMMRegister dst, XMMRegister src) {
void Assembler::mulsd(XMMRegister dst, XMMRegister src) { void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2)); ASSERT(CpuFeatures::IsEnabled(SSE2));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0xF2); EMIT(0xF2);
...@@ -1978,7 +1986,7 @@ void Assembler::mulsd(XMMRegister dst, XMMRegister src) { ...@@ -1978,7 +1986,7 @@ void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
void Assembler::subsd(XMMRegister dst, XMMRegister src) { void Assembler::subsd(XMMRegister dst, XMMRegister src) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2)); ASSERT(CpuFeatures::IsEnabled(SSE2));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0xF2); EMIT(0xF2);
...@@ -1989,7 +1997,7 @@ void Assembler::subsd(XMMRegister dst, XMMRegister src) { ...@@ -1989,7 +1997,7 @@ void Assembler::subsd(XMMRegister dst, XMMRegister src) {
void Assembler::divsd(XMMRegister dst, XMMRegister src) { void Assembler::divsd(XMMRegister dst, XMMRegister src) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2)); ASSERT(CpuFeatures::IsEnabled(SSE2));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0xF2); EMIT(0xF2);
...@@ -2000,7 +2008,7 @@ void Assembler::divsd(XMMRegister dst, XMMRegister src) { ...@@ -2000,7 +2008,7 @@ void Assembler::divsd(XMMRegister dst, XMMRegister src) {
void Assembler::comisd(XMMRegister dst, XMMRegister src) { void Assembler::comisd(XMMRegister dst, XMMRegister src) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2)); ASSERT(CpuFeatures::IsEnabled(SSE2));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0x66); EMIT(0x66);
...@@ -2025,7 +2033,7 @@ void Assembler::movdbl(const Operand& dst, XMMRegister src) { ...@@ -2025,7 +2033,7 @@ void Assembler::movdbl(const Operand& dst, XMMRegister src) {
void Assembler::movsd(const Operand& dst, XMMRegister src ) { void Assembler::movsd(const Operand& dst, XMMRegister src ) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2)); ASSERT(CpuFeatures::IsEnabled(SSE2));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0xF2); // double EMIT(0xF2); // double
...@@ -2036,7 +2044,7 @@ void Assembler::movsd(const Operand& dst, XMMRegister src ) { ...@@ -2036,7 +2044,7 @@ void Assembler::movsd(const Operand& dst, XMMRegister src ) {
void Assembler::movsd(XMMRegister dst, const Operand& src) { void Assembler::movsd(XMMRegister dst, const Operand& src) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2)); ASSERT(CpuFeatures::IsEnabled(SSE2));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
EMIT(0xF2); // double EMIT(0xF2); // double
...@@ -2245,10 +2253,15 @@ void Assembler::dd(uint32_t data, RelocInfo::Mode reloc_info) { ...@@ -2245,10 +2253,15 @@ void Assembler::dd(uint32_t data, RelocInfo::Mode reloc_info) {
void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
ASSERT(rmode != RelocInfo::NONE); ASSERT(rmode != RelocInfo::NONE);
// Don't record external references unless the heap will be serialized. // Don't record external references unless the heap will be serialized.
if (rmode == RelocInfo::EXTERNAL_REFERENCE && if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
!Serializer::enabled() && #ifdef DEBUG
!FLAG_debug_code) { if (!Serializer::enabled()) {
return; Serializer::TooLateToEnableNow();
}
#endif
if (!Serializer::enabled() && !FLAG_debug_code) {
return;
}
} }
RelocInfo rinfo(pc_, rmode, data); RelocInfo rinfo(pc_, rmode, data);
reloc_info_writer.Write(&rinfo); reloc_info_writer.Write(&rinfo);
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#ifndef V8_IA32_ASSEMBLER_IA32_H_ #ifndef V8_IA32_ASSEMBLER_IA32_H_
#define V8_IA32_ASSEMBLER_IA32_H_ #define V8_IA32_ASSEMBLER_IA32_H_
#include "serialize.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -358,15 +360,11 @@ class Displacement BASE_EMBEDDED { ...@@ -358,15 +360,11 @@ class Displacement BASE_EMBEDDED {
// } // }
class CpuFeatures : public AllStatic { class CpuFeatures : public AllStatic {
public: public:
// Feature flags bit positions. They are mostly based on the CPUID spec.
// (We assign CPUID itself to one of the currently reserved bits --
// feel free to change this if needed.)
enum Feature { SSE3 = 32, SSE2 = 26, CMOV = 15, RDTSC = 4, CPUID = 10 };
// Detect features of the target CPU. Set safe defaults if the serializer // Detect features of the target CPU. Set safe defaults if the serializer
// is enabled (snapshots must be portable). // is enabled (snapshots must be portable).
static void Probe(); static void Probe();
// Check whether a feature is supported by the target CPU. // Check whether a feature is supported by the target CPU.
static bool IsSupported(Feature f) { static bool IsSupported(CpuFeature f) {
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 == CMOV && !FLAG_enable_cmov) return false; if (f == CMOV && !FLAG_enable_cmov) return false;
...@@ -374,29 +372,32 @@ class CpuFeatures : public AllStatic { ...@@ -374,29 +372,32 @@ class CpuFeatures : public AllStatic {
return (supported_ & (static_cast<uint64_t>(1) << f)) != 0; return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
} }
// Check whether a feature is currently enabled. // Check whether a feature is currently enabled.
static bool IsEnabled(Feature f) { static bool IsEnabled(CpuFeature f) {
return (enabled_ & (static_cast<uint64_t>(1) << f)) != 0; return (enabled_ & (static_cast<uint64_t>(1) << f)) != 0;
} }
// Enable a specified feature within a scope. // Enable a specified feature within a scope.
class Scope BASE_EMBEDDED { class Scope BASE_EMBEDDED {
#ifdef DEBUG #ifdef DEBUG
public: public:
explicit Scope(Feature f) { explicit Scope(CpuFeature f) {
uint64_t mask = static_cast<uint64_t>(1) << f;
ASSERT(CpuFeatures::IsSupported(f)); ASSERT(CpuFeatures::IsSupported(f));
ASSERT(!Serializer::enabled() || (found_by_runtime_probing_ & mask) == 0);
old_enabled_ = CpuFeatures::enabled_; old_enabled_ = CpuFeatures::enabled_;
CpuFeatures::enabled_ |= (static_cast<uint64_t>(1) << f); CpuFeatures::enabled_ |= mask;
} }
~Scope() { CpuFeatures::enabled_ = old_enabled_; } ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
private: private:
uint64_t old_enabled_; uint64_t old_enabled_;
#else #else
public: public:
explicit Scope(Feature f) {} explicit Scope(CpuFeature f) {}
#endif #endif
}; };
private: private:
static uint64_t supported_; static uint64_t supported_;
static uint64_t enabled_; static uint64_t enabled_;
static uint64_t found_by_runtime_probing_;
}; };
......
...@@ -6751,8 +6751,8 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { ...@@ -6751,8 +6751,8 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
// eax: y // eax: y
// edx: x // edx: x
if (CpuFeatures::IsSupported(CpuFeatures::SSE2)) { if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatures::Scope use_sse2(CpuFeatures::SSE2); CpuFeatures::Scope use_sse2(SSE2);
FloatingPointHelper::LoadSse2Operands(masm, &call_runtime); FloatingPointHelper::LoadSse2Operands(masm, &call_runtime);
switch (op_) { switch (op_) {
...@@ -6847,7 +6847,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { ...@@ -6847,7 +6847,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
if (use_sse3_) { if (use_sse3_) {
// Truncate the operands to 32-bit integers and check for // Truncate the operands to 32-bit integers and check for
// exceptions in doing so. // exceptions in doing so.
CpuFeatures::Scope scope(CpuFeatures::SSE3); CpuFeatures::Scope scope(SSE3);
__ fisttp_s(Operand(esp, 0 * kPointerSize)); __ fisttp_s(Operand(esp, 0 * kPointerSize));
__ fisttp_s(Operand(esp, 1 * kPointerSize)); __ fisttp_s(Operand(esp, 1 * kPointerSize));
__ fnstsw_ax(); __ fnstsw_ax();
...@@ -7474,9 +7474,9 @@ void CompareStub::Generate(MacroAssembler* masm) { ...@@ -7474,9 +7474,9 @@ void CompareStub::Generate(MacroAssembler* masm) {
// Call builtin if operands are not floating point or smi. // Call builtin if operands are not floating point or smi.
Label check_for_symbols; Label check_for_symbols;
Label unordered; Label unordered;
if (CpuFeatures::IsSupported(CpuFeatures::SSE2)) { if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatures::Scope use_sse2(CpuFeatures::SSE2); CpuFeatures::Scope use_sse2(SSE2);
CpuFeatures::Scope use_cmov(CpuFeatures::CMOV); CpuFeatures::Scope use_cmov(CMOV);
FloatingPointHelper::LoadSse2Operands(masm, &check_for_symbols); FloatingPointHelper::LoadSse2Operands(masm, &check_for_symbols);
__ comisd(xmm0, xmm1); __ comisd(xmm0, xmm1);
......
...@@ -658,7 +658,7 @@ class GenericBinaryOpStub: public CodeStub { ...@@ -658,7 +658,7 @@ class GenericBinaryOpStub: public CodeStub {
flags_(flags), flags_(flags),
args_in_registers_(false), args_in_registers_(false),
args_reversed_(false) { args_reversed_(false) {
use_sse3_ = CpuFeatures::IsSupported(CpuFeatures::SSE3); use_sse3_ = CpuFeatures::IsSupported(SSE3);
ASSERT(OpBits::is_valid(Token::NUM_TOKENS)); ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
} }
......
...@@ -319,7 +319,7 @@ void MacroAssembler::CmpInstanceType(Register map, InstanceType type) { ...@@ -319,7 +319,7 @@ void MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
void MacroAssembler::FCmp() { void MacroAssembler::FCmp() {
if (CpuFeatures::IsSupported(CpuFeatures::CMOV)) { if (CpuFeatures::IsSupported(CMOV)) {
fucomip(); fucomip();
ffree(0); ffree(0);
fincstp(); fincstp();
......
...@@ -84,6 +84,11 @@ void OS::Setup() { ...@@ -84,6 +84,11 @@ void OS::Setup() {
} }
uint64_t OS::CpuFeaturesImpliedByPlatform() {
return 0; // FreeBSD runs on anything.
}
double OS::nan_value() { double OS::nan_value() {
return NAN; return NAN;
} }
......
...@@ -84,12 +84,24 @@ void OS::Setup() { ...@@ -84,12 +84,24 @@ void OS::Setup() {
} }
uint64_t OS::CpuFeaturesImpliedByPlatform() {
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
// Here gcc is telling us that we are on an ARM and gcc is assuming that we
// have VFP3 instructions. If gcc can assume it then so can we.
return 1u << VFP3;
#else
return 0; // Linux runs on anything.
#endif
}
double OS::nan_value() { double OS::nan_value() {
return NAN; return NAN;
} }
bool OS::ArmCpuHasFeature(OS::CpuFeature feature) { #ifdef __arm__
bool OS::ArmCpuHasFeature(CpuFeature feature) {
const char* search_string = NULL; const char* search_string = NULL;
const char* file_name = "/proc/cpuinfo"; const char* file_name = "/proc/cpuinfo";
// Simple detection of VFP at runtime for Linux. // Simple detection of VFP at runtime for Linux.
...@@ -103,7 +115,7 @@ bool OS::ArmCpuHasFeature(OS::CpuFeature feature) { ...@@ -103,7 +115,7 @@ bool OS::ArmCpuHasFeature(OS::CpuFeature feature) {
// on Linux, it's reading from a (non-mmap-able) // on Linux, it's reading from a (non-mmap-able)
// character special device. // character special device.
switch (feature) { switch (feature) {
case VFP: case VFP3:
search_string = "vfp"; search_string = "vfp";
break; break;
default: default:
...@@ -136,6 +148,7 @@ bool OS::ArmCpuHasFeature(OS::CpuFeature feature) { ...@@ -136,6 +148,7 @@ bool OS::ArmCpuHasFeature(OS::CpuFeature feature) {
// Did not find string in the proc file. // Did not find string in the proc file.
return false; return false;
} }
#endif // def __arm__
int OS::ActivationFrameAlignment() { int OS::ActivationFrameAlignment() {
......
...@@ -244,6 +244,14 @@ void OS::LogSharedLibraryAddresses() { ...@@ -244,6 +244,14 @@ void OS::LogSharedLibraryAddresses() {
} }
uint64_t OS::CpuFeaturesImpliedByPlatform() {
// MacOSX requires all these to install so we can assume they are present.
// These constants are defined by the CPUid instructions.
const uint64_t one = 1;
return (one << SSE2) | (one << CMOV) | (one << RDTSC) | (one << CPUID);
}
double OS::nan_value() { double OS::nan_value() {
return NAN; return NAN;
} }
......
...@@ -150,13 +150,18 @@ int OS::VSNPrintF(char* str, size_t size, const char* format, va_list args) { ...@@ -150,13 +150,18 @@ int OS::VSNPrintF(char* str, size_t size, const char* format, va_list args) {
} }
uint64_t OS::CpuFeaturesImpliedByPlatform() {
return 0;
}
double OS::nan_value() { double OS::nan_value() {
UNIMPLEMENTED(); UNIMPLEMENTED();
return 0; return 0;
} }
bool OS::ArmCpuHasFeature(OS:CpuFeature feature) { bool OS::ArmCpuHasFeature(CpuFeature feature) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
......
...@@ -1316,6 +1316,11 @@ int OS::StackWalk(Vector<OS::StackFrame> frames) { return 0; } ...@@ -1316,6 +1316,11 @@ int OS::StackWalk(Vector<OS::StackFrame> frames) { return 0; }
#endif // __MINGW32__ #endif // __MINGW32__
uint64_t OS::CpuFeaturesImpliedByPlatform() {
return 0; // Windows runs on anything.
}
double OS::nan_value() { double OS::nan_value() {
#ifdef _MSC_VER #ifdef _MSC_VER
// Positive Quiet NaN with no payload (aka. Indeterminate) has all bits // Positive Quiet NaN with no payload (aka. Indeterminate) has all bits
......
...@@ -247,11 +247,18 @@ class OS { ...@@ -247,11 +247,18 @@ class OS {
// for. // for.
static void LogSharedLibraryAddresses(); static void LogSharedLibraryAddresses();
// The return value indicates the CPU features we are sure of because of the
// OS. For example MacOSX doesn't run on any x86 CPUs that don't have SSE2
// instructions.
// This is a little messy because the interpretation is subject to the cross
// of the CPU and the OS. The bits in the answer correspond to the bit
// positions indicated by the members of the CpuFeature enum from globals.h
static uint64_t CpuFeaturesImpliedByPlatform();
// Returns the double constant NAN // Returns the double constant NAN
static double nan_value(); static double nan_value();
// Support runtime detection of VFP3 on ARM CPUs. // Support runtime detection of VFP3 on ARM CPUs.
enum CpuFeature { VFP };
static bool ArmCpuHasFeature(CpuFeature feature); static bool ArmCpuHasFeature(CpuFeature feature);
// Returns the activation frame alignment constraint or zero if // Returns the activation frame alignment constraint or zero if
......
...@@ -1048,6 +1048,7 @@ Serializer::~Serializer() { ...@@ -1048,6 +1048,7 @@ Serializer::~Serializer() {
bool Serializer::serialization_enabled_ = false; bool Serializer::serialization_enabled_ = false;
bool Serializer::too_late_to_enable_now_ = false;
#ifdef DEBUG #ifdef DEBUG
......
...@@ -148,8 +148,17 @@ class Serializer: public ObjectVisitor { ...@@ -148,8 +148,17 @@ class Serializer: public ObjectVisitor {
static bool enabled() { return serialization_enabled_; } static bool enabled() { return serialization_enabled_; }
static void Enable() { serialization_enabled_ = true; } static void Enable() {
if (!serialization_enabled_) {
ASSERT(!too_late_to_enable_now_);
}
serialization_enabled_ = true;
}
static void Disable() { serialization_enabled_ = false; } static void Disable() { serialization_enabled_ = false; }
// Call this when you have made use of the fact that there is no serialization
// going on.
static void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
private: private:
friend class ReferenceUpdater; friend class ReferenceUpdater;
...@@ -194,6 +203,8 @@ class Serializer: public ObjectVisitor { ...@@ -194,6 +203,8 @@ class Serializer: public ObjectVisitor {
int objects_; // number of objects serialized int objects_; // number of objects serialized
static bool serialization_enabled_; static bool serialization_enabled_;
// Did we already make use of the fact that serialization was not enabled?
static bool too_late_to_enable_now_;
int flags_end_; // The position right after the flags. int flags_end_; // The position right after the flags.
......
...@@ -80,11 +80,15 @@ XMMRegister xmm15 = { 15 }; ...@@ -80,11 +80,15 @@ XMMRegister xmm15 = { 15 };
// fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall // fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall
uint64_t CpuFeatures::supported_ = kDefaultCpuFeatures; uint64_t CpuFeatures::supported_ = kDefaultCpuFeatures;
uint64_t CpuFeatures::enabled_ = 0; uint64_t CpuFeatures::enabled_ = 0;
uint64_t CpuFeatures::found_by_runtime_probing_ = 0;
void CpuFeatures::Probe() { void CpuFeatures::Probe() {
ASSERT(Heap::HasBeenSetup()); ASSERT(Heap::HasBeenSetup());
ASSERT(supported_ == kDefaultCpuFeatures); ASSERT(supported_ == kDefaultCpuFeatures);
if (Serializer::enabled()) return; // No features if we might serialize. if (Serializer::enabled()) {
supported_ |= OS::CpuFeaturesImpliedByPlatform();
return; // No features if we might serialize.
}
Assembler assm(NULL, 0); Assembler assm(NULL, 0);
Label cpuid, done; Label cpuid, done;
...@@ -160,6 +164,11 @@ void CpuFeatures::Probe() { ...@@ -160,6 +164,11 @@ void CpuFeatures::Probe() {
typedef uint64_t (*F0)(); typedef uint64_t (*F0)();
F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry()); F0 probe = FUNCTION_CAST<F0>(Code::cast(code)->entry());
supported_ = probe(); supported_ = probe();
found_by_runtime_probing_ = supported_;
found_by_runtime_probing_ &= ~kDefaultCpuFeatures;
uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
supported_ |= os_guarantees;
found_by_runtime_probing_ &= ~os_guarantees;
// SSE2 and CMOV must be available on an X64 CPU. // SSE2 and CMOV must be available on an X64 CPU.
ASSERT(IsSupported(CPUID)); ASSERT(IsSupported(CPUID));
ASSERT(IsSupported(SSE2)); ASSERT(IsSupported(SSE2));
...@@ -889,7 +898,7 @@ void Assembler::cmpb_al(Immediate imm8) { ...@@ -889,7 +898,7 @@ void Assembler::cmpb_al(Immediate imm8) {
void Assembler::cpuid() { void Assembler::cpuid() {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CPUID)); ASSERT(CpuFeatures::IsEnabled(CPUID));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
emit(0x0F); emit(0x0F);
...@@ -2047,7 +2056,7 @@ void Assembler::fistp_s(const Operand& adr) { ...@@ -2047,7 +2056,7 @@ void Assembler::fistp_s(const Operand& adr) {
void Assembler::fisttp_s(const Operand& adr) { void Assembler::fisttp_s(const Operand& adr) {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE3)); ASSERT(CpuFeatures::IsEnabled(SSE3));
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
emit_optional_rex_32(adr); emit_optional_rex_32(adr);
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#ifndef V8_X64_ASSEMBLER_X64_H_ #ifndef V8_X64_ASSEMBLER_X64_H_
#define V8_X64_ASSEMBLER_X64_H_ #define V8_X64_ASSEMBLER_X64_H_
#include "serialize.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -362,20 +364,11 @@ class Operand BASE_EMBEDDED { ...@@ -362,20 +364,11 @@ class Operand BASE_EMBEDDED {
// } // }
class CpuFeatures : public AllStatic { class CpuFeatures : public AllStatic {
public: public:
// Feature flags bit positions. They are mostly based on the CPUID spec.
// (We assign CPUID itself to one of the currently reserved bits --
// feel free to change this if needed.)
enum Feature { SSE3 = 32,
SSE2 = 26,
CMOV = 15,
RDTSC = 4,
CPUID = 10,
SAHF = 0};
// Detect features of the target CPU. Set safe defaults if the serializer // Detect features of the target CPU. Set safe defaults if the serializer
// is enabled (snapshots must be portable). // is enabled (snapshots must be portable).
static void Probe(); static void Probe();
// Check whether a feature is supported by the target CPU. // Check whether a feature is supported by the target CPU.
static bool IsSupported(Feature f) { static bool IsSupported(CpuFeature f) {
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 == CMOV && !FLAG_enable_cmov) return false; if (f == CMOV && !FLAG_enable_cmov) return false;
...@@ -384,33 +377,35 @@ class CpuFeatures : public AllStatic { ...@@ -384,33 +377,35 @@ class CpuFeatures : public AllStatic {
return (supported_ & (V8_UINT64_C(1) << f)) != 0; return (supported_ & (V8_UINT64_C(1) << f)) != 0;
} }
// Check whether a feature is currently enabled. // Check whether a feature is currently enabled.
static bool IsEnabled(Feature f) { static bool IsEnabled(CpuFeature f) {
return (enabled_ & (V8_UINT64_C(1) << f)) != 0; return (enabled_ & (V8_UINT64_C(1) << f)) != 0;
} }
// Enable a specified feature within a scope. // Enable a specified feature within a scope.
class Scope BASE_EMBEDDED { class Scope BASE_EMBEDDED {
#ifdef DEBUG #ifdef DEBUG
public: public:
explicit Scope(Feature f) { explicit Scope(CpuFeature f) {
uint64_t mask = (V8_UINT64_C(1) << f);
ASSERT(CpuFeatures::IsSupported(f)); ASSERT(CpuFeatures::IsSupported(f));
ASSERT(!Serializer::enabled() || (found_by_runtime_probing_ & mask) == 0);
old_enabled_ = CpuFeatures::enabled_; old_enabled_ = CpuFeatures::enabled_;
CpuFeatures::enabled_ |= (V8_UINT64_C(1) << f); CpuFeatures::enabled_ |= mask;
} }
~Scope() { CpuFeatures::enabled_ = old_enabled_; } ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
private: private:
uint64_t old_enabled_; uint64_t old_enabled_;
#else #else
public: public:
explicit Scope(Feature f) {} explicit Scope(CpuFeature f) {}
#endif #endif
}; };
private: private:
// Safe defaults include SSE2 and CMOV for X64. It is always available, if // Safe defaults include SSE2 and 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.
static const uint64_t kDefaultCpuFeatures = static const uint64_t kDefaultCpuFeatures = (1 << SSE2 | 1 << CMOV);
(1 << CpuFeatures::SSE2 | 1 << CpuFeatures::CMOV);
static uint64_t supported_; static uint64_t supported_;
static uint64_t enabled_; static uint64_t enabled_;
static uint64_t found_by_runtime_probing_;
}; };
......
...@@ -7566,7 +7566,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { ...@@ -7566,7 +7566,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
if (use_sse3_) { if (use_sse3_) {
// Truncate the operands to 32-bit integers and check for // Truncate the operands to 32-bit integers and check for
// exceptions in doing so. // exceptions in doing so.
CpuFeatures::Scope scope(CpuFeatures::SSE3); CpuFeatures::Scope scope(SSE3);
__ fisttp_s(Operand(rsp, 0 * kPointerSize)); __ fisttp_s(Operand(rsp, 0 * kPointerSize));
__ fisttp_s(Operand(rsp, 1 * kPointerSize)); __ fisttp_s(Operand(rsp, 1 * kPointerSize));
__ fnstsw_ax(); __ fnstsw_ax();
......
...@@ -665,7 +665,7 @@ class GenericBinaryOpStub: public CodeStub { ...@@ -665,7 +665,7 @@ class GenericBinaryOpStub: public CodeStub {
flags_(flags), flags_(flags),
args_in_registers_(false), args_in_registers_(false),
args_reversed_(false) { args_reversed_(false) {
use_sse3_ = CpuFeatures::IsSupported(CpuFeatures::SSE3); use_sse3_ = CpuFeatures::IsSupported(SSE3);
ASSERT(OpBits::is_valid(Token::NUM_TOKENS)); ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
} }
......
...@@ -47,10 +47,6 @@ test-serialize/DependentTestThatAlwaysFails: FAIL ...@@ -47,10 +47,6 @@ test-serialize/DependentTestThatAlwaysFails: FAIL
[ $arch == arm ] [ $arch == arm ]
# New serialization doesn't work on ARM yet.
test-serialize/Deserialize2: SKIP
test-serialize/DeserializeAndRunScript2: SKIP
# BUG(240): Test seems flaky on ARM. # BUG(240): Test seems flaky on ARM.
test-api/RegExpInterruption: SKIP test-api/RegExpInterruption: SKIP
......
...@@ -173,8 +173,8 @@ TEST(AssemblerIa323) { ...@@ -173,8 +173,8 @@ TEST(AssemblerIa323) {
v8::internal::byte buffer[256]; v8::internal::byte buffer[256];
Assembler assm(buffer, sizeof buffer); Assembler assm(buffer, sizeof buffer);
CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2)); CHECK(CpuFeatures::IsSupported(SSE2));
{ CpuFeatures::Scope fscope(CpuFeatures::SSE2); { CpuFeatures::Scope fscope(SSE2);
__ cvttss2si(eax, Operand(esp, 4)); __ cvttss2si(eax, Operand(esp, 4));
__ ret(0); __ ret(0);
} }
...@@ -207,8 +207,8 @@ TEST(AssemblerIa324) { ...@@ -207,8 +207,8 @@ TEST(AssemblerIa324) {
v8::internal::byte buffer[256]; v8::internal::byte buffer[256];
Assembler assm(buffer, sizeof buffer); Assembler assm(buffer, sizeof buffer);
CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2)); CHECK(CpuFeatures::IsSupported(SSE2));
CpuFeatures::Scope fscope(CpuFeatures::SSE2); CpuFeatures::Scope fscope(SSE2);
__ cvttsd2si(eax, Operand(esp, 4)); __ cvttsd2si(eax, Operand(esp, 4));
__ ret(0); __ ret(0);
...@@ -260,8 +260,8 @@ typedef double (*F5)(double x, double y); ...@@ -260,8 +260,8 @@ typedef double (*F5)(double x, double y);
TEST(AssemblerIa326) { TEST(AssemblerIa326) {
InitializeVM(); InitializeVM();
v8::HandleScope scope; v8::HandleScope scope;
CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2)); CHECK(CpuFeatures::IsSupported(SSE2));
CpuFeatures::Scope fscope(CpuFeatures::SSE2); CpuFeatures::Scope fscope(SSE2);
v8::internal::byte buffer[256]; v8::internal::byte buffer[256];
Assembler assm(buffer, sizeof buffer); Assembler assm(buffer, sizeof buffer);
...@@ -305,8 +305,8 @@ typedef double (*F6)(int x); ...@@ -305,8 +305,8 @@ typedef double (*F6)(int x);
TEST(AssemblerIa328) { TEST(AssemblerIa328) {
InitializeVM(); InitializeVM();
v8::HandleScope scope; v8::HandleScope scope;
CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2)); CHECK(CpuFeatures::IsSupported(SSE2));
CpuFeatures::Scope fscope(CpuFeatures::SSE2); CpuFeatures::Scope fscope(SSE2);
v8::internal::byte buffer[256]; v8::internal::byte buffer[256];
Assembler assm(buffer, sizeof buffer); Assembler assm(buffer, sizeof buffer);
__ mov(eax, Operand(esp, 4)); __ mov(eax, Operand(esp, 4));
......
...@@ -105,13 +105,13 @@ TEST(DisasmIa320) { ...@@ -105,13 +105,13 @@ TEST(DisasmIa320) {
__ xor_(edx, 3); __ xor_(edx, 3);
__ nop(); __ nop();
{ {
CHECK(CpuFeatures::IsSupported(CpuFeatures::CPUID)); CHECK(CpuFeatures::IsSupported(CPUID));
CpuFeatures::Scope fscope(CpuFeatures::CPUID); CpuFeatures::Scope fscope(CPUID);
__ cpuid(); __ cpuid();
} }
{ {
CHECK(CpuFeatures::IsSupported(CpuFeatures::RDTSC)); CHECK(CpuFeatures::IsSupported(RDTSC));
CpuFeatures::Scope fscope(CpuFeatures::RDTSC); CpuFeatures::Scope fscope(RDTSC);
__ rdtsc(); __ rdtsc();
} }
__ movsx_b(edx, Operand(ecx)); __ movsx_b(edx, Operand(ecx));
...@@ -353,8 +353,8 @@ TEST(DisasmIa320) { ...@@ -353,8 +353,8 @@ TEST(DisasmIa320) {
__ fwait(); __ fwait();
__ nop(); __ nop();
{ {
CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2)); CHECK(CpuFeatures::IsSupported(SSE2));
CpuFeatures::Scope fscope(CpuFeatures::SSE2); CpuFeatures::Scope fscope(SSE2);
__ cvttss2si(edx, Operand(ebx, ecx, times_4, 10000)); __ cvttss2si(edx, Operand(ebx, ecx, times_4, 10000));
__ cvtsi2sd(xmm1, Operand(ebx, ecx, times_4, 10000)); __ cvtsi2sd(xmm1, Operand(ebx, ecx, times_4, 10000));
__ addsd(xmm1, xmm0); __ addsd(xmm1, xmm0);
...@@ -368,8 +368,8 @@ TEST(DisasmIa320) { ...@@ -368,8 +368,8 @@ TEST(DisasmIa320) {
// cmov. // cmov.
{ {
CHECK(CpuFeatures::IsSupported(CpuFeatures::CMOV)); CHECK(CpuFeatures::IsSupported(CMOV));
CpuFeatures::Scope use_cmov(CpuFeatures::CMOV); CpuFeatures::Scope use_cmov(CMOV);
__ cmov(overflow, eax, Operand(eax, 0)); __ cmov(overflow, eax, Operand(eax, 0));
__ cmov(no_overflow, eax, Operand(eax, 1)); __ cmov(no_overflow, eax, Operand(eax, 1));
__ cmov(below, eax, Operand(eax, 2)); __ cmov(below, eax, Operand(eax, 2));
......
...@@ -192,7 +192,6 @@ static void Serialize() { ...@@ -192,7 +192,6 @@ static void Serialize() {
static void Serialize2() { static void Serialize2() {
Serializer::Enable();
// We have to create one context. One reason for this is so that the builtins // We have to create one context. One reason for this is so that the builtins
// can be loaded from v8natives.js and their addresses can be processed. This // can be loaded from v8natives.js and their addresses can be processed. This
// will clear the pending fixups array, which would otherwise contain GC roots // will clear the pending fixups array, which would otherwise contain GC roots
...@@ -214,6 +213,7 @@ TEST(Serialize) { ...@@ -214,6 +213,7 @@ TEST(Serialize) {
// Test that the whole heap can be serialized. // Test that the whole heap can be serialized.
TEST(Serialize2) { TEST(Serialize2) {
Serializer::Enable();
v8::V8::Initialize(); v8::V8::Initialize();
Serialize2(); Serialize2();
} }
......
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