Upgrade V8 to version 4.9.385.28
https://chromium.googlesource.com/v8/v8/+/4.9.385.28
FPIIM-449
Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/test/cctest/compiler/c-signature.h b/test/cctest/compiler/c-signature.h
index 5d161db..13ef38a 100644
--- a/test/cctest/compiler/c-signature.h
+++ b/test/cctest/compiler/c-signature.h
@@ -5,86 +5,121 @@
#ifndef V8_COMPILER_C_SIGNATURE_H_
#define V8_COMPILER_C_SIGNATURE_H_
-#include "src/compiler/machine-type.h"
+#include "src/machine-type.h"
namespace v8 {
namespace internal {
namespace compiler {
+#define FOREACH_CTYPE_MACHINE_TYPE_MAPPING(V) \
+ V(void, MachineType::None()) \
+ V(bool, MachineType::Uint8()) \
+ V(int8_t, MachineType::Int8()) \
+ V(uint8_t, MachineType::Uint8()) \
+ V(int16_t, MachineType::Int16()) \
+ V(uint16_t, MachineType::Uint16()) \
+ V(int32_t, MachineType::Int32()) \
+ V(uint32_t, MachineType::Uint32()) \
+ V(int64_t, MachineType::Int64()) \
+ V(uint64_t, MachineType::Uint64()) \
+ V(float, MachineType::Float32()) \
+ V(double, MachineType::Float64()) \
+ V(void*, MachineType::Pointer()) \
+ V(int*, MachineType::Pointer())
+
template <typename T>
inline MachineType MachineTypeForC() {
- CHECK(false); // Instantiated with invalid type.
- return kMachNone;
+ while (false) {
+ // All other types T must be assignable to Object*
+ *(static_cast<Object* volatile*>(0)) = static_cast<T>(0);
+ }
+ return MachineType::AnyTagged();
}
-template <>
-inline MachineType MachineTypeForC<void>() {
- return kMachNone;
-}
+#define DECLARE_TEMPLATE_SPECIALIZATION(ctype, mtype) \
+ template <> \
+ inline MachineType MachineTypeForC<ctype>() { \
+ return mtype; \
+ }
+FOREACH_CTYPE_MACHINE_TYPE_MAPPING(DECLARE_TEMPLATE_SPECIALIZATION)
+#undef DECLARE_TEMPLATE_SPECIALIZATION
-template <>
-inline MachineType MachineTypeForC<int8_t>() {
- return kMachInt8;
-}
+// Helper for building machine signatures from C types.
+class CSignature : public MachineSignature {
+ protected:
+ CSignature(size_t return_count, size_t parameter_count, MachineType* reps)
+ : MachineSignature(return_count, parameter_count, reps) {}
-template <>
-inline MachineType MachineTypeForC<uint8_t>() {
- return kMachUint8;
-}
+ public:
+ template <typename P1 = void, typename P2 = void, typename P3 = void,
+ typename P4 = void, typename P5 = void>
+ void VerifyParams() {
+ // Verifies the C signature against the machine types. Maximum {5} params.
+ CHECK_LT(parameter_count(), 6u);
+ const int kMax = 5;
+ MachineType params[] = {MachineTypeForC<P1>(), MachineTypeForC<P2>(),
+ MachineTypeForC<P3>(), MachineTypeForC<P4>(),
+ MachineTypeForC<P5>()};
+ for (int p = kMax - 1; p >= 0; p--) {
+ if (p < static_cast<int>(parameter_count())) {
+ CHECK_EQ(GetParam(p), params[p]);
+ } else {
+ CHECK_EQ(MachineType::None(), params[p]);
+ }
+ }
+ }
-template <>
-inline MachineType MachineTypeForC<int16_t>() {
- return kMachInt16;
-}
+ static CSignature* FromMachine(Zone* zone, MachineSignature* msig) {
+ return reinterpret_cast<CSignature*>(msig);
+ }
-template <>
-inline MachineType MachineTypeForC<uint16_t>() {
- return kMachUint16;
-}
+ static CSignature* New(Zone* zone, MachineType ret,
+ MachineType p1 = MachineType::None(),
+ MachineType p2 = MachineType::None(),
+ MachineType p3 = MachineType::None(),
+ MachineType p4 = MachineType::None(),
+ MachineType p5 = MachineType::None()) {
+ MachineType* buffer = zone->NewArray<MachineType>(6);
+ int pos = 0;
+ size_t return_count = 0;
+ if (ret != MachineType::None()) {
+ buffer[pos++] = ret;
+ return_count++;
+ }
+ buffer[pos++] = p1;
+ buffer[pos++] = p2;
+ buffer[pos++] = p3;
+ buffer[pos++] = p4;
+ buffer[pos++] = p5;
+ size_t param_count = 5;
+ if (p5 == MachineType::None()) param_count--;
+ if (p4 == MachineType::None()) param_count--;
+ if (p3 == MachineType::None()) param_count--;
+ if (p2 == MachineType::None()) param_count--;
+ if (p1 == MachineType::None()) param_count--;
+ for (size_t i = 0; i < param_count; i++) {
+ // Check that there are no MachineType::None()'s in the middle of
+ // parameters.
+ CHECK_NE(MachineType::None(), buffer[return_count + i]);
+ }
+ return new (zone) CSignature(return_count, param_count, buffer);
+ }
+};
-template <>
-inline MachineType MachineTypeForC<int32_t>() {
- return kMachInt32;
-}
-
-template <>
-inline MachineType MachineTypeForC<uint32_t>() {
- return kMachUint32;
-}
-
-template <>
-inline MachineType MachineTypeForC<int64_t>() {
- return kMachInt64;
-}
-
-template <>
-inline MachineType MachineTypeForC<uint64_t>() {
- return kMachUint64;
-}
-
-template <>
-inline MachineType MachineTypeForC<double>() {
- return kMachFloat64;
-}
-
-template <>
-inline MachineType MachineTypeForC<Object*>() {
- return kMachAnyTagged;
-}
template <typename Ret, uint16_t kParamCount>
-class CSignatureOf : public MachineSignature {
+class CSignatureOf : public CSignature {
protected:
MachineType storage_[1 + kParamCount];
CSignatureOf()
- : MachineSignature(MachineTypeForC<Ret>() != kMachNone ? 1 : 0,
- kParamCount,
- reinterpret_cast<MachineType*>(&storage_)) {
+ : CSignature(MachineTypeForC<Ret>() != MachineType::None() ? 1 : 0,
+ kParamCount, reinterpret_cast<MachineType*>(&storage_)) {
if (return_count_ == 1) storage_[0] = MachineTypeForC<Ret>();
}
void Set(int index, MachineType type) {
- DCHECK(index >= 0 && index < kParamCount);
+ CHECK_LE(0, index);
+ CHECK_LT(index, kParamCount);
reps_[return_count_ + index] = type;
}
};
@@ -123,11 +158,13 @@
}
};
-static const CSignature2<int32_t, int32_t, int32_t> int32_int32_to_int32;
-static const CSignature2<uint32_t, uint32_t, uint32_t> uint32_uint32_to_uint32;
-static const CSignature2<double, double, double> float64_float64_to_float64;
-}
-}
-} // namespace v8::internal::compiler
+typedef CSignature2<int32_t, int32_t, int32_t> CSignature_i_ii;
+typedef CSignature2<uint32_t, uint32_t, uint32_t> CSignature_u_uu;
+typedef CSignature2<float, float, float> CSignature_f_ff;
+typedef CSignature2<double, double, double> CSignature_d_dd;
+typedef CSignature2<Object*, Object*, Object*> CSignature_o_oo;
+} // namespace compiler
+} // namespace internal
+} // namespace v8
#endif // V8_COMPILER_C_SIGNATURE_H_
diff --git a/test/cctest/compiler/call-tester.h b/test/cctest/compiler/call-tester.h
index cad171e..e60f717 100644
--- a/test/cctest/compiler/call-tester.h
+++ b/test/cctest/compiler/call-tester.h
@@ -5,9 +5,8 @@
#ifndef V8_CCTEST_COMPILER_CALL_TESTER_H_
#define V8_CCTEST_COMPILER_CALL_TESTER_H_
-#include "src/v8.h"
-
#include "src/simulator.h"
+#include "test/cctest/compiler/c-signature.h"
#if V8_TARGET_ARCH_IA32
#if __GNUC__
@@ -23,95 +22,64 @@
namespace internal {
namespace compiler {
-// TODO(titzer): use c-signature.h instead of ReturnValueTraits
template <typename R>
-struct ReturnValueTraits {
- static R Cast(uintptr_t r) { return reinterpret_cast<R>(r); }
- static MachineType Representation() {
- // TODO(dcarney): detect when R is of a subclass of Object* instead of this
- // type check.
- while (false) {
- *(static_cast<Object* volatile*>(0)) = static_cast<R>(0);
- }
- return kMachAnyTagged;
- }
-};
+inline R CastReturnValue(uintptr_t r) {
+ return reinterpret_cast<R>(r);
+}
template <>
-struct ReturnValueTraits<int32_t*> {
- static int32_t* Cast(uintptr_t r) { return reinterpret_cast<int32_t*>(r); }
- static MachineType Representation() { return kMachPtr; }
-};
+inline void CastReturnValue(uintptr_t r) {}
template <>
-struct ReturnValueTraits<void> {
- static void Cast(uintptr_t r) {}
- static MachineType Representation() { return kMachPtr; }
-};
+inline bool CastReturnValue(uintptr_t r) {
+ return static_cast<bool>(r);
+}
template <>
-struct ReturnValueTraits<bool> {
- static bool Cast(uintptr_t r) { return static_cast<bool>(r); }
- static MachineType Representation() { return kRepBit; }
-};
+inline int32_t CastReturnValue(uintptr_t r) {
+ return static_cast<int32_t>(r);
+}
template <>
-struct ReturnValueTraits<int32_t> {
- static int32_t Cast(uintptr_t r) { return static_cast<int32_t>(r); }
- static MachineType Representation() { return kMachInt32; }
-};
+inline uint32_t CastReturnValue(uintptr_t r) {
+ return static_cast<uint32_t>(r);
+}
template <>
-struct ReturnValueTraits<uint32_t> {
- static uint32_t Cast(uintptr_t r) { return static_cast<uint32_t>(r); }
- static MachineType Representation() { return kMachUint32; }
-};
+inline int64_t CastReturnValue(uintptr_t r) {
+ return static_cast<int64_t>(r);
+}
template <>
-struct ReturnValueTraits<int64_t> {
- static int64_t Cast(uintptr_t r) { return static_cast<int64_t>(r); }
- static MachineType Representation() { return kMachInt64; }
-};
+inline uint64_t CastReturnValue(uintptr_t r) {
+ return static_cast<uint64_t>(r);
+}
template <>
-struct ReturnValueTraits<uint64_t> {
- static uint64_t Cast(uintptr_t r) { return static_cast<uint64_t>(r); }
- static MachineType Representation() { return kMachUint64; }
-};
+inline int16_t CastReturnValue(uintptr_t r) {
+ return static_cast<int16_t>(r);
+}
template <>
-struct ReturnValueTraits<int16_t> {
- static int16_t Cast(uintptr_t r) { return static_cast<int16_t>(r); }
- static MachineType Representation() { return kMachInt16; }
-};
+inline uint16_t CastReturnValue(uintptr_t r) {
+ return static_cast<uint16_t>(r);
+}
template <>
-struct ReturnValueTraits<uint16_t> {
- static uint16_t Cast(uintptr_t r) { return static_cast<uint16_t>(r); }
- static MachineType Representation() { return kMachUint16; }
-};
+inline int8_t CastReturnValue(uintptr_t r) {
+ return static_cast<int8_t>(r);
+}
template <>
-struct ReturnValueTraits<int8_t> {
- static int8_t Cast(uintptr_t r) { return static_cast<int8_t>(r); }
- static MachineType Representation() { return kMachInt8; }
-};
+inline uint8_t CastReturnValue(uintptr_t r) {
+ return static_cast<uint8_t>(r);
+}
template <>
-struct ReturnValueTraits<uint8_t> {
- static uint8_t Cast(uintptr_t r) { return static_cast<uint8_t>(r); }
- static MachineType Representation() { return kMachUint8; }
-};
-
-template <>
-struct ReturnValueTraits<double> {
- static double Cast(uintptr_t r) {
- UNREACHABLE();
- return 0.0;
- }
- static MachineType Representation() { return kMachFloat64; }
-};
-
+inline double CastReturnValue(uintptr_t r) {
+ UNREACHABLE();
+ return 0.0;
+}
template <typename R>
struct ParameterTraits {
@@ -128,42 +96,79 @@
static uintptr_t Cast(void* r) { return reinterpret_cast<uintptr_t>(r); }
};
+
+#if !V8_TARGET_ARCH_32_BIT
+
+// Additional template specialization required for mips64 to sign-extend
+// parameters defined by calling convention.
+template <>
+struct ParameterTraits<int32_t> {
+ static int64_t Cast(int32_t r) { return static_cast<int64_t>(r); }
+};
+
+template <>
+struct ParameterTraits<uint32_t> {
+ static int64_t Cast(uint32_t r) {
+ return static_cast<int64_t>(static_cast<int32_t>(r));
+ }
+};
+
+#endif // !V8_TARGET_ARCH_64_BIT
+
+
+template <typename R>
class CallHelper {
public:
- explicit CallHelper(Isolate* isolate, MachineSignature* machine_sig)
- : machine_sig_(machine_sig), isolate_(isolate) {
+ explicit CallHelper(Isolate* isolate, CSignature* csig)
+ : csig_(csig), isolate_(isolate) {
USE(isolate_);
}
virtual ~CallHelper() {}
- static MachineSignature* MakeMachineSignature(
- Zone* zone, MachineType return_type, MachineType p0 = kMachNone,
- MachineType p1 = kMachNone, MachineType p2 = kMachNone,
- MachineType p3 = kMachNone, MachineType p4 = kMachNone) {
- // Count the number of parameters.
- size_t param_count = 5;
- MachineType types[] = {p0, p1, p2, p3, p4};
- while (param_count > 0 && types[param_count - 1] == kMachNone)
- param_count--;
- size_t return_count = return_type == kMachNone ? 0 : 1;
+ R Call() {
+ typedef R V8_CDECL FType();
+ csig_->VerifyParams();
+ return DoCall(FUNCTION_CAST<FType*>(Generate()));
+ }
- // Build the machine signature.
- MachineSignature::Builder builder(zone, return_count, param_count);
- if (return_count > 0) builder.AddReturn(return_type);
- for (size_t i = 0; i < param_count; i++) {
- builder.AddParam(types[i]);
- }
- return builder.Build();
+ template <typename P1>
+ R Call(P1 p1) {
+ typedef R V8_CDECL FType(P1);
+ csig_->VerifyParams<P1>();
+ return DoCall(FUNCTION_CAST<FType*>(Generate()), p1);
+ }
+
+ template <typename P1, typename P2>
+ R Call(P1 p1, P2 p2) {
+ typedef R V8_CDECL FType(P1, P2);
+ csig_->VerifyParams<P1, P2>();
+ return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2);
+ }
+
+ template <typename P1, typename P2, typename P3>
+ R Call(P1 p1, P2 p2, P3 p3) {
+ typedef R V8_CDECL FType(P1, P2, P3);
+ csig_->VerifyParams<P1, P2, P3>();
+ return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3);
+ }
+
+ template <typename P1, typename P2, typename P3, typename P4>
+ R Call(P1 p1, P2 p2, P3 p3, P4 p4) {
+ typedef R V8_CDECL FType(P1, P2, P3, P4);
+ csig_->VerifyParams<P1, P2, P3, P4>();
+ return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4);
+ }
+
+ template <typename P1, typename P2, typename P3, typename P4, typename P5>
+ R Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
+ typedef R V8_CDECL FType(P1, P2, P3, P4, P5);
+ csig_->VerifyParams<P1, P2, P3, P4, P5>();
+ return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4, p5);
}
protected:
- MachineSignature* machine_sig_;
- void VerifyParameters(size_t parameter_count, MachineType* parameter_types) {
- CHECK(machine_sig_->parameter_count() == parameter_count);
- for (size_t i = 0; i < parameter_count; i++) {
- CHECK_EQ(machine_sig_->GetParam(i), parameter_types[i]);
- }
- }
+ CSignature* csig_;
+
virtual byte* Generate() = 0;
private:
@@ -173,255 +178,181 @@
return static_cast<uintptr_t>(simulator->CallInt64(f, args));
}
- template <typename R, typename F>
+ template <typename F>
R DoCall(F* f) {
Simulator::CallArgument args[] = {Simulator::CallArgument::End()};
- return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
+ return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f), args));
}
- template <typename R, typename F, typename P1>
+ template <typename F, typename P1>
R DoCall(F* f, P1 p1) {
Simulator::CallArgument args[] = {Simulator::CallArgument(p1),
Simulator::CallArgument::End()};
- return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
+ return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f), args));
}
- template <typename R, typename F, typename P1, typename P2>
+ template <typename F, typename P1, typename P2>
R DoCall(F* f, P1 p1, P2 p2) {
Simulator::CallArgument args[] = {Simulator::CallArgument(p1),
Simulator::CallArgument(p2),
Simulator::CallArgument::End()};
- return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
+ return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f), args));
}
- template <typename R, typename F, typename P1, typename P2, typename P3>
+ template <typename F, typename P1, typename P2, typename P3>
R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
Simulator::CallArgument args[] = {
Simulator::CallArgument(p1), Simulator::CallArgument(p2),
Simulator::CallArgument(p3), Simulator::CallArgument::End()};
- return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
+ return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f), args));
}
- template <typename R, typename F, typename P1, typename P2, typename P3,
- typename P4>
+ template <typename F, typename P1, typename P2, typename P3, typename P4>
R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
Simulator::CallArgument args[] = {
Simulator::CallArgument(p1), Simulator::CallArgument(p2),
Simulator::CallArgument(p3), Simulator::CallArgument(p4),
Simulator::CallArgument::End()};
- return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
+ return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f), args));
}
-#elif USE_SIMULATOR && V8_TARGET_ARCH_MIPS64
+ template <typename F, typename P1, typename P2, typename P3, typename P4,
+ typename P5>
+ R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
+ Simulator::CallArgument args[] = {
+ Simulator::CallArgument(p1), Simulator::CallArgument(p2),
+ Simulator::CallArgument(p3), Simulator::CallArgument(p4),
+ Simulator::CallArgument(p5), Simulator::CallArgument::End()};
+ return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f), args));
+ }
+#elif USE_SIMULATOR && (V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64)
uintptr_t CallSimulator(byte* f, int64_t p1 = 0, int64_t p2 = 0,
- int64_t p3 = 0, int64_t p4 = 0) {
+ int64_t p3 = 0, int64_t p4 = 0, int64_t p5 = 0) {
Simulator* simulator = Simulator::current(isolate_);
- return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4));
+ return static_cast<uintptr_t>(simulator->Call(f, 5, p1, p2, p3, p4, p5));
}
- template <typename R, typename F>
+
+ template <typename F>
R DoCall(F* f) {
- return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
+ return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f)));
}
- template <typename R, typename F, typename P1>
+ template <typename F, typename P1>
R DoCall(F* f, P1 p1) {
- return ReturnValueTraits<R>::Cast(
+ return CastReturnValue<R>(
CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1)));
}
- template <typename R, typename F, typename P1, typename P2>
+ template <typename F, typename P1, typename P2>
R DoCall(F* f, P1 p1, P2 p2) {
- return ReturnValueTraits<R>::Cast(
- CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
- ParameterTraits<P2>::Cast(p2)));
+ return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f),
+ ParameterTraits<P1>::Cast(p1),
+ ParameterTraits<P2>::Cast(p2)));
}
- template <typename R, typename F, typename P1, typename P2, typename P3>
+ template <typename F, typename P1, typename P2, typename P3>
R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
- return ReturnValueTraits<R>::Cast(CallSimulator(
+ return CastReturnValue<R>(CallSimulator(
FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3)));
}
- template <typename R, typename F, typename P1, typename P2, typename P3,
- typename P4>
+ template <typename F, typename P1, typename P2, typename P3, typename P4>
R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
- return ReturnValueTraits<R>::Cast(CallSimulator(
+ return CastReturnValue<R>(CallSimulator(
FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3),
ParameterTraits<P4>::Cast(p4)));
}
-#elif USE_SIMULATOR && (V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS)
+ template <typename F, typename P1, typename P2, typename P3, typename P4,
+ typename P5>
+ R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
+ return CastReturnValue<R>(CallSimulator(
+ FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
+ ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3),
+ ParameterTraits<P4>::Cast(p4), ParameterTraits<P5>::Cast(p5)));
+ }
+#elif USE_SIMULATOR && \
+ (V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_PPC)
uintptr_t CallSimulator(byte* f, int32_t p1 = 0, int32_t p2 = 0,
- int32_t p3 = 0, int32_t p4 = 0) {
+ int32_t p3 = 0, int32_t p4 = 0, int32_t p5 = 0) {
Simulator* simulator = Simulator::current(isolate_);
- return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4));
+ return static_cast<uintptr_t>(simulator->Call(f, 5, p1, p2, p3, p4, p5));
}
- template <typename R, typename F>
+ template <typename F>
R DoCall(F* f) {
- return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
+ return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f)));
}
- template <typename R, typename F, typename P1>
+ template <typename F, typename P1>
R DoCall(F* f, P1 p1) {
- return ReturnValueTraits<R>::Cast(
+ return CastReturnValue<R>(
CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1)));
}
- template <typename R, typename F, typename P1, typename P2>
+ template <typename F, typename P1, typename P2>
R DoCall(F* f, P1 p1, P2 p2) {
- return ReturnValueTraits<R>::Cast(
- CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
- ParameterTraits<P2>::Cast(p2)));
+ return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f),
+ ParameterTraits<P1>::Cast(p1),
+ ParameterTraits<P2>::Cast(p2)));
}
- template <typename R, typename F, typename P1, typename P2, typename P3>
+ template <typename F, typename P1, typename P2, typename P3>
R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
- return ReturnValueTraits<R>::Cast(CallSimulator(
+ return CastReturnValue<R>(CallSimulator(
FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3)));
}
- template <typename R, typename F, typename P1, typename P2, typename P3,
- typename P4>
+ template <typename F, typename P1, typename P2, typename P3, typename P4>
R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
- return ReturnValueTraits<R>::Cast(CallSimulator(
+ return CastReturnValue<R>(CallSimulator(
FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3),
ParameterTraits<P4>::Cast(p4)));
}
+ template <typename F, typename P1, typename P2, typename P3, typename P4,
+ typename P5>
+ R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
+ return CastReturnValue<R>(CallSimulator(
+ FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
+ ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3),
+ ParameterTraits<P4>::Cast(p4), ParameterTraits<P5>::Cast(p5)));
+ }
#else
- template <typename R, typename F>
+ template <typename F>
R DoCall(F* f) {
return f();
}
- template <typename R, typename F, typename P1>
+ template <typename F, typename P1>
R DoCall(F* f, P1 p1) {
return f(p1);
}
- template <typename R, typename F, typename P1, typename P2>
+ template <typename F, typename P1, typename P2>
R DoCall(F* f, P1 p1, P2 p2) {
return f(p1, p2);
}
- template <typename R, typename F, typename P1, typename P2, typename P3>
+ template <typename F, typename P1, typename P2, typename P3>
R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
return f(p1, p2, p3);
}
- template <typename R, typename F, typename P1, typename P2, typename P3,
- typename P4>
+ template <typename F, typename P1, typename P2, typename P3, typename P4>
R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
return f(p1, p2, p3, p4);
}
-#endif
-
-#ifndef DEBUG
- void VerifyParameters0() {}
-
- template <typename P1>
- void VerifyParameters1() {}
-
- template <typename P1, typename P2>
- void VerifyParameters2() {}
-
- template <typename P1, typename P2, typename P3>
- void VerifyParameters3() {}
-
- template <typename P1, typename P2, typename P3, typename P4>
- void VerifyParameters4() {}
-#else
- void VerifyParameters0() { VerifyParameters(0, NULL); }
-
- template <typename P1>
- void VerifyParameters1() {
- MachineType parameters[] = {ReturnValueTraits<P1>::Representation()};
- VerifyParameters(arraysize(parameters), parameters);
- }
-
- template <typename P1, typename P2>
- void VerifyParameters2() {
- MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
- ReturnValueTraits<P2>::Representation()};
- VerifyParameters(arraysize(parameters), parameters);
- }
-
- template <typename P1, typename P2, typename P3>
- void VerifyParameters3() {
- MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
- ReturnValueTraits<P2>::Representation(),
- ReturnValueTraits<P3>::Representation()};
- VerifyParameters(arraysize(parameters), parameters);
- }
-
- template <typename P1, typename P2, typename P3, typename P4>
- void VerifyParameters4() {
- MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
- ReturnValueTraits<P2>::Representation(),
- ReturnValueTraits<P3>::Representation(),
- ReturnValueTraits<P4>::Representation()};
- VerifyParameters(arraysize(parameters), parameters);
+ template <typename F, typename P1, typename P2, typename P3, typename P4,
+ typename P5>
+ R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
+ return f(p1, p2, p3, p4, p5);
}
#endif
- // TODO(dcarney): replace Call() in CallHelper2 with these.
- template <typename R>
- R Call0() {
- typedef R V8_CDECL FType();
- VerifyParameters0();
- return DoCall<R>(FUNCTION_CAST<FType*>(Generate()));
- }
-
- template <typename R, typename P1>
- R Call1(P1 p1) {
- typedef R V8_CDECL FType(P1);
- VerifyParameters1<P1>();
- return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1);
- }
-
- template <typename R, typename P1, typename P2>
- R Call2(P1 p1, P2 p2) {
- typedef R V8_CDECL FType(P1, P2);
- VerifyParameters2<P1, P2>();
- return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2);
- }
-
- template <typename R, typename P1, typename P2, typename P3>
- R Call3(P1 p1, P2 p2, P3 p3) {
- typedef R V8_CDECL FType(P1, P2, P3);
- VerifyParameters3<P1, P2, P3>();
- return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3);
- }
-
- template <typename R, typename P1, typename P2, typename P3, typename P4>
- R Call4(P1 p1, P2 p2, P3 p3, P4 p4) {
- typedef R V8_CDECL FType(P1, P2, P3, P4);
- VerifyParameters4<P1, P2, P3, P4>();
- return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4);
- }
-
- template <typename R, typename C>
- friend class CallHelper2;
Isolate* isolate_;
};
-
-// TODO(dcarney): replace CallHelper with CallHelper2 and rename.
-template <typename R, typename C>
-class CallHelper2 {
+// A call helper that calls the given code object assuming C calling convention.
+template <typename T>
+class CodeRunner : public CallHelper<T> {
public:
- R Call() { return helper()->template Call0<R>(); }
+ CodeRunner(Isolate* isolate, Handle<Code> code, CSignature* csig)
+ : CallHelper<T>(isolate, csig), code_(code) {}
+ virtual ~CodeRunner() {}
- template <typename P1>
- R Call(P1 p1) {
- return helper()->template Call1<R>(p1);
- }
-
- template <typename P1, typename P2>
- R Call(P1 p1, P2 p2) {
- return helper()->template Call2<R>(p1, p2);
- }
-
- template <typename P1, typename P2, typename P3>
- R Call(P1 p1, P2 p2, P3 p3) {
- return helper()->template Call3<R>(p1, p2, p3);
- }
-
- template <typename P1, typename P2, typename P3, typename P4>
- R Call(P1 p1, P2 p2, P3 p3, P4 p4) {
- return helper()->template Call4<R>(p1, p2, p3, p4);
- }
+ virtual byte* Generate() { return code_->entry(); }
private:
- CallHelper* helper() { return static_cast<C*>(this); }
+ Handle<Code> code_;
};
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/test/cctest/compiler/codegen-tester.cc b/test/cctest/compiler/codegen-tester.cc
index 5311001..fc0956f 100644
--- a/test/cctest/compiler/codegen-tester.cc
+++ b/test/cctest/compiler/codegen-tester.cc
@@ -2,14 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
#include "test/cctest/compiler/value-helper.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
TEST(CompareWrapper) {
// Who tests the testers?
@@ -141,7 +140,7 @@
CompareWrapper wFloat64LessThanOrEqual(IrOpcode::kFloat64LessThanOrEqual);
// Check NaN handling.
- double nan = v8::base::OS::nan_value();
+ double nan = std::numeric_limits<double>::quiet_NaN();
double inf = V8_INFINITY;
CHECK_EQ(false, wFloat64Equal.Float64Compare(nan, 0.0));
CHECK_EQ(false, wFloat64Equal.Float64Compare(nan, 1.0));
@@ -292,7 +291,8 @@
for (int i = -2; i < num_int_inputs; i++) { // for all left shapes
for (int j = -2; j < num_int_inputs; j++) { // for all right shapes
if (i >= 0 && j >= 0) break; // No constant/constant combos
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+ MachineType::Int32());
Node* p0 = m.Parameter(0);
Node* p1 = m.Parameter(1);
Node* n0;
@@ -302,7 +302,7 @@
if (i == -2) {
n0 = p0;
} else if (i == -1) {
- n0 = m.LoadFromPointer(&input_a, kMachInt32);
+ n0 = m.LoadFromPointer(&input_a, MachineType::Int32());
} else {
n0 = m.Int32Constant(inputs[i]);
}
@@ -311,7 +311,7 @@
if (j == -2) {
n1 = p1;
} else if (j == -1) {
- n1 = m.LoadFromPointer(&input_b, kMachInt32);
+ n1 = m.LoadFromPointer(&input_b, MachineType::Int32());
} else {
n1 = m.Int32Constant(inputs[j]);
}
@@ -368,14 +368,13 @@
}
-#if V8_TURBOFAN_TARGET
-
TEST(ParametersEqual) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+ MachineType::Int32());
Node* p1 = m.Parameter(1);
- CHECK_NE(NULL, p1);
+ CHECK(p1);
Node* p0 = m.Parameter(0);
- CHECK_NE(NULL, p0);
+ CHECK(p0);
CHECK_EQ(p0, m.Parameter(0));
CHECK_EQ(p1, m.Parameter(1));
}
@@ -485,7 +484,7 @@
TEST(RunParam1) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
m.Return(m.Parameter(0));
FOR_INT32_INPUTS(i) {
@@ -496,7 +495,8 @@
TEST(RunParam2_1) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+ MachineType::Int32());
Node* p0 = m.Parameter(0);
Node* p1 = m.Parameter(1);
m.Return(p0);
@@ -510,7 +510,8 @@
TEST(RunParam2_2) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+ MachineType::Int32());
Node* p0 = m.Parameter(0);
Node* p1 = m.Parameter(1);
m.Return(p1);
@@ -525,7 +526,8 @@
TEST(RunParam3) {
for (int i = 0; i < 3; i++) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
Node* nodes[] = {m.Parameter(0), m.Parameter(1), m.Parameter(2)};
m.Return(nodes[i]);
@@ -561,7 +563,7 @@
Float64BinopTester bt(&m);
bt.AddReturn(bt.param0);
- FOR_FLOAT64_INPUTS(i) { CHECK_EQ(*i, bt.call(*i, 9.0)); }
+ FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(*i, bt.call(*i, 9.0)); }
}
{
@@ -569,8 +571,156 @@
Float64BinopTester bt(&m);
bt.AddReturn(bt.param1);
- FOR_FLOAT64_INPUTS(i) { CHECK_EQ(*i, bt.call(-11.25, *i)); }
+ FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(*i, bt.call(-11.25, *i)); }
}
}
-#endif // V8_TURBOFAN_TARGET
+
+#if V8_TARGET_ARCH_64_BIT
+// TODO(ahaas): run int64 tests on all platforms when supported.
+TEST(RunBufferedRawMachineAssemblerTesterTester) {
+ {
+ BufferedRawMachineAssemblerTester<int64_t> m;
+ m.Return(m.Int64Constant(0x12500000000));
+ CHECK_EQ(0x12500000000, m.Call());
+ }
+ {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+ m.Return(m.Parameter(0));
+ FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(*i, m.Call(*i)); }
+ }
+ {
+ BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Int64(),
+ MachineType::Int64());
+ m.Return(m.Int64Add(m.Parameter(0), m.Parameter(1)));
+ FOR_INT64_INPUTS(i) {
+ FOR_INT64_INPUTS(j) {
+ CHECK_EQ(*i + *j, m.Call(*i, *j));
+ CHECK_EQ(*j + *i, m.Call(*j, *i));
+ }
+ }
+ }
+ {
+ BufferedRawMachineAssemblerTester<int64_t> m(
+ MachineType::Int64(), MachineType::Int64(), MachineType::Int64());
+ m.Return(
+ m.Int64Add(m.Int64Add(m.Parameter(0), m.Parameter(1)), m.Parameter(2)));
+ FOR_INT64_INPUTS(i) {
+ FOR_INT64_INPUTS(j) {
+ CHECK_EQ(*i + *i + *j, m.Call(*i, *i, *j));
+ CHECK_EQ(*i + *j + *i, m.Call(*i, *j, *i));
+ CHECK_EQ(*j + *i + *i, m.Call(*j, *i, *i));
+ }
+ }
+ }
+ {
+ BufferedRawMachineAssemblerTester<int64_t> m(
+ MachineType::Int64(), MachineType::Int64(), MachineType::Int64(),
+ MachineType::Int64());
+ m.Return(m.Int64Add(
+ m.Int64Add(m.Int64Add(m.Parameter(0), m.Parameter(1)), m.Parameter(2)),
+ m.Parameter(3)));
+ FOR_INT64_INPUTS(i) {
+ FOR_INT64_INPUTS(j) {
+ CHECK_EQ(*i + *i + *i + *j, m.Call(*i, *i, *i, *j));
+ CHECK_EQ(*i + *i + *j + *i, m.Call(*i, *i, *j, *i));
+ CHECK_EQ(*i + *j + *i + *i, m.Call(*i, *j, *i, *i));
+ CHECK_EQ(*j + *i + *i + *i, m.Call(*j, *i, *i, *i));
+ }
+ }
+ }
+ {
+ BufferedRawMachineAssemblerTester<void> m;
+ int64_t result;
+ m.Store(MachineTypeForC<int64_t>().representation(),
+ m.PointerConstant(&result), m.Int64Constant(0x12500000000),
+ kNoWriteBarrier);
+ m.Return(m.Int32Constant(0));
+ m.Call();
+ CHECK_EQ(0x12500000000, result);
+ }
+ {
+ BufferedRawMachineAssemblerTester<void> m(MachineType::Float64());
+ double result;
+ m.Store(MachineTypeForC<double>().representation(),
+ m.PointerConstant(&result), m.Parameter(0), kNoWriteBarrier);
+ m.Return(m.Int32Constant(0));
+ FOR_FLOAT64_INPUTS(i) {
+ m.Call(*i);
+ CheckDoubleEq(*i, result);
+ }
+ }
+ {
+ BufferedRawMachineAssemblerTester<void> m(MachineType::Int64(),
+ MachineType::Int64());
+ int64_t result;
+ m.Store(MachineTypeForC<int64_t>().representation(),
+ m.PointerConstant(&result),
+ m.Int64Add(m.Parameter(0), m.Parameter(1)), kNoWriteBarrier);
+ m.Return(m.Int32Constant(0));
+ FOR_INT64_INPUTS(i) {
+ FOR_INT64_INPUTS(j) {
+ m.Call(*i, *j);
+ CHECK_EQ(*i + *j, result);
+
+ m.Call(*j, *i);
+ CHECK_EQ(*j + *i, result);
+ }
+ }
+ }
+ {
+ BufferedRawMachineAssemblerTester<void> m(
+ MachineType::Int64(), MachineType::Int64(), MachineType::Int64());
+ int64_t result;
+ m.Store(
+ MachineTypeForC<int64_t>().representation(), m.PointerConstant(&result),
+ m.Int64Add(m.Int64Add(m.Parameter(0), m.Parameter(1)), m.Parameter(2)),
+ kNoWriteBarrier);
+ m.Return(m.Int32Constant(0));
+ FOR_INT64_INPUTS(i) {
+ FOR_INT64_INPUTS(j) {
+ m.Call(*i, *i, *j);
+ CHECK_EQ(*i + *i + *j, result);
+
+ m.Call(*i, *j, *i);
+ CHECK_EQ(*i + *j + *i, result);
+
+ m.Call(*j, *i, *i);
+ CHECK_EQ(*j + *i + *i, result);
+ }
+ }
+ }
+ {
+ BufferedRawMachineAssemblerTester<void> m(
+ MachineType::Int64(), MachineType::Int64(), MachineType::Int64(),
+ MachineType::Int64());
+ int64_t result;
+ m.Store(MachineTypeForC<int64_t>().representation(),
+ m.PointerConstant(&result),
+ m.Int64Add(m.Int64Add(m.Int64Add(m.Parameter(0), m.Parameter(1)),
+ m.Parameter(2)),
+ m.Parameter(3)),
+ kNoWriteBarrier);
+ m.Return(m.Int32Constant(0));
+ FOR_INT64_INPUTS(i) {
+ FOR_INT64_INPUTS(j) {
+ m.Call(*i, *i, *i, *j);
+ CHECK_EQ(*i + *i + *i + *j, result);
+
+ m.Call(*i, *i, *j, *i);
+ CHECK_EQ(*i + *i + *j + *i, result);
+
+ m.Call(*i, *j, *i, *i);
+ CHECK_EQ(*i + *j + *i + *i, result);
+
+ m.Call(*j, *i, *i, *i);
+ CHECK_EQ(*j + *i + *i + *i, result);
+ }
+ }
+ }
+}
+
+#endif
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/codegen-tester.h b/test/cctest/compiler/codegen-tester.h
index 283d533..56e90c6 100644
--- a/test/cctest/compiler/codegen-tester.h
+++ b/test/cctest/compiler/codegen-tester.h
@@ -5,8 +5,6 @@
#ifndef V8_CCTEST_COMPILER_CODEGEN_TESTER_H_
#define V8_CCTEST_COMPILER_CODEGEN_TESTER_H_
-#include "src/v8.h"
-
#include "src/compiler/instruction-selector.h"
#include "src/compiler/pipeline.h"
#include "src/compiler/raw-machine-assembler.h"
@@ -17,38 +15,29 @@
namespace internal {
namespace compiler {
-template <typename MachineAssembler>
-class MachineAssemblerTester : public HandleAndZoneScope,
- public CallHelper,
- public MachineAssembler {
+template <typename ReturnType>
+class RawMachineAssemblerTester : public HandleAndZoneScope,
+ public CallHelper<ReturnType>,
+ public RawMachineAssembler {
public:
- MachineAssemblerTester(MachineType return_type, MachineType p0,
- MachineType p1, MachineType p2, MachineType p3,
- MachineType p4,
- MachineOperatorBuilder::Flags flags =
- MachineOperatorBuilder::Flag::kNoFlags)
+ RawMachineAssemblerTester(MachineType p0 = MachineType::None(),
+ MachineType p1 = MachineType::None(),
+ MachineType p2 = MachineType::None(),
+ MachineType p3 = MachineType::None(),
+ MachineType p4 = MachineType::None())
: HandleAndZoneScope(),
- CallHelper(
+ CallHelper<ReturnType>(
main_isolate(),
- MakeMachineSignature(main_zone(), return_type, p0, p1, p2, p3, p4)),
- MachineAssembler(
- new (main_zone()) Graph(main_zone()),
- MakeMachineSignature(main_zone(), return_type, p0, p1, p2, p3, p4),
- kMachPtr, flags) {}
-
- Node* LoadFromPointer(void* address, MachineType rep, int32_t offset = 0) {
- return this->Load(rep, this->PointerConstant(address),
- this->Int32Constant(offset));
- }
-
- void StoreToPointer(void* address, MachineType rep, Node* node) {
- this->Store(rep, this->PointerConstant(address), node);
- }
-
- Node* StringConstant(const char* string) {
- return this->HeapConstant(
- this->isolate()->factory()->InternalizeUtf8String(string));
- }
+ CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0, p1,
+ p2, p3, p4)),
+ RawMachineAssembler(
+ main_isolate(), new (main_zone()) Graph(main_zone()),
+ Linkage::GetSimplifiedCDescriptor(
+ main_zone(),
+ CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0,
+ p1, p2, p3, p4)),
+ MachineType::PointerRepresentation(),
+ InstructionSelector::SupportedMachineOperatorFlags()) {}
void CheckNumber(double expected, Object* number) {
CHECK(this->isolate()->factory()->NewNumber(expected)->SameValue(number));
@@ -62,14 +51,20 @@
void GenerateCode() { Generate(); }
+ Handle<Code> GetCode() {
+ Generate();
+ return code_.ToHandleChecked();
+ }
+
protected:
virtual byte* Generate() {
if (code_.is_null()) {
Schedule* schedule = this->Export();
CallDescriptor* call_descriptor = this->call_descriptor();
Graph* graph = this->graph();
- code_ =
- Pipeline::GenerateCodeForTesting(call_descriptor, graph, schedule);
+ CompilationInfo info("testing", main_isolate(), main_zone());
+ code_ = Pipeline::GenerateCodeForTesting(&info, call_descriptor, graph,
+ schedule);
}
return this->code_.ToHandleChecked()->entry();
}
@@ -80,40 +75,226 @@
template <typename ReturnType>
-class RawMachineAssemblerTester
- : public MachineAssemblerTester<RawMachineAssembler>,
- public CallHelper2<ReturnType, RawMachineAssemblerTester<ReturnType> > {
+class BufferedRawMachineAssemblerTester
+ : public RawMachineAssemblerTester<int32_t> {
public:
- RawMachineAssemblerTester(MachineType p0 = kMachNone,
- MachineType p1 = kMachNone,
- MachineType p2 = kMachNone,
- MachineType p3 = kMachNone,
- MachineType p4 = kMachNone)
- : MachineAssemblerTester<RawMachineAssembler>(
- ReturnValueTraits<ReturnType>::Representation(), p0, p1, p2, p3, p4,
- InstructionSelector::SupportedMachineOperatorFlags()) {}
+ BufferedRawMachineAssemblerTester(MachineType p0 = MachineType::None(),
+ MachineType p1 = MachineType::None(),
+ MachineType p2 = MachineType::None(),
+ MachineType p3 = MachineType::None())
+ : BufferedRawMachineAssemblerTester(ComputeParameterCount(p0, p1, p2, p3),
+ p0, p1, p2, p3) {}
- template <typename Ci, typename Fn>
- void Run(const Ci& ci, const Fn& fn) {
- typename Ci::const_iterator i;
- for (i = ci.begin(); i != ci.end(); ++i) {
- CHECK_EQ(fn(*i), this->Call(*i));
- }
+
+ // The BufferedRawMachineAssemblerTester does not pass parameters directly
+ // to the constructed IR graph. Instead it passes a pointer to the parameter
+ // to the IR graph, and adds Load nodes to the IR graph to load the
+ // parameters from memory. Thereby it is possible to pass 64 bit parameters
+ // to the IR graph.
+ Node* Parameter(size_t index) {
+ CHECK(index >= 0 && index < 4);
+ return parameter_nodes_[index];
}
- template <typename Ci, typename Cj, typename Fn>
- void Run(const Ci& ci, const Cj& cj, const Fn& fn) {
- typename Ci::const_iterator i;
- typename Cj::const_iterator j;
- for (i = ci.begin(); i != ci.end(); ++i) {
- for (j = cj.begin(); j != cj.end(); ++j) {
- CHECK_EQ(fn(*i, *j), this->Call(*i, *j));
- }
- }
+
+ // The BufferedRawMachineAssemblerTester adds a Store node to the IR graph
+ // to store the graph's return value in memory. The memory address for the
+ // Store node is provided as a parameter. By storing the return value in
+ // memory it is possible to return 64 bit values.
+ void Return(Node* input) {
+ Store(MachineTypeForC<ReturnType>().representation(),
+ RawMachineAssembler::Parameter(return_parameter_index_), input,
+ kNoWriteBarrier);
+ RawMachineAssembler::Return(Int32Constant(1234));
}
+
+ ReturnType Call() {
+ ReturnType return_value;
+ test_graph_signature_->VerifyParams();
+ CallHelper<int32_t>::Call(reinterpret_cast<void*>(&return_value));
+ return return_value;
+ }
+
+ template <typename P0>
+ ReturnType Call(P0 p0) {
+ ReturnType return_value;
+ test_graph_signature_->VerifyParams<P0>();
+ CallHelper<int32_t>::Call(reinterpret_cast<void*>(&p0),
+ reinterpret_cast<void*>(&return_value));
+ return return_value;
+ }
+
+ template <typename P0, typename P1>
+ ReturnType Call(P0 p0, P1 p1) {
+ ReturnType return_value;
+ test_graph_signature_->VerifyParams<P0, P1>();
+ CallHelper<int32_t>::Call(reinterpret_cast<void*>(&p0),
+ reinterpret_cast<void*>(&p1),
+ reinterpret_cast<void*>(&return_value));
+ return return_value;
+ }
+
+ template <typename P0, typename P1, typename P2>
+ ReturnType Call(P0 p0, P1 p1, P2 p2) {
+ ReturnType return_value;
+ test_graph_signature_->VerifyParams<P0, P1, P2>();
+ CallHelper<int32_t>::Call(
+ reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
+ reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&return_value));
+ return return_value;
+ }
+
+ template <typename P0, typename P1, typename P2, typename P3>
+ ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) {
+ ReturnType return_value;
+ test_graph_signature_->VerifyParams<P0, P1, P2, P3>();
+ CallHelper<int32_t>::Call(
+ reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
+ reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&p3),
+ reinterpret_cast<void*>(&return_value));
+ return return_value;
+ }
+
+ private:
+ BufferedRawMachineAssemblerTester(uint32_t return_parameter_index,
+ MachineType p0, MachineType p1,
+ MachineType p2, MachineType p3)
+ : RawMachineAssemblerTester<int32_t>(
+ MachineType::Pointer(),
+ p0 == MachineType::None() ? MachineType::None()
+ : MachineType::Pointer(),
+ p1 == MachineType::None() ? MachineType::None()
+ : MachineType::Pointer(),
+ p2 == MachineType::None() ? MachineType::None()
+ : MachineType::Pointer(),
+ p3 == MachineType::None() ? MachineType::None()
+ : MachineType::Pointer()),
+ test_graph_signature_(
+ CSignature::New(main_zone(), MachineType::Int32(), p0, p1, p2, p3)),
+ return_parameter_index_(return_parameter_index) {
+ parameter_nodes_[0] = p0 == MachineType::None()
+ ? nullptr
+ : Load(p0, RawMachineAssembler::Parameter(0));
+ parameter_nodes_[1] = p1 == MachineType::None()
+ ? nullptr
+ : Load(p1, RawMachineAssembler::Parameter(1));
+ parameter_nodes_[2] = p2 == MachineType::None()
+ ? nullptr
+ : Load(p2, RawMachineAssembler::Parameter(2));
+ parameter_nodes_[3] = p3 == MachineType::None()
+ ? nullptr
+ : Load(p3, RawMachineAssembler::Parameter(3));
+ }
+
+
+ static uint32_t ComputeParameterCount(MachineType p0, MachineType p1,
+ MachineType p2, MachineType p3) {
+ if (p0 == MachineType::None()) {
+ return 0;
+ }
+ if (p1 == MachineType::None()) {
+ return 1;
+ }
+ if (p2 == MachineType::None()) {
+ return 2;
+ }
+ if (p3 == MachineType::None()) {
+ return 3;
+ }
+ return 4;
+ }
+
+
+ CSignature* test_graph_signature_;
+ Node* parameter_nodes_[4];
+ uint32_t return_parameter_index_;
};
+template <>
+class BufferedRawMachineAssemblerTester<void>
+ : public RawMachineAssemblerTester<void> {
+ public:
+ BufferedRawMachineAssemblerTester(MachineType p0 = MachineType::None(),
+ MachineType p1 = MachineType::None(),
+ MachineType p2 = MachineType::None(),
+ MachineType p3 = MachineType::None())
+ : RawMachineAssemblerTester<void>(
+ p0 == MachineType::None() ? MachineType::None()
+ : MachineType::Pointer(),
+ p1 == MachineType::None() ? MachineType::None()
+ : MachineType::Pointer(),
+ p2 == MachineType::None() ? MachineType::None()
+ : MachineType::Pointer(),
+ p3 == MachineType::None() ? MachineType::None()
+ : MachineType::Pointer()),
+ test_graph_signature_(
+ CSignature::New(RawMachineAssemblerTester<void>::main_zone(),
+ MachineType::None(), p0, p1, p2, p3)) {
+ parameter_nodes_[0] = p0 == MachineType::None()
+ ? nullptr
+ : Load(p0, RawMachineAssembler::Parameter(0));
+ parameter_nodes_[1] = p1 == MachineType::None()
+ ? nullptr
+ : Load(p1, RawMachineAssembler::Parameter(1));
+ parameter_nodes_[2] = p2 == MachineType::None()
+ ? nullptr
+ : Load(p2, RawMachineAssembler::Parameter(2));
+ parameter_nodes_[3] = p3 == MachineType::None()
+ ? nullptr
+ : Load(p3, RawMachineAssembler::Parameter(3));
+ }
+
+
+ // The BufferedRawMachineAssemblerTester does not pass parameters directly
+ // to the constructed IR graph. Instead it passes a pointer to the parameter
+ // to the IR graph, and adds Load nodes to the IR graph to load the
+ // parameters from memory. Thereby it is possible to pass 64 bit parameters
+ // to the IR graph.
+ Node* Parameter(size_t index) {
+ CHECK(index >= 0 && index < 4);
+ return parameter_nodes_[index];
+ }
+
+
+ void Call() {
+ test_graph_signature_->VerifyParams();
+ CallHelper<void>::Call();
+ }
+
+ template <typename P0>
+ void Call(P0 p0) {
+ test_graph_signature_->VerifyParams<P0>();
+ CallHelper<void>::Call(reinterpret_cast<void*>(&p0));
+ }
+
+ template <typename P0, typename P1>
+ void Call(P0 p0, P1 p1) {
+ test_graph_signature_->VerifyParams<P0, P1>();
+ CallHelper<void>::Call(reinterpret_cast<void*>(&p0),
+ reinterpret_cast<void*>(&p1));
+ }
+
+ template <typename P0, typename P1, typename P2>
+ void Call(P0 p0, P1 p1, P2 p2) {
+ test_graph_signature_->VerifyParams<P0, P1, P2>();
+ CallHelper<void>::Call(reinterpret_cast<void*>(&p0),
+ reinterpret_cast<void*>(&p1),
+ reinterpret_cast<void*>(&p2));
+ }
+
+ template <typename P0, typename P1, typename P2, typename P3>
+ void Call(P0 p0, P1 p1, P2 p2, P3 p3) {
+ test_graph_signature_->VerifyParams<P0, P1, P2, P3>();
+ CallHelper<void>::Call(
+ reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
+ reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&p3));
+ }
+
+ private:
+ CSignature* test_graph_signature_;
+ Node* parameter_nodes_[4];
+};
static const bool USE_RESULT_BUFFER = true;
static const bool USE_RETURN_REGISTER = false;
static const int32_t CHECK_VALUE = 0x99BEEDCE;
@@ -121,13 +302,15 @@
// TODO(titzer): use the C-style calling convention, or any register-based
// calling convention for binop tests.
-template <typename CType, MachineType rep, bool use_result_buffer>
+template <typename CType, bool use_result_buffer>
class BinopTester {
public:
- explicit BinopTester(RawMachineAssemblerTester<int32_t>* tester)
+ explicit BinopTester(RawMachineAssemblerTester<int32_t>* tester,
+ MachineType rep)
: T(tester),
param0(T->LoadFromPointer(&p0, rep)),
param1(T->LoadFromPointer(&p1, rep)),
+ rep(rep),
p0(static_cast<CType>(0)),
p1(static_cast<CType>(0)),
result(static_cast<CType>(0)) {}
@@ -143,13 +326,14 @@
CHECK_EQ(CHECK_VALUE, T->Call());
return result;
} else {
- return T->Call();
+ return static_cast<CType>(T->Call());
}
}
void AddReturn(Node* val) {
if (use_result_buffer) {
- T->Store(rep, T->PointerConstant(&result), T->Int32Constant(0), val);
+ T->Store(rep.representation(), T->PointerConstant(&result),
+ T->Int32Constant(0), val, kNoWriteBarrier);
T->Return(T->Int32Constant(CHECK_VALUE));
} else {
T->Return(val);
@@ -168,6 +352,7 @@
}
protected:
+ MachineType rep;
CType p0;
CType p1;
CType result;
@@ -176,21 +361,31 @@
// A helper class for testing code sequences that take two int parameters and
// return an int value.
-class Int32BinopTester
- : public BinopTester<int32_t, kMachInt32, USE_RETURN_REGISTER> {
+class Int32BinopTester : public BinopTester<int32_t, USE_RETURN_REGISTER> {
public:
explicit Int32BinopTester(RawMachineAssemblerTester<int32_t>* tester)
- : BinopTester<int32_t, kMachInt32, USE_RETURN_REGISTER>(tester) {}
+ : BinopTester<int32_t, USE_RETURN_REGISTER>(tester,
+ MachineType::Int32()) {}
+};
+
+
+// A helper class for testing code sequences that take two int parameters and
+// return an int value.
+class Int64BinopTester : public BinopTester<int64_t, USE_RETURN_REGISTER> {
+ public:
+ explicit Int64BinopTester(RawMachineAssemblerTester<int32_t>* tester)
+ : BinopTester<int64_t, USE_RETURN_REGISTER>(tester,
+ MachineType::Int64()) {}
};
// A helper class for testing code sequences that take two uint parameters and
// return an uint value.
-class Uint32BinopTester
- : public BinopTester<uint32_t, kMachUint32, USE_RETURN_REGISTER> {
+class Uint32BinopTester : public BinopTester<uint32_t, USE_RETURN_REGISTER> {
public:
explicit Uint32BinopTester(RawMachineAssemblerTester<int32_t>* tester)
- : BinopTester<uint32_t, kMachUint32, USE_RETURN_REGISTER>(tester) {}
+ : BinopTester<uint32_t, USE_RETURN_REGISTER>(tester,
+ MachineType::Uint32()) {}
uint32_t call(uint32_t a0, uint32_t a1) {
p0 = a0;
@@ -200,14 +395,24 @@
};
+// A helper class for testing code sequences that take two float parameters and
+// return a float value.
+// TODO(titzer): figure out how to return floats correctly on ia32.
+class Float32BinopTester : public BinopTester<float, USE_RESULT_BUFFER> {
+ public:
+ explicit Float32BinopTester(RawMachineAssemblerTester<int32_t>* tester)
+ : BinopTester<float, USE_RESULT_BUFFER>(tester, MachineType::Float32()) {}
+};
+
+
// A helper class for testing code sequences that take two double parameters and
// return a double value.
// TODO(titzer): figure out how to return doubles correctly on ia32.
-class Float64BinopTester
- : public BinopTester<double, kMachFloat64, USE_RESULT_BUFFER> {
+class Float64BinopTester : public BinopTester<double, USE_RESULT_BUFFER> {
public:
explicit Float64BinopTester(RawMachineAssemblerTester<int32_t>* tester)
- : BinopTester<double, kMachFloat64, USE_RESULT_BUFFER>(tester) {}
+ : BinopTester<double, USE_RESULT_BUFFER>(tester, MachineType::Float64()) {
+ }
};
@@ -215,22 +420,22 @@
// and return a pointer value.
// TODO(titzer): pick word size of pointers based on V8_TARGET.
template <typename Type>
-class PointerBinopTester
- : public BinopTester<Type*, kMachPtr, USE_RETURN_REGISTER> {
+class PointerBinopTester : public BinopTester<Type*, USE_RETURN_REGISTER> {
public:
explicit PointerBinopTester(RawMachineAssemblerTester<int32_t>* tester)
- : BinopTester<Type*, kMachPtr, USE_RETURN_REGISTER>(tester) {}
+ : BinopTester<Type*, USE_RETURN_REGISTER>(tester,
+ MachineType::Pointer()) {}
};
// A helper class for testing code sequences that take two tagged parameters and
// return a tagged value.
template <typename Type>
-class TaggedBinopTester
- : public BinopTester<Type*, kMachAnyTagged, USE_RETURN_REGISTER> {
+class TaggedBinopTester : public BinopTester<Type*, USE_RETURN_REGISTER> {
public:
explicit TaggedBinopTester(RawMachineAssemblerTester<int32_t>* tester)
- : BinopTester<Type*, kMachAnyTagged, USE_RETURN_REGISTER>(tester) {}
+ : BinopTester<Type*, USE_RETURN_REGISTER>(tester,
+ MachineType::AnyTagged()) {}
};
// A helper class for testing compares. Wraps a machine opcode and provides
@@ -240,7 +445,7 @@
explicit CompareWrapper(IrOpcode::Value op) : opcode(op) {}
Node* MakeNode(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) {
- return m->NewNode(op(m->machine()), a, b);
+ return m->AddNode(op(m->machine()), a, b);
}
const Operator* op(MachineOperatorBuilder* machine) {
@@ -332,6 +537,24 @@
void RunLeft(RawMachineAssemblerTester<int32_t>* m);
void RunRight(RawMachineAssemblerTester<int32_t>* m);
};
+
+// TODO(bmeurer): Drop this crap once we switch to GTest/Gmock.
+static inline void CheckFloatEq(volatile float x, volatile float y) {
+ if (std::isnan(x)) {
+ CHECK(std::isnan(y));
+ } else {
+ CHECK_EQ(x, y);
+ }
+}
+
+static inline void CheckDoubleEq(volatile double x, volatile double y) {
+ if (std::isnan(x)) {
+ CHECK(std::isnan(y));
+ } else {
+ CHECK_EQ(x, y);
+ }
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/test/cctest/compiler/function-tester.h b/test/cctest/compiler/function-tester.h
index 7e16eea..2fcd353 100644
--- a/test/cctest/compiler/function-tester.h
+++ b/test/cctest/compiler/function-tester.h
@@ -5,22 +5,18 @@
#ifndef V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
#define V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
-#include "src/v8.h"
-#include "test/cctest/cctest.h"
-
-#include "src/ast-numbering.h"
+#include "src/ast/ast-numbering.h"
+#include "src/ast/scopes.h"
#include "src/compiler.h"
#include "src/compiler/linkage.h"
#include "src/compiler/pipeline.h"
#include "src/execution.h"
-#include "src/full-codegen.h"
+#include "src/full-codegen/full-codegen.h"
#include "src/handles.h"
#include "src/objects-inl.h"
-#include "src/parser.h"
-#include "src/rewriter.h"
-#include "src/scopes.h"
-
-#define USE_CRANKSHAFT 0
+#include "src/parsing/parser.h"
+#include "src/parsing/rewriter.h"
+#include "test/cctest/cctest.h"
namespace v8 {
namespace internal {
@@ -33,48 +29,65 @@
function((FLAG_allow_natives_syntax = true, NewFunction(source))),
flags_(flags) {
Compile(function);
- const uint32_t supported_flags = CompilationInfo::kContextSpecializing |
- CompilationInfo::kInliningEnabled |
- CompilationInfo::kTypingEnabled;
- CHECK_EQ(0, flags_ & ~supported_flags);
+ const uint32_t supported_flags =
+ CompilationInfo::kFunctionContextSpecializing |
+ CompilationInfo::kInliningEnabled | CompilationInfo::kTypingEnabled;
+ CHECK_EQ(0u, flags_ & ~supported_flags);
}
- explicit FunctionTester(Graph* graph)
+ FunctionTester(Graph* graph, int param_count)
: isolate(main_isolate()),
- function(NewFunction("(function(a,b){})")),
+ function(NewFunction(BuildFunction(param_count).c_str())),
flags_(0) {
CompileGraph(graph);
}
+ FunctionTester(const CallInterfaceDescriptor& descriptor, Handle<Code> code)
+ : isolate(main_isolate()),
+ function(
+ (FLAG_allow_natives_syntax = true,
+ NewFunction(BuildFunctionFromDescriptor(descriptor).c_str()))),
+ flags_(0) {
+ Compile(function);
+ function->ReplaceCode(*code);
+ }
+
Isolate* isolate;
Handle<JSFunction> function;
+ MaybeHandle<Object> Call() {
+ return Execution::Call(isolate, function, undefined(), 0, nullptr);
+ }
+
MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) {
Handle<Object> args[] = {a, b};
- return Execution::Call(isolate, function, undefined(), 2, args, false);
+ return Execution::Call(isolate, function, undefined(), 2, args);
+ }
+
+ MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, Handle<Object> c,
+ Handle<Object> d) {
+ Handle<Object> args[] = {a, b, c, d};
+ return Execution::Call(isolate, function, undefined(), 4, args);
}
void CheckThrows(Handle<Object> a, Handle<Object> b) {
- TryCatch try_catch;
+ TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
MaybeHandle<Object> no_result = Call(a, b);
CHECK(isolate->has_pending_exception());
CHECK(try_catch.HasCaught());
CHECK(no_result.is_null());
- // TODO(mstarzinger): Temporary workaround for issue chromium:362388.
isolate->OptionalRescheduleException(true);
}
- v8::Handle<v8::Message> CheckThrowsReturnMessage(Handle<Object> a,
- Handle<Object> b) {
- TryCatch try_catch;
+ v8::Local<v8::Message> CheckThrowsReturnMessage(Handle<Object> a,
+ Handle<Object> b) {
+ TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
MaybeHandle<Object> no_result = Call(a, b);
CHECK(isolate->has_pending_exception());
CHECK(try_catch.HasCaught());
CHECK(no_result.is_null());
- // TODO(mstarzinger): Calling OptionalRescheduleException is a dirty hack,
- // it's the only way to make Message() not to assert because an external
- // exception has been caught by the try_catch.
isolate->OptionalRescheduleException(true);
+ CHECK(!try_catch.Message().IsEmpty());
return try_catch.Message();
}
@@ -118,13 +131,13 @@
}
Handle<JSFunction> NewFunction(const char* source) {
- return v8::Utils::OpenHandle(
- *v8::Handle<v8::Function>::Cast(CompileRun(source)));
+ return Handle<JSFunction>::cast(v8::Utils::OpenHandle(
+ *v8::Local<v8::Function>::Cast(CompileRun(source))));
}
Handle<JSObject> NewObject(const char* source) {
- return v8::Utils::OpenHandle(
- *v8::Handle<v8::Object>::Cast(CompileRun(source)));
+ return Handle<JSObject>::cast(v8::Utils::OpenHandle(
+ *v8::Local<v8::Object>::Cast(CompileRun(source))));
}
Handle<String> Val(const char* string) {
@@ -151,13 +164,15 @@
Handle<JSFunction> Compile(Handle<JSFunction> function) {
// TODO(titzer): make this method private.
-#if V8_TURBOFAN_TARGET
- CompilationInfoWithZone info(function);
+ Zone zone;
+ ParseInfo parse_info(&zone, function);
+ CompilationInfo info(&parse_info);
+ info.MarkAsDeoptimizationEnabled();
- CHECK(Parser::Parse(&info));
+ CHECK(Parser::ParseStatic(info.parse_info()));
info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
- if (flags_ & CompilationInfo::kContextSpecializing) {
- info.MarkAsContextSpecializing();
+ if (flags_ & CompilationInfo::kFunctionContextSpecializing) {
+ info.MarkAsFunctionContextSpecializing();
}
if (flags_ & CompilationInfo::kInliningEnabled) {
info.MarkAsInliningEnabled();
@@ -165,37 +180,22 @@
if (flags_ & CompilationInfo::kTypingEnabled) {
info.MarkAsTypingEnabled();
}
- CHECK(Compiler::Analyze(&info));
+ CHECK(Compiler::Analyze(info.parse_info()));
CHECK(Compiler::EnsureDeoptimizationSupport(&info));
Pipeline pipeline(&info);
Handle<Code> code = pipeline.GenerateCode();
- if (FLAG_turbo_deoptimization) {
- info.context()->native_context()->AddOptimizedCode(*code);
- }
-
CHECK(!code.is_null());
+ info.dependencies()->Commit(code);
+ info.context()->native_context()->AddOptimizedCode(*code);
function->ReplaceCode(*code);
-#elif USE_CRANKSHAFT
- Handle<Code> unoptimized = Handle<Code>(function->code());
- Handle<Code> code = Compiler::GetOptimizedCode(function, unoptimized,
- Compiler::NOT_CONCURRENT);
- CHECK(!code.is_null());
-#if ENABLE_DISASSEMBLER
- if (FLAG_print_opt_code) {
- CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
- code->Disassemble("test code", tracing_scope.file());
- }
-#endif
- function->ReplaceCode(*code);
-#endif
return function;
}
- static Handle<JSFunction> ForMachineGraph(Graph* graph) {
+ static Handle<JSFunction> ForMachineGraph(Graph* graph, int param_count) {
JSFunction* p = NULL;
{ // because of the implicit handle scope of FunctionTester.
- FunctionTester f(graph);
+ FunctionTester f(graph, param_count);
p = *f.function;
}
return Handle<JSFunction>(p); // allocated in outer handle scope.
@@ -204,16 +204,36 @@
private:
uint32_t flags_;
+ std::string BuildFunction(int param_count) {
+ std::string function_string = "(function(";
+ if (param_count > 0) {
+ char next = 'a';
+ function_string += next;
+ while (param_count-- > 0) {
+ function_string += ',';
+ function_string += ++next;
+ }
+ }
+ function_string += "){})";
+ return function_string;
+ }
+
+ std::string BuildFunctionFromDescriptor(
+ const CallInterfaceDescriptor& descriptor) {
+ return BuildFunction(descriptor.GetParameterCount());
+ }
+
// Compile the given machine graph instead of the source of the function
// and replace the JSFunction's code with the result.
Handle<JSFunction> CompileGraph(Graph* graph) {
- CHECK(Pipeline::SupportedTarget());
- CompilationInfoWithZone info(function);
+ Zone zone;
+ ParseInfo parse_info(&zone, function);
+ CompilationInfo info(&parse_info);
- CHECK(Parser::Parse(&info));
+ CHECK(Parser::ParseStatic(info.parse_info()));
info.SetOptimizing(BailoutId::None(),
Handle<Code>(function->shared()->code()));
- CHECK(Compiler::Analyze(&info));
+ CHECK(Compiler::Analyze(info.parse_info()));
CHECK(Compiler::EnsureDeoptimizationSupport(&info));
Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, graph);
@@ -222,8 +242,8 @@
return function;
}
};
-}
-}
-} // namespace v8::internal::compiler
+} // namespace compiler
+} // namespace internal
+} // namespace v8
#endif // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
diff --git a/test/cctest/compiler/graph-builder-tester.cc b/test/cctest/compiler/graph-builder-tester.cc
deleted file mode 100644
index b0f470b..0000000
--- a/test/cctest/compiler/graph-builder-tester.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "test/cctest/compiler/graph-builder-tester.h"
-
-#include "src/compiler/linkage.h"
-#include "src/compiler/pipeline.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-MachineCallHelper::MachineCallHelper(Zone* zone, MachineSignature* machine_sig)
- : CallHelper(zone->isolate(), machine_sig),
- parameters_(NULL),
- graph_(NULL) {}
-
-
-void MachineCallHelper::InitParameters(GraphBuilder* builder,
- CommonOperatorBuilder* common) {
- DCHECK_EQ(NULL, parameters_);
- graph_ = builder->graph();
- int param_count = static_cast<int>(parameter_count());
- if (param_count == 0) return;
- parameters_ = graph_->zone()->NewArray<Node*>(param_count);
- for (int i = 0; i < param_count; ++i) {
- parameters_[i] = builder->NewNode(common->Parameter(i), graph_->start());
- }
-}
-
-
-byte* MachineCallHelper::Generate() {
- DCHECK(parameter_count() == 0 || parameters_ != NULL);
- if (!Pipeline::SupportedBackend()) return NULL;
- if (code_.is_null()) {
- Zone* zone = graph_->zone();
- CallDescriptor* desc =
- Linkage::GetSimplifiedCDescriptor(zone, machine_sig_);
- code_ = Pipeline::GenerateCodeForTesting(desc, graph_);
- }
- return code_.ToHandleChecked()->entry();
-}
-
-
-Node* MachineCallHelper::Parameter(size_t index) {
- DCHECK_NE(NULL, parameters_);
- DCHECK(index < parameter_count());
- return parameters_[index];
-}
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
diff --git a/test/cctest/compiler/graph-builder-tester.h b/test/cctest/compiler/graph-builder-tester.h
index 772de4d..de2713a 100644
--- a/test/cctest/compiler/graph-builder-tester.h
+++ b/test/cctest/compiler/graph-builder-tester.h
@@ -5,67 +5,37 @@
#ifndef V8_CCTEST_COMPILER_GRAPH_BUILDER_TESTER_H_
#define V8_CCTEST_COMPILER_GRAPH_BUILDER_TESTER_H_
-#include "src/v8.h"
-#include "test/cctest/cctest.h"
-
#include "src/compiler/common-operator.h"
-#include "src/compiler/graph-builder.h"
+#include "src/compiler/instruction-selector.h"
+#include "src/compiler/linkage.h"
#include "src/compiler/machine-operator.h"
+#include "src/compiler/operator-properties.h"
+#include "src/compiler/pipeline.h"
#include "src/compiler/simplified-operator.h"
+#include "test/cctest/cctest.h"
#include "test/cctest/compiler/call-tester.h"
-#include "test/cctest/compiler/simplified-graph-builder.h"
namespace v8 {
namespace internal {
namespace compiler {
-// A class that just passes node creation on to the Graph.
-class DirectGraphBuilder : public GraphBuilder {
- public:
- explicit DirectGraphBuilder(Graph* graph) : GraphBuilder(graph) {}
- virtual ~DirectGraphBuilder() {}
-
- protected:
- virtual Node* MakeNode(const Operator* op, int value_input_count,
- Node** value_inputs, bool incomplete) FINAL {
- return graph()->NewNode(op, value_input_count, value_inputs, incomplete);
- }
-};
-
-
-class MachineCallHelper : public CallHelper {
- public:
- MachineCallHelper(Zone* zone, MachineSignature* machine_sig);
-
- Node* Parameter(size_t index);
-
- void GenerateCode() { Generate(); }
-
- protected:
- virtual byte* Generate();
- void InitParameters(GraphBuilder* builder, CommonOperatorBuilder* common);
-
- protected:
- size_t parameter_count() const { return machine_sig_->parameter_count(); }
-
- private:
- Node** parameters_;
- // TODO(dcarney): shouldn't need graph stored.
- Graph* graph_;
- MaybeHandle<Code> code_;
-};
-
-
class GraphAndBuilders {
public:
explicit GraphAndBuilders(Zone* zone)
: main_graph_(new (zone) Graph(zone)),
main_common_(zone),
- main_machine_(zone),
+ main_machine_(zone, MachineType::PointerRepresentation(),
+ InstructionSelector::SupportedMachineOperatorFlags()),
main_simplified_(zone) {}
+ Graph* graph() const { return main_graph_; }
+ Zone* zone() const { return graph()->zone(); }
+ CommonOperatorBuilder* common() { return &main_common_; }
+ MachineOperatorBuilder* machine() { return &main_machine_; }
+ SimplifiedOperatorBuilder* simplified() { return &main_simplified_; }
+
protected:
- // Prefixed with main_ to avoid naiming conflicts.
+ // Prefixed with main_ to avoid naming conflicts.
Graph* main_graph_;
CommonOperatorBuilder main_common_;
MachineOperatorBuilder main_machine_;
@@ -74,33 +44,267 @@
template <typename ReturnType>
-class GraphBuilderTester
- : public HandleAndZoneScope,
- private GraphAndBuilders,
- public MachineCallHelper,
- public SimplifiedGraphBuilder,
- public CallHelper2<ReturnType, GraphBuilderTester<ReturnType> > {
+class GraphBuilderTester : public HandleAndZoneScope,
+ public GraphAndBuilders,
+ public CallHelper<ReturnType> {
public:
- explicit GraphBuilderTester(MachineType p0 = kMachNone,
- MachineType p1 = kMachNone,
- MachineType p2 = kMachNone,
- MachineType p3 = kMachNone,
- MachineType p4 = kMachNone)
+ explicit GraphBuilderTester(MachineType p0 = MachineType::None(),
+ MachineType p1 = MachineType::None(),
+ MachineType p2 = MachineType::None(),
+ MachineType p3 = MachineType::None(),
+ MachineType p4 = MachineType::None())
: GraphAndBuilders(main_zone()),
- MachineCallHelper(
- main_zone(),
- MakeMachineSignature(
- main_zone(), ReturnValueTraits<ReturnType>::Representation(),
- p0, p1, p2, p3, p4)),
- SimplifiedGraphBuilder(main_graph_, &main_common_, &main_machine_,
- &main_simplified_) {
+ CallHelper<ReturnType>(
+ main_isolate(),
+ CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0, p1,
+ p2, p3, p4)),
+ effect_(NULL),
+ return_(NULL),
+ parameters_(main_zone()->template NewArray<Node*>(parameter_count())) {
Begin(static_cast<int>(parameter_count()));
- InitParameters(this, &main_common_);
+ InitParameters();
}
virtual ~GraphBuilderTester() {}
- Factory* factory() const { return isolate()->factory(); }
+ void GenerateCode() { Generate(); }
+ Node* Parameter(size_t index) {
+ CHECK_LT(index, parameter_count());
+ return parameters_[index];
+ }
+
+ Isolate* isolate() { return main_isolate(); }
+ Factory* factory() { return isolate()->factory(); }
+
+ // Initialize graph and builder.
+ void Begin(int num_parameters) {
+ CHECK_NULL(graph()->start());
+ Node* start = graph()->NewNode(common()->Start(num_parameters + 3));
+ graph()->SetStart(start);
+ effect_ = start;
+ }
+
+ void Return(Node* value) {
+ return_ =
+ graph()->NewNode(common()->Return(), value, effect_, graph()->start());
+ effect_ = NULL;
+ }
+
+ // Close the graph.
+ void End() {
+ Node* end = graph()->NewNode(common()->End(1), return_);
+ graph()->SetEnd(end);
+ }
+
+ Node* PointerConstant(void* value) {
+ intptr_t intptr_value = reinterpret_cast<intptr_t>(value);
+ return kPointerSize == 8 ? NewNode(common()->Int64Constant(intptr_value))
+ : Int32Constant(static_cast<int>(intptr_value));
+ }
+ Node* Int32Constant(int32_t value) {
+ return NewNode(common()->Int32Constant(value));
+ }
+ Node* HeapConstant(Handle<HeapObject> object) {
+ return NewNode(common()->HeapConstant(object));
+ }
+
+ Node* BooleanNot(Node* a) { return NewNode(simplified()->BooleanNot(), a); }
+
+ Node* NumberEqual(Node* a, Node* b) {
+ return NewNode(simplified()->NumberEqual(), a, b);
+ }
+ Node* NumberLessThan(Node* a, Node* b) {
+ return NewNode(simplified()->NumberLessThan(), a, b);
+ }
+ Node* NumberLessThanOrEqual(Node* a, Node* b) {
+ return NewNode(simplified()->NumberLessThanOrEqual(), a, b);
+ }
+ Node* NumberAdd(Node* a, Node* b) {
+ return NewNode(simplified()->NumberAdd(), a, b);
+ }
+ Node* NumberSubtract(Node* a, Node* b) {
+ return NewNode(simplified()->NumberSubtract(), a, b);
+ }
+ Node* NumberMultiply(Node* a, Node* b) {
+ return NewNode(simplified()->NumberMultiply(), a, b);
+ }
+ Node* NumberDivide(Node* a, Node* b) {
+ return NewNode(simplified()->NumberDivide(), a, b);
+ }
+ Node* NumberModulus(Node* a, Node* b) {
+ return NewNode(simplified()->NumberModulus(), a, b);
+ }
+ Node* NumberToInt32(Node* a) {
+ return NewNode(simplified()->NumberToInt32(), a);
+ }
+ Node* NumberToUint32(Node* a) {
+ return NewNode(simplified()->NumberToUint32(), a);
+ }
+
+ Node* StringEqual(Node* a, Node* b) {
+ return NewNode(simplified()->StringEqual(), a, b);
+ }
+ Node* StringLessThan(Node* a, Node* b) {
+ return NewNode(simplified()->StringLessThan(), a, b);
+ }
+ Node* StringLessThanOrEqual(Node* a, Node* b) {
+ return NewNode(simplified()->StringLessThanOrEqual(), a, b);
+ }
+
+ Node* ChangeTaggedToInt32(Node* a) {
+ return NewNode(simplified()->ChangeTaggedToInt32(), a);
+ }
+ Node* ChangeTaggedToUint32(Node* a) {
+ return NewNode(simplified()->ChangeTaggedToUint32(), a);
+ }
+ Node* ChangeTaggedToFloat64(Node* a) {
+ return NewNode(simplified()->ChangeTaggedToFloat64(), a);
+ }
+ Node* ChangeInt32ToTagged(Node* a) {
+ return NewNode(simplified()->ChangeInt32ToTagged(), a);
+ }
+ Node* ChangeUint32ToTagged(Node* a) {
+ return NewNode(simplified()->ChangeUint32ToTagged(), a);
+ }
+ Node* ChangeFloat64ToTagged(Node* a) {
+ return NewNode(simplified()->ChangeFloat64ToTagged(), a);
+ }
+ Node* ChangeBoolToBit(Node* a) {
+ return NewNode(simplified()->ChangeBoolToBit(), a);
+ }
+ Node* ChangeBitToBool(Node* a) {
+ return NewNode(simplified()->ChangeBitToBool(), a);
+ }
+
+ Node* LoadField(const FieldAccess& access, Node* object) {
+ return NewNode(simplified()->LoadField(access), object);
+ }
+ Node* StoreField(const FieldAccess& access, Node* object, Node* value) {
+ return NewNode(simplified()->StoreField(access), object, value);
+ }
+ Node* LoadElement(const ElementAccess& access, Node* object, Node* index) {
+ return NewNode(simplified()->LoadElement(access), object, index);
+ }
+ Node* StoreElement(const ElementAccess& access, Node* object, Node* index,
+ Node* value) {
+ return NewNode(simplified()->StoreElement(access), object, index, value);
+ }
+
+ Node* NewNode(const Operator* op) {
+ return MakeNode(op, 0, static_cast<Node**>(NULL));
+ }
+
+ Node* NewNode(const Operator* op, Node* n1) { return MakeNode(op, 1, &n1); }
+
+ Node* NewNode(const Operator* op, Node* n1, Node* n2) {
+ Node* buffer[] = {n1, n2};
+ return MakeNode(op, arraysize(buffer), buffer);
+ }
+
+ Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) {
+ Node* buffer[] = {n1, n2, n3};
+ return MakeNode(op, arraysize(buffer), buffer);
+ }
+
+ Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) {
+ Node* buffer[] = {n1, n2, n3, n4};
+ return MakeNode(op, arraysize(buffer), buffer);
+ }
+
+ Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
+ Node* n5) {
+ Node* buffer[] = {n1, n2, n3, n4, n5};
+ return MakeNode(op, arraysize(buffer), buffer);
+ }
+
+ Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
+ Node* n5, Node* n6) {
+ Node* nodes[] = {n1, n2, n3, n4, n5, n6};
+ return MakeNode(op, arraysize(nodes), nodes);
+ }
+
+ Node* NewNode(const Operator* op, int value_input_count,
+ Node** value_inputs) {
+ return MakeNode(op, value_input_count, value_inputs);
+ }
+
+ Handle<Code> GetCode() {
+ Generate();
+ return code_.ToHandleChecked();
+ }
+
+ protected:
+ Node* MakeNode(const Operator* op, int value_input_count,
+ Node** value_inputs) {
+ CHECK_EQ(op->ValueInputCount(), value_input_count);
+
+ CHECK(!OperatorProperties::HasContextInput(op));
+ CHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op));
+ bool has_control = op->ControlInputCount() == 1;
+ bool has_effect = op->EffectInputCount() == 1;
+
+ CHECK_LT(op->ControlInputCount(), 2);
+ CHECK_LT(op->EffectInputCount(), 2);
+
+ Node* result = NULL;
+ if (!has_control && !has_effect) {
+ result = graph()->NewNode(op, value_input_count, value_inputs);
+ } else {
+ int input_count_with_deps = value_input_count;
+ if (has_control) ++input_count_with_deps;
+ if (has_effect) ++input_count_with_deps;
+ Node** buffer = zone()->template NewArray<Node*>(input_count_with_deps);
+ memcpy(buffer, value_inputs, kPointerSize * value_input_count);
+ Node** current_input = buffer + value_input_count;
+ if (has_effect) {
+ *current_input++ = effect_;
+ }
+ if (has_control) {
+ *current_input++ = graph()->start();
+ }
+ result = graph()->NewNode(op, input_count_with_deps, buffer);
+ if (has_effect) {
+ effect_ = result;
+ }
+ // This graph builder does not support control flow.
+ CHECK_EQ(0, op->ControlOutputCount());
+ }
+
+ return result;
+ }
+
+ virtual byte* Generate() {
+ if (code_.is_null()) {
+ Zone* zone = graph()->zone();
+ CallDescriptor* desc =
+ Linkage::GetSimplifiedCDescriptor(zone, this->csig_);
+ CompilationInfo info("testing", main_isolate(), main_zone());
+ code_ = Pipeline::GenerateCodeForTesting(&info, desc, graph());
+#ifdef ENABLE_DISASSEMBLER
+ if (!code_.is_null() && FLAG_print_opt_code) {
+ OFStream os(stdout);
+ code_.ToHandleChecked()->Disassemble("test code", os);
+ }
+#endif
+ }
+ return code_.ToHandleChecked()->entry();
+ }
+
+ void InitParameters() {
+ int param_count = static_cast<int>(parameter_count());
+ for (int i = 0; i < param_count; ++i) {
+ parameters_[i] = this->NewNode(common()->Parameter(i), graph()->start());
+ }
+ }
+
+ size_t parameter_count() const { return this->csig_->parameter_count(); }
+
+ private:
+ Node* effect_;
+ Node* return_;
+ Node** parameters_;
+ MaybeHandle<Code> code_;
};
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/test/cctest/compiler/graph-tester.h b/test/cctest/compiler/graph-tester.h
deleted file mode 100644
index e569245..0000000
--- a/test/cctest/compiler/graph-tester.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_CCTEST_COMPILER_GRAPH_TESTER_H_
-#define V8_CCTEST_COMPILER_GRAPH_TESTER_H_
-
-#include "src/v8.h"
-#include "test/cctest/cctest.h"
-
-#include "src/compiler/common-operator.h"
-#include "src/compiler/graph.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-class GraphTester : public HandleAndZoneScope, public Graph {
- public:
- GraphTester() : Graph(main_zone()) {}
-};
-
-
-class GraphWithStartNodeTester : public GraphTester {
- public:
- explicit GraphWithStartNodeTester(int num_parameters = 0)
- : builder_(main_zone()),
- start_node_(NewNode(builder_.Start(num_parameters))) {
- SetStart(start_node_);
- }
-
- Node* start_node() { return start_node_; }
-
- private:
- CommonOperatorBuilder builder_;
- Node* start_node_;
-};
-}
-}
-} // namespace v8::internal::compiler
-
-#endif // V8_CCTEST_COMPILER_GRAPH_TESTER_H_
diff --git a/test/cctest/compiler/instruction-selector-tester.h b/test/cctest/compiler/instruction-selector-tester.h
deleted file mode 100644
index 3a28b2e..0000000
--- a/test/cctest/compiler/instruction-selector-tester.h
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_CCTEST_COMPILER_INSTRUCTION_SELECTOR_TEST_H_
-#define V8_CCTEST_COMPILER_INSTRUCTION_SELECTOR_TEST_H_
-
-#include <deque>
-#include <set>
-
-#include "src/compiler/instruction-selector.h"
-#include "src/compiler/raw-machine-assembler.h"
-#include "src/ostreams.h"
-#include "test/cctest/cctest.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-typedef std::set<int> VirtualRegisterSet;
-
-enum InstructionSelectorTesterMode { kTargetMode, kInternalMode };
-
-class InstructionSelectorTester : public HandleAndZoneScope,
- public RawMachineAssembler {
- public:
- enum Mode { kTargetMode, kInternalMode };
-
- static const int kParameterCount = 3;
- static MachineType* BuildParameterArray(Zone* zone) {
- MachineType* array = zone->NewArray<MachineType>(kParameterCount);
- for (int i = 0; i < kParameterCount; ++i) {
- array[i] = kMachInt32;
- }
- return array;
- }
-
- InstructionSelectorTester()
- : RawMachineAssembler(
- new (main_zone()) Graph(main_zone()),
- new (main_zone()) MachineCallDescriptorBuilder(
- kMachInt32, kParameterCount, BuildParameterArray(main_zone())),
- kMachPtr) {}
-
- void SelectInstructions(CpuFeature feature) {
- SelectInstructions(InstructionSelector::Features(feature));
- }
-
- void SelectInstructions(CpuFeature feature1, CpuFeature feature2) {
- SelectInstructions(InstructionSelector::Features(feature1, feature2));
- }
-
- void SelectInstructions(Mode mode = kTargetMode) {
- SelectInstructions(InstructionSelector::Features(), mode);
- }
-
- void SelectInstructions(InstructionSelector::Features features,
- Mode mode = kTargetMode) {
- OFStream out(stdout);
- Schedule* schedule = Export();
- CHECK_NE(0, graph()->NodeCount());
- CompilationInfo info(main_isolate(), main_zone());
- Linkage linkage(&info, call_descriptor());
- InstructionSequence sequence(&linkage, graph(), schedule);
- SourcePositionTable source_positions(graph());
- InstructionSelector selector(&sequence, &source_positions, features);
- selector.SelectInstructions();
- out << "--- Code sequence after instruction selection --- " << endl
- << sequence;
- for (InstructionSequence::const_iterator i = sequence.begin();
- i != sequence.end(); ++i) {
- Instruction* instr = *i;
- if (instr->opcode() < 0) continue;
- if (mode == kTargetMode) {
- switch (ArchOpcodeField::decode(instr->opcode())) {
-#define CASE(Name) \
- case k##Name: \
- break;
- TARGET_ARCH_OPCODE_LIST(CASE)
-#undef CASE
- default:
- continue;
- }
- }
- code.push_back(instr);
- }
- for (int vreg = 0; vreg < sequence.VirtualRegisterCount(); ++vreg) {
- if (sequence.IsDouble(vreg)) {
- CHECK(!sequence.IsReference(vreg));
- doubles.insert(vreg);
- }
- if (sequence.IsReference(vreg)) {
- CHECK(!sequence.IsDouble(vreg));
- references.insert(vreg);
- }
- }
- immediates.assign(sequence.immediates().begin(),
- sequence.immediates().end());
- }
-
- int32_t ToInt32(const InstructionOperand* operand) const {
- size_t i = operand->index();
- CHECK(i < immediates.size());
- CHECK_EQ(InstructionOperand::IMMEDIATE, operand->kind());
- return immediates[i].ToInt32();
- }
-
- std::deque<Instruction*> code;
- VirtualRegisterSet doubles;
- VirtualRegisterSet references;
- std::deque<Constant> immediates;
-};
-
-
-static inline void CheckSameVreg(InstructionOperand* exp,
- InstructionOperand* val) {
- CHECK_EQ(InstructionOperand::UNALLOCATED, exp->kind());
- CHECK_EQ(InstructionOperand::UNALLOCATED, val->kind());
- CHECK_EQ(UnallocatedOperand::cast(exp)->virtual_register(),
- UnallocatedOperand::cast(val)->virtual_register());
-}
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
-
-#endif // V8_CCTEST_COMPILER_INSTRUCTION_SELECTOR_TEST_H_
diff --git a/test/cctest/compiler/simplified-graph-builder.cc b/test/cctest/compiler/simplified-graph-builder.cc
deleted file mode 100644
index baa03fb..0000000
--- a/test/cctest/compiler/simplified-graph-builder.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "test/cctest/compiler/simplified-graph-builder.h"
-
-#include "src/compiler/operator-properties.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-SimplifiedGraphBuilder::SimplifiedGraphBuilder(
- Graph* graph, CommonOperatorBuilder* common,
- MachineOperatorBuilder* machine, SimplifiedOperatorBuilder* simplified)
- : GraphBuilder(graph),
- effect_(NULL),
- return_(NULL),
- common_(common),
- machine_(machine),
- simplified_(simplified) {}
-
-
-void SimplifiedGraphBuilder::Begin(int num_parameters) {
- DCHECK(graph()->start() == NULL);
- Node* start = graph()->NewNode(common()->Start(num_parameters));
- graph()->SetStart(start);
- effect_ = start;
-}
-
-
-void SimplifiedGraphBuilder::Return(Node* value) {
- return_ =
- graph()->NewNode(common()->Return(), value, effect_, graph()->start());
- effect_ = NULL;
-}
-
-
-void SimplifiedGraphBuilder::End() {
- Node* end = graph()->NewNode(common()->End(), return_);
- graph()->SetEnd(end);
-}
-
-
-Node* SimplifiedGraphBuilder::MakeNode(const Operator* op,
- int value_input_count,
- Node** value_inputs, bool incomplete) {
- DCHECK(op->ValueInputCount() == value_input_count);
-
- DCHECK(!OperatorProperties::HasContextInput(op));
- DCHECK(!OperatorProperties::HasFrameStateInput(op));
- bool has_control = op->ControlInputCount() == 1;
- bool has_effect = op->EffectInputCount() == 1;
-
- DCHECK(op->ControlInputCount() < 2);
- DCHECK(op->EffectInputCount() < 2);
-
- Node* result = NULL;
- if (!has_control && !has_effect) {
- result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
- } else {
- int input_count_with_deps = value_input_count;
- if (has_control) ++input_count_with_deps;
- if (has_effect) ++input_count_with_deps;
- Node** buffer = zone()->NewArray<Node*>(input_count_with_deps);
- memcpy(buffer, value_inputs, kPointerSize * value_input_count);
- Node** current_input = buffer + value_input_count;
- if (has_effect) {
- *current_input++ = effect_;
- }
- if (has_control) {
- *current_input++ = graph()->start();
- }
- result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
- if (has_effect) {
- effect_ = result;
- }
- // This graph builder does not support control flow.
- CHECK_EQ(0, op->ControlOutputCount());
- }
-
- return result;
-}
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
diff --git a/test/cctest/compiler/simplified-graph-builder.h b/test/cctest/compiler/simplified-graph-builder.h
deleted file mode 100644
index 537094a..0000000
--- a/test/cctest/compiler/simplified-graph-builder.h
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_CCTEST_COMPILER_SIMPLIFIED_GRAPH_BUILDER_H_
-#define V8_CCTEST_COMPILER_SIMPLIFIED_GRAPH_BUILDER_H_
-
-#include "src/compiler/common-operator.h"
-#include "src/compiler/graph-builder.h"
-#include "src/compiler/machine-operator.h"
-#include "src/compiler/simplified-operator.h"
-#include "test/cctest/cctest.h"
-#include "test/cctest/compiler/call-tester.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-class SimplifiedGraphBuilder : public GraphBuilder {
- public:
- SimplifiedGraphBuilder(Graph* graph, CommonOperatorBuilder* common,
- MachineOperatorBuilder* machine,
- SimplifiedOperatorBuilder* simplified);
- virtual ~SimplifiedGraphBuilder() {}
-
- Zone* zone() const { return graph()->zone(); }
- Isolate* isolate() const { return zone()->isolate(); }
- CommonOperatorBuilder* common() const { return common_; }
- MachineOperatorBuilder* machine() const { return machine_; }
- SimplifiedOperatorBuilder* simplified() const { return simplified_; }
-
- // Initialize graph and builder.
- void Begin(int num_parameters);
-
- void Return(Node* value);
-
- // Close the graph.
- void End();
-
- Node* PointerConstant(void* value) {
- intptr_t intptr_value = reinterpret_cast<intptr_t>(value);
- return kPointerSize == 8 ? NewNode(common()->Int64Constant(intptr_value))
- : Int32Constant(static_cast<int>(intptr_value));
- }
- Node* Int32Constant(int32_t value) {
- return NewNode(common()->Int32Constant(value));
- }
- Node* HeapConstant(Handle<HeapObject> object) {
- Unique<HeapObject> val = Unique<HeapObject>::CreateUninitialized(object);
- return NewNode(common()->HeapConstant(val));
- }
-
- Node* BooleanNot(Node* a) { return NewNode(simplified()->BooleanNot(), a); }
-
- Node* NumberEqual(Node* a, Node* b) {
- return NewNode(simplified()->NumberEqual(), a, b);
- }
- Node* NumberLessThan(Node* a, Node* b) {
- return NewNode(simplified()->NumberLessThan(), a, b);
- }
- Node* NumberLessThanOrEqual(Node* a, Node* b) {
- return NewNode(simplified()->NumberLessThanOrEqual(), a, b);
- }
- Node* NumberAdd(Node* a, Node* b) {
- return NewNode(simplified()->NumberAdd(), a, b);
- }
- Node* NumberSubtract(Node* a, Node* b) {
- return NewNode(simplified()->NumberSubtract(), a, b);
- }
- Node* NumberMultiply(Node* a, Node* b) {
- return NewNode(simplified()->NumberMultiply(), a, b);
- }
- Node* NumberDivide(Node* a, Node* b) {
- return NewNode(simplified()->NumberDivide(), a, b);
- }
- Node* NumberModulus(Node* a, Node* b) {
- return NewNode(simplified()->NumberModulus(), a, b);
- }
- Node* NumberToInt32(Node* a) {
- return NewNode(simplified()->NumberToInt32(), a);
- }
- Node* NumberToUint32(Node* a) {
- return NewNode(simplified()->NumberToUint32(), a);
- }
-
- Node* StringEqual(Node* a, Node* b) {
- return NewNode(simplified()->StringEqual(), a, b);
- }
- Node* StringLessThan(Node* a, Node* b) {
- return NewNode(simplified()->StringLessThan(), a, b);
- }
- Node* StringLessThanOrEqual(Node* a, Node* b) {
- return NewNode(simplified()->StringLessThanOrEqual(), a, b);
- }
- Node* StringAdd(Node* a, Node* b) {
- return NewNode(simplified()->StringAdd(), a, b);
- }
-
- Node* ChangeTaggedToInt32(Node* a) {
- return NewNode(simplified()->ChangeTaggedToInt32(), a);
- }
- Node* ChangeTaggedToUint32(Node* a) {
- return NewNode(simplified()->ChangeTaggedToUint32(), a);
- }
- Node* ChangeTaggedToFloat64(Node* a) {
- return NewNode(simplified()->ChangeTaggedToFloat64(), a);
- }
- Node* ChangeInt32ToTagged(Node* a) {
- return NewNode(simplified()->ChangeInt32ToTagged(), a);
- }
- Node* ChangeUint32ToTagged(Node* a) {
- return NewNode(simplified()->ChangeUint32ToTagged(), a);
- }
- Node* ChangeFloat64ToTagged(Node* a) {
- return NewNode(simplified()->ChangeFloat64ToTagged(), a);
- }
- Node* ChangeBoolToBit(Node* a) {
- return NewNode(simplified()->ChangeBoolToBit(), a);
- }
- Node* ChangeBitToBool(Node* a) {
- return NewNode(simplified()->ChangeBitToBool(), a);
- }
-
- Node* LoadField(const FieldAccess& access, Node* object) {
- return NewNode(simplified()->LoadField(access), object);
- }
- Node* StoreField(const FieldAccess& access, Node* object, Node* value) {
- return NewNode(simplified()->StoreField(access), object, value);
- }
- Node* LoadElement(const ElementAccess& access, Node* object, Node* index) {
- return NewNode(simplified()->LoadElement(access), object, index);
- }
- Node* StoreElement(const ElementAccess& access, Node* object, Node* index,
- Node* value) {
- return NewNode(simplified()->StoreElement(access), object, index, value);
- }
-
- protected:
- virtual Node* MakeNode(const Operator* op, int value_input_count,
- Node** value_inputs, bool incomplete) FINAL;
-
- private:
- Node* effect_;
- Node* return_;
- CommonOperatorBuilder* common_;
- MachineOperatorBuilder* machine_;
- SimplifiedOperatorBuilder* simplified_;
-};
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
-
-#endif // V8_CCTEST_COMPILER_SIMPLIFIED_GRAPH_BUILDER_H_
diff --git a/test/cctest/compiler/test-basic-block-profiler.cc b/test/cctest/compiler/test-basic-block-profiler.cc
index 703fc17..17400ab 100644
--- a/test/cctest/compiler/test-basic-block-profiler.cc
+++ b/test/cctest/compiler/test-basic-block-profiler.cc
@@ -2,29 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "src/basic-block-profiler.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
-#if V8_TURBOFAN_TARGET
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-typedef RawMachineAssembler::Label MLabel;
+namespace v8 {
+namespace internal {
+namespace compiler {
class BasicBlockProfilerTest : public RawMachineAssemblerTester<int32_t> {
public:
- BasicBlockProfilerTest() : RawMachineAssemblerTester<int32_t>(kMachInt32) {
+ BasicBlockProfilerTest()
+ : RawMachineAssemblerTester<int32_t>(MachineType::Int32()) {
FLAG_turbo_profiling = true;
}
void ResetCounts() { isolate()->basic_block_profiler()->ResetCounts(); }
void Expect(size_t size, uint32_t* expected) {
- CHECK_NE(NULL, isolate()->basic_block_profiler());
+ CHECK(isolate()->basic_block_profiler());
const BasicBlockProfiler::DataList* l =
isolate()->basic_block_profiler()->data_list();
CHECK_NE(0, static_cast<int>(l->size()));
@@ -41,7 +37,7 @@
TEST(ProfileDiamond) {
BasicBlockProfilerTest m;
- MLabel blocka, blockb, end;
+ RawMachineLabel blocka, blockb, end;
m.Branch(m.Parameter(0), &blocka, &blockb);
m.Bind(&blocka);
m.Goto(&end);
@@ -81,12 +77,12 @@
TEST(ProfileLoop) {
BasicBlockProfilerTest m;
- MLabel header, body, end;
+ RawMachineLabel header, body, end;
Node* one = m.Int32Constant(1);
m.Goto(&header);
m.Bind(&header);
- Node* count = m.Phi(kMachInt32, m.Parameter(0), one);
+ Node* count = m.Phi(MachineRepresentation::kWord32, m.Parameter(0), one);
m.Branch(count, &body, &end);
m.Bind(&body);
@@ -111,4 +107,6 @@
}
}
-#endif // V8_TURBOFAN_TARGET
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-branch-combine.cc b/test/cctest/compiler/test-branch-combine.cc
index cd3472d..c3b4308 100644
--- a/test/cctest/compiler/test-branch-combine.cc
+++ b/test/cctest/compiler/test-branch-combine.cc
@@ -2,18 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
#include "test/cctest/compiler/value-helper.h"
-#if V8_TURBOFAN_TARGET
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-typedef RawMachineAssembler::Label MLabel;
+namespace v8 {
+namespace internal {
+namespace compiler {
static IrOpcode::Value int32cmp_opcodes[] = {
IrOpcode::kWord32Equal, IrOpcode::kInt32LessThan,
@@ -23,12 +18,12 @@
TEST(BranchCombineWord32EqualZero_1) {
// Test combining a branch with x == 0
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
int32_t eq_constant = -1033;
int32_t ne_constant = 825118;
Node* p0 = m.Parameter(0);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32Equal(p0, m.Int32Constant(0)), &blocka, &blockb);
m.Bind(&blocka);
m.Return(m.Int32Constant(eq_constant));
@@ -49,9 +44,9 @@
int32_t ne_constant = 815118;
for (int k = 0; k < 6; k++) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
Node* p0 = m.Parameter(0);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
Node* cond = p0;
for (int j = 0; j < k; j++) {
cond = m.Word32Equal(cond, m.Int32Constant(0));
@@ -74,12 +69,12 @@
TEST(BranchCombineInt32LessThanZero_1) {
// Test combining a branch with x < 0
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
int32_t eq_constant = -1433;
int32_t ne_constant = 845118;
Node* p0 = m.Parameter(0);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
m.Branch(m.Int32LessThan(p0, m.Int32Constant(0)), &blocka, &blockb);
m.Bind(&blocka);
m.Return(m.Int32Constant(eq_constant));
@@ -96,12 +91,12 @@
TEST(BranchCombineUint32LessThan100_1) {
// Test combining a branch with x < 100
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
int32_t eq_constant = 1471;
int32_t ne_constant = 88845718;
Node* p0 = m.Parameter(0);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
m.Branch(m.Uint32LessThan(p0, m.Int32Constant(100)), &blocka, &blockb);
m.Bind(&blocka);
m.Return(m.Int32Constant(eq_constant));
@@ -118,12 +113,12 @@
TEST(BranchCombineUint32LessThanOrEqual100_1) {
// Test combining a branch with x <= 100
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
int32_t eq_constant = 1479;
int32_t ne_constant = 77845719;
Node* p0 = m.Parameter(0);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
m.Branch(m.Uint32LessThanOrEqual(p0, m.Int32Constant(100)), &blocka, &blockb);
m.Bind(&blocka);
m.Return(m.Int32Constant(eq_constant));
@@ -140,12 +135,12 @@
TEST(BranchCombineZeroLessThanInt32_1) {
// Test combining a branch with 0 < x
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
int32_t eq_constant = -2033;
int32_t ne_constant = 225118;
Node* p0 = m.Parameter(0);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
m.Branch(m.Int32LessThan(m.Int32Constant(0), p0), &blocka, &blockb);
m.Bind(&blocka);
m.Return(m.Int32Constant(eq_constant));
@@ -162,12 +157,12 @@
TEST(BranchCombineInt32GreaterThanZero_1) {
// Test combining a branch with x > 0
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
int32_t eq_constant = -1073;
int32_t ne_constant = 825178;
Node* p0 = m.Parameter(0);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
m.Branch(m.Int32GreaterThan(p0, m.Int32Constant(0)), &blocka, &blockb);
m.Bind(&blocka);
m.Return(m.Int32Constant(eq_constant));
@@ -184,13 +179,14 @@
TEST(BranchCombineWord32EqualP) {
// Test combining a branch with an Word32Equal.
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+ MachineType::Int32());
int32_t eq_constant = -1035;
int32_t ne_constant = 825018;
Node* p0 = m.Parameter(0);
Node* p1 = m.Parameter(1);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32Equal(p0, p1), &blocka, &blockb);
m.Bind(&blocka);
m.Return(m.Int32Constant(eq_constant));
@@ -214,13 +210,13 @@
for (int left = 0; left < 2; left++) {
FOR_INT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
int32_t a = *i;
Node* p0 = m.Int32Constant(a);
Node* p1 = m.Parameter(0);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
if (left == 1) m.Branch(m.Word32Equal(p0, p1), &blocka, &blockb);
if (left == 0) m.Branch(m.Word32Equal(p1, p0), &blocka, &blockb);
m.Bind(&blocka);
@@ -243,11 +239,12 @@
int32_t ne_constant = 725018;
for (int op = 0; op < 2; op++) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+ MachineType::Int32());
Node* p0 = m.Parameter(0);
Node* p1 = m.Parameter(1);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
if (op == 0) m.Branch(m.Int32LessThan(p0, p1), &blocka, &blockb);
if (op == 1) m.Branch(m.Int32LessThanOrEqual(p0, p1), &blocka, &blockb);
m.Bind(&blocka);
@@ -275,12 +272,12 @@
for (int op = 0; op < 2; op++) {
FOR_INT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
int32_t a = *i;
Node* p0 = m.Int32Constant(a);
Node* p1 = m.Parameter(0);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
if (op == 0) m.Branch(m.Int32LessThan(p0, p1), &blocka, &blockb);
if (op == 1) m.Branch(m.Int32LessThanOrEqual(p0, p1), &blocka, &blockb);
m.Bind(&blocka);
@@ -336,7 +333,7 @@
: w(opcode), invert(i), true_first(t), eq_constant(eq), ne_constant(ne) {}
virtual void gen(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) {
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
Node* cond = w.MakeNode(m, a, b);
if (invert) cond = m->Word32Equal(cond, m->Int32Constant(0));
m->Branch(cond, &blocka, &blockb);
@@ -415,7 +412,7 @@
TEST(BranchCombineFloat64Compares) {
double inf = V8_INFINITY;
- double nan = v8::base::OS::nan_value();
+ double nan = std::numeric_limits<double>::quiet_NaN();
double inputs[] = {0.0, 1.0, -1.0, -inf, inf, nan};
int32_t eq_constant = -1733;
@@ -432,10 +429,10 @@
CompareWrapper cmp = cmps[c];
for (int invert = 0; invert < 2; invert++) {
RawMachineAssemblerTester<int32_t> m;
- Node* a = m.LoadFromPointer(&input_a, kMachFloat64);
- Node* b = m.LoadFromPointer(&input_b, kMachFloat64);
+ Node* a = m.LoadFromPointer(&input_a, MachineType::Float64());
+ Node* b = m.LoadFromPointer(&input_b, MachineType::Float64());
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
Node* cond = cmp.MakeNode(&m, a, b);
if (invert) cond = m.Word32Equal(cond, m.Int32Constant(0));
m.Branch(cond, &blocka, &blockb);
@@ -444,10 +441,10 @@
m.Bind(&blockb);
m.Return(m.Int32Constant(ne_constant));
- for (size_t i = 0; i < arraysize(inputs); i++) {
- for (size_t j = 0; j < arraysize(inputs); j += 2) {
+ for (size_t i = 0; i < arraysize(inputs); ++i) {
+ for (size_t j = 0; j < arraysize(inputs); ++j) {
input_a = inputs[i];
- input_b = inputs[i];
+ input_b = inputs[j];
int32_t expected =
invert ? (cmp.Float64Compare(input_a, input_b) ? ne_constant
: eq_constant)
@@ -459,4 +456,7 @@
}
}
}
-#endif // V8_TURBOFAN_TARGET
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-changes-lowering.cc b/test/cctest/compiler/test-changes-lowering.cc
index 5795754..e850da7 100644
--- a/test/cctest/compiler/test-changes-lowering.cc
+++ b/test/cctest/compiler/test-changes-lowering.cc
@@ -4,10 +4,11 @@
#include <limits>
+#include "src/ast/scopes.h"
#include "src/compiler/change-lowering.h"
#include "src/compiler/control-builders.h"
#include "src/compiler/js-graph.h"
-#include "src/compiler/node-properties-inl.h"
+#include "src/compiler/node-properties.h"
#include "src/compiler/pipeline.h"
#include "src/compiler/select-lowering.h"
#include "src/compiler/simplified-lowering.h"
@@ -15,25 +16,26 @@
#include "src/compiler/verifier.h"
#include "src/execution.h"
#include "src/globals.h"
-#include "src/parser.h"
-#include "src/rewriter.h"
-#include "src/scopes.h"
+#include "src/parsing/parser.h"
+#include "src/parsing/rewriter.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
#include "test/cctest/compiler/function-tester.h"
#include "test/cctest/compiler/graph-builder-tester.h"
#include "test/cctest/compiler/value-helper.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
template <typename ReturnType>
class ChangesLoweringTester : public GraphBuilderTester<ReturnType> {
public:
- explicit ChangesLoweringTester(MachineType p0 = kMachNone)
+ explicit ChangesLoweringTester(MachineType p0 = MachineType::None())
: GraphBuilderTester<ReturnType>(p0),
javascript(this->zone()),
- jsgraph(this->graph(), this->common(), &javascript, this->machine()),
+ jsgraph(this->isolate(), this->graph(), this->common(), &javascript,
+ nullptr, this->machine()),
function(Handle<JSFunction>::null()) {}
JSOperatorBuilder javascript;
@@ -58,22 +60,22 @@
void StoreFloat64(Node* node, double* ptr) {
Node* ptr_node = this->PointerConstant(ptr);
- this->Store(kMachFloat64, ptr_node, node);
+ this->Store(MachineType::Float64(), ptr_node, node);
}
Node* LoadInt32(int32_t* ptr) {
Node* ptr_node = this->PointerConstant(ptr);
- return this->Load(kMachInt32, ptr_node);
+ return this->Load(MachineType::Int32(), ptr_node);
}
Node* LoadUint32(uint32_t* ptr) {
Node* ptr_node = this->PointerConstant(ptr);
- return this->Load(kMachUint32, ptr_node);
+ return this->Load(MachineType::Uint32(), ptr_node);
}
Node* LoadFloat64(double* ptr) {
Node* ptr_node = this->PointerConstant(ptr);
- return this->Load(kMachFloat64, ptr_node);
+ return this->Load(MachineType::Float64(), ptr_node);
}
void CheckNumber(double expected, Object* number) {
@@ -87,7 +89,7 @@
Node* change = this->graph()->NewNode(op, p0);
Node* ret = this->graph()->NewNode(this->common()->Return(), change,
this->start(), this->start());
- Node* end = this->graph()->NewNode(this->common()->End(), ret);
+ Node* end = this->graph()->NewNode(this->common()->End(1), ret);
this->graph()->SetEnd(end);
LowerChange(change);
}
@@ -103,7 +105,7 @@
change, this->start(), this->start());
Node* ret = this->graph()->NewNode(
this->common()->Return(), this->Int32Constant(0), store, this->start());
- Node* end = this->graph()->NewNode(this->common()->End(), ret);
+ Node* end = this->graph()->NewNode(this->common()->End(1), ret);
this->graph()->SetEnd(end);
LowerChange(change);
}
@@ -118,20 +120,18 @@
Node* change = this->graph()->NewNode(op, load);
Node* ret = this->graph()->NewNode(this->common()->Return(), change,
this->start(), this->start());
- Node* end = this->graph()->NewNode(this->common()->End(), ret);
+ Node* end = this->graph()->NewNode(this->common()->End(1), ret);
this->graph()->SetEnd(end);
LowerChange(change);
}
void LowerChange(Node* change) {
// Run the graph reducer with changes lowering on a single node.
- CompilationInfo info(this->isolate(), this->zone());
- Linkage linkage(this->zone(), &info);
- Typer typer(this->graph(), info.context());
+ Typer typer(this->isolate(), this->graph());
typer.Run();
- ChangeLowering change_lowering(&jsgraph, &linkage);
+ ChangeLowering change_lowering(&jsgraph);
SelectLowering select_lowering(this->graph(), this->common());
- GraphReducer reducer(this->graph(), this->zone());
+ GraphReducer reducer(this->zone(), this->graph());
reducer.AddReducer(&change_lowering);
reducer.AddReducer(&select_lowering);
reducer.ReduceNode(change);
@@ -145,10 +145,9 @@
TEST(RunChangeTaggedToInt32) {
// Build and lower a graph by hand.
- ChangesLoweringTester<int32_t> t(kMachAnyTagged);
+ ChangesLoweringTester<int32_t> t(MachineType::AnyTagged());
t.BuildAndLower(t.simplified()->ChangeTaggedToInt32());
- if (Pipeline::SupportedTarget()) {
FOR_INT32_INPUTS(i) {
int32_t input = *i;
@@ -168,17 +167,15 @@
int32_t result = t.Call(*number);
CHECK_EQ(input, result);
}
- }
}
}
TEST(RunChangeTaggedToUint32) {
// Build and lower a graph by hand.
- ChangesLoweringTester<uint32_t> t(kMachAnyTagged);
+ ChangesLoweringTester<uint32_t> t(MachineType::AnyTagged());
t.BuildAndLower(t.simplified()->ChangeTaggedToUint32());
- if (Pipeline::SupportedTarget()) {
FOR_UINT32_INPUTS(i) {
uint32_t input = *i;
@@ -199,20 +196,19 @@
CHECK_EQ(static_cast<int32_t>(input), static_cast<int32_t>(result));
}
}
- }
}
TEST(RunChangeTaggedToFloat64) {
- ChangesLoweringTester<int32_t> t(kMachAnyTagged);
+ ChangesLoweringTester<int32_t> t(MachineType::AnyTagged());
double result;
- t.BuildStoreAndLower(
- t.simplified()->ChangeTaggedToFloat64(),
- t.machine()->Store(StoreRepresentation(kMachFloat64, kNoWriteBarrier)),
- &result);
+ t.BuildStoreAndLower(t.simplified()->ChangeTaggedToFloat64(),
+ t.machine()->Store(StoreRepresentation(
+ MachineRepresentation::kFloat64, kNoWriteBarrier)),
+ &result);
- if (Pipeline::SupportedTarget()) {
+ {
FOR_INT32_INPUTS(i) {
int32_t input = *i;
@@ -235,19 +231,19 @@
}
}
- if (Pipeline::SupportedTarget()) {
+ {
FOR_FLOAT64_INPUTS(i) {
double input = *i;
{
Handle<Object> number = t.factory()->NewNumber(input);
t.Call(*number);
- CHECK_EQ(input, result);
+ CheckDoubleEq(input, result);
}
{
Handle<HeapNumber> number = t.factory()->NewHeapNumber(input);
t.Call(*number);
- CHECK_EQ(input, result);
+ CheckDoubleEq(input, result);
}
}
}
@@ -255,16 +251,16 @@
TEST(RunChangeBoolToBit) {
- ChangesLoweringTester<int32_t> t(kMachAnyTagged);
+ ChangesLoweringTester<int32_t> t(MachineType::AnyTagged());
t.BuildAndLower(t.simplified()->ChangeBoolToBit());
- if (Pipeline::SupportedTarget()) {
+ {
Object* true_obj = t.heap()->true_value();
int32_t result = t.Call(true_obj);
CHECK_EQ(1, result);
}
- if (Pipeline::SupportedTarget()) {
+ {
Object* false_obj = t.heap()->false_value();
int32_t result = t.Call(false_obj);
CHECK_EQ(0, result);
@@ -273,125 +269,22 @@
TEST(RunChangeBitToBool) {
- ChangesLoweringTester<Object*> t(kMachInt32);
+ ChangesLoweringTester<Object*> t(MachineType::Int32());
t.BuildAndLower(t.simplified()->ChangeBitToBool());
- if (Pipeline::SupportedTarget()) {
+ {
Object* result = t.Call(1);
Object* true_obj = t.heap()->true_value();
CHECK_EQ(true_obj, result);
}
- if (Pipeline::SupportedTarget()) {
+ {
Object* result = t.Call(0);
Object* false_obj = t.heap()->false_value();
CHECK_EQ(false_obj, result);
}
}
-
-#if V8_TURBOFAN_BACKEND
-// TODO(titzer): disabled on ARM
-
-TEST(RunChangeInt32ToTaggedSmi) {
- ChangesLoweringTester<Object*> t;
- int32_t input;
- t.BuildLoadAndLower(t.simplified()->ChangeInt32ToTagged(),
- t.machine()->Load(kMachInt32), &input);
-
- if (Pipeline::SupportedTarget()) {
- FOR_INT32_INPUTS(i) {
- input = *i;
- if (!Smi::IsValid(input)) continue;
- Object* result = t.Call();
- t.CheckNumber(static_cast<double>(input), result);
- }
- }
-}
-
-
-TEST(RunChangeUint32ToTaggedSmi) {
- ChangesLoweringTester<Object*> t;
- uint32_t input;
- t.BuildLoadAndLower(t.simplified()->ChangeUint32ToTagged(),
- t.machine()->Load(kMachUint32), &input);
-
- if (Pipeline::SupportedTarget()) {
- FOR_UINT32_INPUTS(i) {
- input = *i;
- if (input > static_cast<uint32_t>(Smi::kMaxValue)) continue;
- Object* result = t.Call();
- double expected = static_cast<double>(input);
- t.CheckNumber(expected, result);
- }
- }
-}
-
-
-TEST(RunChangeInt32ToTagged) {
- ChangesLoweringTester<Object*> t;
- int32_t input;
- t.BuildLoadAndLower(t.simplified()->ChangeInt32ToTagged(),
- t.machine()->Load(kMachInt32), &input);
-
- if (Pipeline::SupportedTarget()) {
- for (int m = 0; m < 3; m++) { // Try 3 GC modes.
- FOR_INT32_INPUTS(i) {
- if (m == 0) CcTest::heap()->EnableInlineAllocation();
- if (m == 1) CcTest::heap()->DisableInlineAllocation();
- if (m == 2) SimulateFullSpace(CcTest::heap()->new_space());
-
- input = *i;
- Object* result = t.CallWithPotentialGC<Object>();
- t.CheckNumber(static_cast<double>(input), result);
- }
- }
- }
-}
-
-
-TEST(RunChangeUint32ToTagged) {
- ChangesLoweringTester<Object*> t;
- uint32_t input;
- t.BuildLoadAndLower(t.simplified()->ChangeUint32ToTagged(),
- t.machine()->Load(kMachUint32), &input);
-
- if (Pipeline::SupportedTarget()) {
- for (int m = 0; m < 3; m++) { // Try 3 GC modes.
- FOR_UINT32_INPUTS(i) {
- if (m == 0) CcTest::heap()->EnableInlineAllocation();
- if (m == 1) CcTest::heap()->DisableInlineAllocation();
- if (m == 2) SimulateFullSpace(CcTest::heap()->new_space());
-
- input = *i;
- Object* result = t.CallWithPotentialGC<Object>();
- double expected = static_cast<double>(input);
- t.CheckNumber(expected, result);
- }
- }
- }
-}
-
-
-TEST(RunChangeFloat64ToTagged) {
- ChangesLoweringTester<Object*> t;
- double input;
- t.BuildLoadAndLower(t.simplified()->ChangeFloat64ToTagged(),
- t.machine()->Load(kMachFloat64), &input);
-
- if (Pipeline::SupportedTarget()) {
- for (int m = 0; m < 3; m++) { // Try 3 GC modes.
- FOR_FLOAT64_INPUTS(i) {
- if (m == 0) CcTest::heap()->EnableInlineAllocation();
- if (m == 1) CcTest::heap()->DisableInlineAllocation();
- if (m == 2) SimulateFullSpace(CcTest::heap()->new_space());
-
- input = *i;
- Object* result = t.CallWithPotentialGC<Object>();
- t.CheckNumber(input, result);
- }
- }
- }
-}
-
-#endif // V8_TURBOFAN_BACKEND
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-code-stub-assembler.cc b/test/cctest/compiler/test-code-stub-assembler.cc
new file mode 100644
index 0000000..d7a7a81
--- /dev/null
+++ b/test/cctest/compiler/test-code-stub-assembler.cc
@@ -0,0 +1,125 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/interface-descriptors.h"
+#include "src/isolate.h"
+#include "test/cctest/compiler/function-tester.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+
+class CodeStubAssemblerTester : public CodeStubAssembler {
+ public:
+ CodeStubAssemblerTester(Isolate* isolate,
+ const CallInterfaceDescriptor& descriptor)
+ : CodeStubAssembler(isolate, isolate->runtime_zone(), descriptor,
+ Code::STUB, "test"),
+ scope_(isolate) {}
+
+ private:
+ HandleScope scope_;
+ LocalContext context_;
+};
+
+
+TEST(SimpleSmiReturn) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ VoidDescriptor descriptor(isolate);
+ CodeStubAssemblerTester m(isolate, descriptor);
+ m.Return(m.SmiTag(m.Int32Constant(37)));
+ Handle<Code> code = m.GenerateCode();
+ FunctionTester ft(descriptor, code);
+ MaybeHandle<Object> result = ft.Call();
+ CHECK_EQ(37, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+
+TEST(SimpleIntPtrReturn) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ VoidDescriptor descriptor(isolate);
+ CodeStubAssemblerTester m(isolate, descriptor);
+ int test;
+ m.Return(m.IntPtrConstant(reinterpret_cast<intptr_t>(&test)));
+ Handle<Code> code = m.GenerateCode();
+ FunctionTester ft(descriptor, code);
+ MaybeHandle<Object> result = ft.Call();
+ CHECK_EQ(reinterpret_cast<intptr_t>(&test),
+ reinterpret_cast<intptr_t>(*result.ToHandleChecked()));
+}
+
+
+TEST(SimpleDoubleReturn) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ VoidDescriptor descriptor(isolate);
+ CodeStubAssemblerTester m(isolate, descriptor);
+ m.Return(m.NumberConstant(0.5));
+ Handle<Code> code = m.GenerateCode();
+ FunctionTester ft(descriptor, code);
+ MaybeHandle<Object> result = ft.Call();
+ CHECK_EQ(0.5, Handle<HeapNumber>::cast(result.ToHandleChecked())->value());
+}
+
+
+TEST(SimpleCallRuntime1Arg) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ VoidDescriptor descriptor(isolate);
+ CodeStubAssemblerTester m(isolate, descriptor);
+ Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
+ Node* b = m.SmiTag(m.Int32Constant(256));
+ m.Return(m.CallRuntime(Runtime::kMathSqrt, context, b));
+ Handle<Code> code = m.GenerateCode();
+ FunctionTester ft(descriptor, code);
+ MaybeHandle<Object> result = ft.Call();
+ CHECK_EQ(16, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+
+TEST(SimpleTailCallRuntime1Arg) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ VoidDescriptor descriptor(isolate);
+ CodeStubAssemblerTester m(isolate, descriptor);
+ Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
+ Node* b = m.SmiTag(m.Int32Constant(256));
+ m.TailCallRuntime(Runtime::kMathSqrt, context, b);
+ Handle<Code> code = m.GenerateCode();
+ FunctionTester ft(descriptor, code);
+ MaybeHandle<Object> result = ft.Call();
+ CHECK_EQ(16, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+
+TEST(SimpleCallRuntime2Arg) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ VoidDescriptor descriptor(isolate);
+ CodeStubAssemblerTester m(isolate, descriptor);
+ Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
+ Node* a = m.SmiTag(m.Int32Constant(2));
+ Node* b = m.SmiTag(m.Int32Constant(4));
+ m.Return(m.CallRuntime(Runtime::kMathPow, context, a, b));
+ Handle<Code> code = m.GenerateCode();
+ FunctionTester ft(descriptor, code);
+ MaybeHandle<Object> result = ft.Call();
+ CHECK_EQ(16, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+
+TEST(SimpleTailCallRuntime2Arg) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ VoidDescriptor descriptor(isolate);
+ CodeStubAssemblerTester m(isolate, descriptor);
+ Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
+ Node* a = m.SmiTag(m.Int32Constant(2));
+ Node* b = m.SmiTag(m.Int32Constant(4));
+ m.TailCallRuntime(Runtime::kMathPow, context, a, b);
+ Handle<Code> code = m.GenerateCode();
+ FunctionTester ft(descriptor, code);
+ MaybeHandle<Object> result = ft.Call();
+ CHECK_EQ(16, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-codegen-deopt.cc b/test/cctest/compiler/test-codegen-deopt.cc
deleted file mode 100644
index 56afe7b..0000000
--- a/test/cctest/compiler/test-codegen-deopt.cc
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-#include "test/cctest/cctest.h"
-
-#include "src/compiler/code-generator.h"
-#include "src/compiler/common-operator.h"
-#include "src/compiler/graph.h"
-#include "src/compiler/instruction-selector.h"
-#include "src/compiler/machine-operator.h"
-#include "src/compiler/node.h"
-#include "src/compiler/operator.h"
-#include "src/compiler/raw-machine-assembler.h"
-#include "src/compiler/register-allocator.h"
-#include "src/compiler/schedule.h"
-
-#include "src/ast-numbering.h"
-#include "src/full-codegen.h"
-#include "src/parser.h"
-#include "src/rewriter.h"
-
-#include "test/cctest/compiler/c-signature.h"
-#include "test/cctest/compiler/function-tester.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-
-#if V8_TURBOFAN_TARGET
-
-typedef RawMachineAssembler::Label MLabel;
-typedef v8::internal::compiler::InstructionSequence TestInstrSeq;
-
-static Handle<JSFunction> NewFunction(const char* source) {
- return v8::Utils::OpenHandle(
- *v8::Handle<v8::Function>::Cast(CompileRun(source)));
-}
-
-
-class DeoptCodegenTester {
- public:
- explicit DeoptCodegenTester(HandleAndZoneScope* scope, const char* src)
- : scope_(scope),
- function(NewFunction(src)),
- info(function, scope->main_zone()),
- bailout_id(-1) {
- CHECK(Parser::Parse(&info));
- info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
- CHECK(Compiler::Analyze(&info));
- CHECK(Compiler::EnsureDeoptimizationSupport(&info));
-
- DCHECK(info.shared_info()->has_deoptimization_support());
-
- graph = new (scope_->main_zone()) Graph(scope_->main_zone());
- }
-
- virtual ~DeoptCodegenTester() {}
-
- void GenerateCodeFromSchedule(Schedule* schedule) {
- OFStream os(stdout);
- if (FLAG_trace_turbo) {
- os << *schedule;
- }
- result_code = Pipeline::GenerateCodeForTesting(&info, graph, schedule);
-#ifdef OBJECT_PRINT
- if (FLAG_print_opt_code || FLAG_trace_turbo) {
- result_code->Print();
- }
-#endif
- }
-
- Zone* zone() { return scope_->main_zone(); }
-
- HandleAndZoneScope* scope_;
- Handle<JSFunction> function;
- CompilationInfo info;
- BailoutId bailout_id;
- Handle<Code> result_code;
- TestInstrSeq* code;
- Graph* graph;
-};
-
-
-class TrivialDeoptCodegenTester : public DeoptCodegenTester {
- public:
- explicit TrivialDeoptCodegenTester(HandleAndZoneScope* scope)
- : DeoptCodegenTester(scope,
- "function foo() { deopt(); return 42; }; foo") {}
-
- void GenerateCode() {
- GenerateCodeFromSchedule(BuildGraphAndSchedule(graph));
- }
-
- Schedule* BuildGraphAndSchedule(Graph* graph) {
- CommonOperatorBuilder common(zone());
-
- // Manually construct a schedule for the function below:
- // function foo() {
- // deopt();
- // }
-
- CSignature1<Object*, Object*> sig;
- RawMachineAssembler m(graph, &sig);
-
- Handle<JSFunction> deopt_function =
- NewFunction("function deopt() { %DeoptimizeFunction(foo); }; deopt");
- Unique<JSFunction> deopt_fun_constant =
- Unique<JSFunction>::CreateUninitialized(deopt_function);
- Node* deopt_fun_node = m.NewNode(common.HeapConstant(deopt_fun_constant));
-
- Handle<Context> caller_context(function->context(), CcTest::i_isolate());
- Unique<Context> caller_context_constant =
- Unique<Context>::CreateUninitialized(caller_context);
- Node* caller_context_node =
- m.NewNode(common.HeapConstant(caller_context_constant));
-
- bailout_id = GetCallBailoutId();
- Node* parameters = m.NewNode(common.StateValues(1), m.UndefinedConstant());
- Node* locals = m.NewNode(common.StateValues(0));
- Node* stack = m.NewNode(common.StateValues(0));
-
- Node* state_node = m.NewNode(
- common.FrameState(JS_FRAME, bailout_id,
- OutputFrameStateCombine::Ignore()),
- parameters, locals, stack, caller_context_node, m.UndefinedConstant());
-
- Handle<Context> context(deopt_function->context(), CcTest::i_isolate());
- Unique<Context> context_constant =
- Unique<Context>::CreateUninitialized(context);
- Node* context_node = m.NewNode(common.HeapConstant(context_constant));
-
- m.CallJS0(deopt_fun_node, m.UndefinedConstant(), context_node, state_node);
-
- m.Return(m.UndefinedConstant());
-
- // Schedule the graph:
- Schedule* schedule = m.Export();
-
- return schedule;
- }
-
- BailoutId GetCallBailoutId() {
- ZoneList<Statement*>* body = info.function()->body();
- for (int i = 0; i < body->length(); i++) {
- if (body->at(i)->IsExpressionStatement() &&
- body->at(i)->AsExpressionStatement()->expression()->IsCall()) {
- return body->at(i)->AsExpressionStatement()->expression()->id();
- }
- }
- CHECK(false);
- return BailoutId(-1);
- }
-};
-
-
-TEST(TurboTrivialDeoptCodegen) {
- HandleAndZoneScope scope;
- InitializedHandleScope handles;
-
- FLAG_allow_natives_syntax = true;
- FLAG_turbo_deoptimization = true;
-
- TrivialDeoptCodegenTester t(&scope);
- t.GenerateCode();
-
- DeoptimizationInputData* data =
- DeoptimizationInputData::cast(t.result_code->deoptimization_data());
-
- // TODO(jarin) Find a way to test the safepoint.
-
- // Check that we deoptimize to the right AST id.
- CHECK_EQ(1, data->DeoptCount());
- CHECK_EQ(t.bailout_id.ToInt(), data->AstId(0).ToInt());
-}
-
-
-TEST(TurboTrivialDeoptCodegenAndRun) {
- HandleAndZoneScope scope;
- InitializedHandleScope handles;
-
- FLAG_allow_natives_syntax = true;
- FLAG_turbo_deoptimization = true;
-
- TrivialDeoptCodegenTester t(&scope);
- t.GenerateCode();
-
- t.function->ReplaceCode(*t.result_code);
- t.info.context()->native_context()->AddOptimizedCode(*t.result_code);
-
- Isolate* isolate = scope.main_isolate();
- Handle<Object> result;
- bool has_pending_exception =
- !Execution::Call(isolate, t.function,
- isolate->factory()->undefined_value(), 0, NULL,
- false).ToHandle(&result);
- CHECK(!has_pending_exception);
- CHECK(result->SameValue(Smi::FromInt(42)));
-}
-
-
-class TrivialRuntimeDeoptCodegenTester : public DeoptCodegenTester {
- public:
- explicit TrivialRuntimeDeoptCodegenTester(HandleAndZoneScope* scope)
- : DeoptCodegenTester(
- scope,
- "function foo() { %DeoptimizeFunction(foo); return 42; }; foo") {}
-
- void GenerateCode() {
- GenerateCodeFromSchedule(BuildGraphAndSchedule(graph));
- }
-
- Schedule* BuildGraphAndSchedule(Graph* graph) {
- CommonOperatorBuilder common(zone());
-
- // Manually construct a schedule for the function below:
- // function foo() {
- // %DeoptimizeFunction(foo);
- // }
-
- CSignature1<Object*, Object*> sig;
- RawMachineAssembler m(graph, &sig);
-
- Unique<HeapObject> this_fun_constant =
- Unique<HeapObject>::CreateUninitialized(function);
- Node* this_fun_node = m.NewNode(common.HeapConstant(this_fun_constant));
-
- Handle<Context> context(function->context(), CcTest::i_isolate());
- Unique<HeapObject> context_constant =
- Unique<HeapObject>::CreateUninitialized(context);
- Node* context_node = m.NewNode(common.HeapConstant(context_constant));
-
- bailout_id = GetCallBailoutId();
- Node* parameters = m.NewNode(common.StateValues(1), m.UndefinedConstant());
- Node* locals = m.NewNode(common.StateValues(0));
- Node* stack = m.NewNode(common.StateValues(0));
-
- Node* state_node = m.NewNode(
- common.FrameState(JS_FRAME, bailout_id,
- OutputFrameStateCombine::Ignore()),
- parameters, locals, stack, context_node, m.UndefinedConstant());
-
- m.CallRuntime1(Runtime::kDeoptimizeFunction, this_fun_node, context_node,
- state_node);
-
- m.Return(m.UndefinedConstant());
-
- // Schedule the graph:
- Schedule* schedule = m.Export();
-
- return schedule;
- }
-
- BailoutId GetCallBailoutId() {
- ZoneList<Statement*>* body = info.function()->body();
- for (int i = 0; i < body->length(); i++) {
- if (body->at(i)->IsExpressionStatement() &&
- body->at(i)->AsExpressionStatement()->expression()->IsCallRuntime()) {
- return body->at(i)->AsExpressionStatement()->expression()->id();
- }
- }
- CHECK(false);
- return BailoutId(-1);
- }
-};
-
-
-TEST(TurboTrivialRuntimeDeoptCodegenAndRun) {
- HandleAndZoneScope scope;
- InitializedHandleScope handles;
-
- FLAG_allow_natives_syntax = true;
- FLAG_turbo_deoptimization = true;
-
- TrivialRuntimeDeoptCodegenTester t(&scope);
- t.GenerateCode();
-
- t.function->ReplaceCode(*t.result_code);
- t.info.context()->native_context()->AddOptimizedCode(*t.result_code);
-
- Isolate* isolate = scope.main_isolate();
- Handle<Object> result;
- bool has_pending_exception =
- !Execution::Call(isolate, t.function,
- isolate->factory()->undefined_value(), 0, NULL,
- false).ToHandle(&result);
- CHECK(!has_pending_exception);
- CHECK(result->SameValue(Smi::FromInt(42)));
-}
-
-#endif
diff --git a/test/cctest/compiler/test-control-reducer.cc b/test/cctest/compiler/test-control-reducer.cc
deleted file mode 100644
index 03aa50b..0000000
--- a/test/cctest/compiler/test-control-reducer.cc
+++ /dev/null
@@ -1,1678 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-#include "test/cctest/cctest.h"
-
-#include "src/base/bits.h"
-#include "src/compiler/common-operator.h"
-#include "src/compiler/control-reducer.h"
-#include "src/compiler/graph-inl.h"
-#include "src/compiler/js-graph.h"
-#include "src/compiler/node-properties-inl.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-static const size_t kNumLeafs = 4;
-
-// TODO(titzer): convert this whole file into unit tests.
-
-static int CheckInputs(Node* node, Node* i0 = NULL, Node* i1 = NULL,
- Node* i2 = NULL) {
- int count = 3;
- if (i2 == NULL) count = 2;
- if (i1 == NULL) count = 1;
- if (i0 == NULL) count = 0;
- CHECK_EQ(count, node->InputCount());
- if (i0 != NULL) CHECK_EQ(i0, node->InputAt(0));
- if (i1 != NULL) CHECK_EQ(i1, node->InputAt(1));
- if (i2 != NULL) CHECK_EQ(i2, node->InputAt(2));
- return count;
-}
-
-
-static int CheckMerge(Node* node, Node* i0 = NULL, Node* i1 = NULL,
- Node* i2 = NULL) {
- CHECK_EQ(IrOpcode::kMerge, node->opcode());
- int count = CheckInputs(node, i0, i1, i2);
- CHECK_EQ(count, node->op()->ControlInputCount());
- return count;
-}
-
-
-static int CheckLoop(Node* node, Node* i0 = NULL, Node* i1 = NULL,
- Node* i2 = NULL) {
- CHECK_EQ(IrOpcode::kLoop, node->opcode());
- int count = CheckInputs(node, i0, i1, i2);
- CHECK_EQ(count, node->op()->ControlInputCount());
- return count;
-}
-
-
-bool IsUsedBy(Node* a, Node* b) {
- for (UseIter i = a->uses().begin(); i != a->uses().end(); ++i) {
- if (b == *i) return true;
- }
- return false;
-}
-
-
-// A helper for all tests dealing with ControlTester.
-class ControlReducerTester : HandleAndZoneScope {
- public:
- ControlReducerTester()
- : isolate(main_isolate()),
- common(main_zone()),
- graph(main_zone()),
- jsgraph(&graph, &common, NULL, NULL),
- start(graph.NewNode(common.Start(1))),
- end(graph.NewNode(common.End(), start)),
- p0(graph.NewNode(common.Parameter(0), start)),
- zero(jsgraph.Int32Constant(0)),
- one(jsgraph.OneConstant()),
- half(jsgraph.Constant(0.5)),
- self(graph.NewNode(common.Int32Constant(0xaabbccdd))),
- dead(graph.NewNode(common.Dead())) {
- graph.SetEnd(end);
- graph.SetStart(start);
- leaf[0] = zero;
- leaf[1] = one;
- leaf[2] = half;
- leaf[3] = p0;
- }
-
- Isolate* isolate;
- CommonOperatorBuilder common;
- Graph graph;
- JSGraph jsgraph;
- Node* start;
- Node* end;
- Node* p0;
- Node* zero;
- Node* one;
- Node* half;
- Node* self;
- Node* dead;
- Node* leaf[kNumLeafs];
-
- Node* Phi(Node* a) {
- return SetSelfReferences(graph.NewNode(op(1, false), a, start));
- }
-
- Node* Phi(Node* a, Node* b) {
- return SetSelfReferences(graph.NewNode(op(2, false), a, b, start));
- }
-
- Node* Phi(Node* a, Node* b, Node* c) {
- return SetSelfReferences(graph.NewNode(op(3, false), a, b, c, start));
- }
-
- Node* Phi(Node* a, Node* b, Node* c, Node* d) {
- return SetSelfReferences(graph.NewNode(op(4, false), a, b, c, d, start));
- }
-
- Node* EffectPhi(Node* a) {
- return SetSelfReferences(graph.NewNode(op(1, true), a, start));
- }
-
- Node* EffectPhi(Node* a, Node* b) {
- return SetSelfReferences(graph.NewNode(op(2, true), a, b, start));
- }
-
- Node* EffectPhi(Node* a, Node* b, Node* c) {
- return SetSelfReferences(graph.NewNode(op(3, true), a, b, c, start));
- }
-
- Node* EffectPhi(Node* a, Node* b, Node* c, Node* d) {
- return SetSelfReferences(graph.NewNode(op(4, true), a, b, c, d, start));
- }
-
- Node* SetSelfReferences(Node* node) {
- for (Edge edge : node->input_edges()) {
- if (edge.to() == self) node->ReplaceInput(edge.index(), node);
- }
- return node;
- }
-
- const Operator* op(int count, bool effect) {
- return effect ? common.EffectPhi(count) : common.Phi(kMachAnyTagged, count);
- }
-
- void Trim() { ControlReducer::TrimGraph(main_zone(), &jsgraph); }
-
- void ReduceGraph() {
- ControlReducer::ReduceGraph(main_zone(), &jsgraph, &common);
- }
-
- // Checks one-step reduction of a phi.
- void ReducePhi(Node* expect, Node* phi) {
- Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, &common, phi);
- CHECK_EQ(expect, result);
- ReducePhiIterative(expect, phi); // iterative should give the same result.
- }
-
- void ReducePhiIterative(Node* expect, Node* phi) {
- p0->ReplaceInput(0, start); // hack: parameters may be trimmed.
- Node* ret = graph.NewNode(common.Return(), phi, start, start);
- Node* end = graph.NewNode(common.End(), ret);
- graph.SetEnd(end);
- ControlReducer::ReduceGraph(main_zone(), &jsgraph, &common);
- CheckInputs(end, ret);
- CheckInputs(ret, expect, start, start);
- }
-
- void ReduceMerge(Node* expect, Node* merge) {
- Node* result =
- ControlReducer::ReduceMergeForTesting(&jsgraph, &common, merge);
- CHECK_EQ(expect, result);
- }
-
- void ReduceMergeIterative(Node* expect, Node* merge) {
- p0->ReplaceInput(0, start); // hack: parameters may be trimmed.
- Node* end = graph.NewNode(common.End(), merge);
- graph.SetEnd(end);
- ReduceGraph();
- CheckInputs(end, expect);
- }
-
- void ReduceBranch(Node* expect, Node* branch) {
- Node* result =
- ControlReducer::ReduceBranchForTesting(&jsgraph, &common, branch);
- CHECK_EQ(expect, result);
- }
-
- Node* Return(Node* val, Node* effect, Node* control) {
- Node* ret = graph.NewNode(common.Return(), val, effect, control);
- end->ReplaceInput(0, ret);
- return ret;
- }
-};
-
-
-TEST(Trim1_live) {
- ControlReducerTester T;
- CHECK(IsUsedBy(T.start, T.p0));
- T.graph.SetEnd(T.p0);
- T.Trim();
- CHECK(IsUsedBy(T.start, T.p0));
- CheckInputs(T.p0, T.start);
-}
-
-
-TEST(Trim1_dead) {
- ControlReducerTester T;
- CHECK(IsUsedBy(T.start, T.p0));
- T.Trim();
- CHECK(!IsUsedBy(T.start, T.p0));
- CHECK_EQ(NULL, T.p0->InputAt(0));
-}
-
-
-TEST(Trim2_live) {
- ControlReducerTester T;
- Node* phi =
- T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start);
- CHECK(IsUsedBy(T.one, phi));
- CHECK(IsUsedBy(T.half, phi));
- CHECK(IsUsedBy(T.start, phi));
- T.graph.SetEnd(phi);
- T.Trim();
- CHECK(IsUsedBy(T.one, phi));
- CHECK(IsUsedBy(T.half, phi));
- CHECK(IsUsedBy(T.start, phi));
- CheckInputs(phi, T.one, T.half, T.start);
-}
-
-
-TEST(Trim2_dead) {
- ControlReducerTester T;
- Node* phi =
- T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start);
- CHECK(IsUsedBy(T.one, phi));
- CHECK(IsUsedBy(T.half, phi));
- CHECK(IsUsedBy(T.start, phi));
- T.Trim();
- CHECK(!IsUsedBy(T.one, phi));
- CHECK(!IsUsedBy(T.half, phi));
- CHECK(!IsUsedBy(T.start, phi));
- CHECK_EQ(NULL, phi->InputAt(0));
- CHECK_EQ(NULL, phi->InputAt(1));
- CHECK_EQ(NULL, phi->InputAt(2));
-}
-
-
-TEST(Trim_chain1) {
- ControlReducerTester T;
- const int kDepth = 15;
- Node* live[kDepth];
- Node* dead[kDepth];
- Node* end = T.start;
- for (int i = 0; i < kDepth; i++) {
- live[i] = end = T.graph.NewNode(T.common.Merge(1), end);
- dead[i] = T.graph.NewNode(T.common.Merge(1), end);
- }
- // end -> live[last] -> live[last-1] -> ... -> start
- // dead[last] ^ dead[last-1] ^ ... ^
- T.graph.SetEnd(end);
- T.Trim();
- for (int i = 0; i < kDepth; i++) {
- CHECK(!IsUsedBy(live[i], dead[i]));
- CHECK_EQ(NULL, dead[i]->InputAt(0));
- CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0));
- }
-}
-
-
-TEST(Trim_chain2) {
- ControlReducerTester T;
- const int kDepth = 15;
- Node* live[kDepth];
- Node* dead[kDepth];
- Node* l = T.start;
- Node* d = T.start;
- for (int i = 0; i < kDepth; i++) {
- live[i] = l = T.graph.NewNode(T.common.Merge(1), l);
- dead[i] = d = T.graph.NewNode(T.common.Merge(1), d);
- }
- // end -> live[last] -> live[last-1] -> ... -> start
- // dead[last] -> dead[last-1] -> ... -> start
- T.graph.SetEnd(l);
- T.Trim();
- CHECK(!IsUsedBy(T.start, dead[0]));
- for (int i = 0; i < kDepth; i++) {
- CHECK_EQ(i == 0 ? NULL : dead[i - 1], dead[i]->InputAt(0));
- CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0));
- }
-}
-
-
-TEST(Trim_cycle1) {
- ControlReducerTester T;
- Node* loop = T.graph.NewNode(T.common.Loop(1), T.start, T.start);
- loop->ReplaceInput(1, loop);
- Node* end = T.graph.NewNode(T.common.End(), loop);
- T.graph.SetEnd(end);
-
- CHECK(IsUsedBy(T.start, loop));
- CHECK(IsUsedBy(loop, end));
- CHECK(IsUsedBy(loop, loop));
-
- T.Trim();
-
- // nothing should have happened to the loop itself.
- CHECK(IsUsedBy(T.start, loop));
- CHECK(IsUsedBy(loop, end));
- CHECK(IsUsedBy(loop, loop));
- CheckInputs(loop, T.start, loop);
- CheckInputs(end, loop);
-}
-
-
-TEST(Trim_cycle2) {
- ControlReducerTester T;
- Node* loop = T.graph.NewNode(T.common.Loop(2), T.start, T.start);
- loop->ReplaceInput(1, loop);
- Node* end = T.graph.NewNode(T.common.End(), loop);
- Node* phi =
- T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, loop);
- T.graph.SetEnd(end);
-
- CHECK(IsUsedBy(T.start, loop));
- CHECK(IsUsedBy(loop, end));
- CHECK(IsUsedBy(loop, loop));
- CHECK(IsUsedBy(loop, phi));
- CHECK(IsUsedBy(T.one, phi));
- CHECK(IsUsedBy(T.half, phi));
-
- T.Trim();
-
- // nothing should have happened to the loop itself.
- CHECK(IsUsedBy(T.start, loop));
- CHECK(IsUsedBy(loop, end));
- CHECK(IsUsedBy(loop, loop));
- CheckInputs(loop, T.start, loop);
- CheckInputs(end, loop);
-
- // phi should have been trimmed away.
- CHECK(!IsUsedBy(loop, phi));
- CHECK(!IsUsedBy(T.one, phi));
- CHECK(!IsUsedBy(T.half, phi));
- CHECK_EQ(NULL, phi->InputAt(0));
- CHECK_EQ(NULL, phi->InputAt(1));
- CHECK_EQ(NULL, phi->InputAt(2));
-}
-
-
-void CheckTrimConstant(ControlReducerTester* T, Node* k) {
- Node* phi = T->graph.NewNode(T->common.Phi(kMachInt32, 1), k, T->start);
- CHECK(IsUsedBy(k, phi));
- T->Trim();
- CHECK(!IsUsedBy(k, phi));
- CHECK_EQ(NULL, phi->InputAt(0));
- CHECK_EQ(NULL, phi->InputAt(1));
-}
-
-
-TEST(Trim_constants) {
- ControlReducerTester T;
- int32_t int32_constants[] = {
- 0, -1, -2, 2, 2, 3, 3, 4, 4, 5, 5, 4, 5, 6, 6, 7, 8, 7, 8, 9,
- 0, -11, -12, 12, 12, 13, 13, 14, 14, 15, 15, 14, 15, 6, 6, 7, 8, 7, 8, 9};
-
- for (size_t i = 0; i < arraysize(int32_constants); i++) {
- CheckTrimConstant(&T, T.jsgraph.Int32Constant(int32_constants[i]));
- CheckTrimConstant(&T, T.jsgraph.Float64Constant(int32_constants[i]));
- CheckTrimConstant(&T, T.jsgraph.Constant(int32_constants[i]));
- }
-
- Node* other_constants[] = {
- T.jsgraph.UndefinedConstant(), T.jsgraph.TheHoleConstant(),
- T.jsgraph.TrueConstant(), T.jsgraph.FalseConstant(),
- T.jsgraph.NullConstant(), T.jsgraph.ZeroConstant(),
- T.jsgraph.OneConstant(), T.jsgraph.NaNConstant(),
- T.jsgraph.Constant(21), T.jsgraph.Constant(22.2)};
-
- for (size_t i = 0; i < arraysize(other_constants); i++) {
- CheckTrimConstant(&T, other_constants[i]);
- }
-}
-
-
-TEST(CReducePhi1) {
- ControlReducerTester R;
-
- R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0]));
- R.ReducePhi(R.leaf[1], R.Phi(R.leaf[1]));
- R.ReducePhi(R.leaf[2], R.Phi(R.leaf[2]));
- R.ReducePhi(R.leaf[3], R.Phi(R.leaf[3]));
-}
-
-
-TEST(CReducePhi1_dead) {
- ControlReducerTester R;
-
- R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0], R.dead));
- R.ReducePhi(R.leaf[1], R.Phi(R.leaf[1], R.dead));
- R.ReducePhi(R.leaf[2], R.Phi(R.leaf[2], R.dead));
- R.ReducePhi(R.leaf[3], R.Phi(R.leaf[3], R.dead));
-
- R.ReducePhi(R.leaf[0], R.Phi(R.dead, R.leaf[0]));
- R.ReducePhi(R.leaf[1], R.Phi(R.dead, R.leaf[1]));
- R.ReducePhi(R.leaf[2], R.Phi(R.dead, R.leaf[2]));
- R.ReducePhi(R.leaf[3], R.Phi(R.dead, R.leaf[3]));
-}
-
-
-TEST(CReducePhi1_dead2) {
- ControlReducerTester R;
-
- R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0], R.dead, R.dead));
- R.ReducePhi(R.leaf[0], R.Phi(R.dead, R.leaf[0], R.dead));
- R.ReducePhi(R.leaf[0], R.Phi(R.dead, R.dead, R.leaf[0]));
-}
-
-
-TEST(CReducePhi2a) {
- ControlReducerTester R;
-
- for (size_t i = 0; i < kNumLeafs; i++) {
- Node* a = R.leaf[i];
- R.ReducePhi(a, R.Phi(a, a));
- }
-}
-
-
-TEST(CReducePhi2b) {
- ControlReducerTester R;
-
- for (size_t i = 0; i < kNumLeafs; i++) {
- Node* a = R.leaf[i];
- R.ReducePhi(a, R.Phi(R.self, a));
- R.ReducePhi(a, R.Phi(a, R.self));
- }
-}
-
-
-TEST(CReducePhi2c) {
- ControlReducerTester R;
-
- for (size_t i = 1; i < kNumLeafs; i++) {
- Node* a = R.leaf[i], *b = R.leaf[0];
- Node* phi1 = R.Phi(b, a);
- R.ReducePhi(phi1, phi1);
-
- Node* phi2 = R.Phi(a, b);
- R.ReducePhi(phi2, phi2);
- }
-}
-
-
-TEST(CReducePhi2_dead) {
- ControlReducerTester R;
-
- for (size_t i = 0; i < kNumLeafs; i++) {
- Node* a = R.leaf[i];
- R.ReducePhi(a, R.Phi(a, a, R.dead));
- R.ReducePhi(a, R.Phi(a, R.dead, a));
- R.ReducePhi(a, R.Phi(R.dead, a, a));
- }
-
- for (size_t i = 0; i < kNumLeafs; i++) {
- Node* a = R.leaf[i];
- R.ReducePhi(a, R.Phi(R.self, a));
- R.ReducePhi(a, R.Phi(a, R.self));
- R.ReducePhi(a, R.Phi(R.self, a, R.dead));
- R.ReducePhi(a, R.Phi(a, R.self, R.dead));
- }
-
- for (size_t i = 1; i < kNumLeafs; i++) {
- Node* a = R.leaf[i], *b = R.leaf[0];
- Node* phi1 = R.Phi(b, a, R.dead);
- R.ReducePhi(phi1, phi1);
-
- Node* phi2 = R.Phi(a, b, R.dead);
- R.ReducePhi(phi2, phi2);
- }
-}
-
-
-TEST(CReducePhi3) {
- ControlReducerTester R;
-
- for (size_t i = 0; i < kNumLeafs; i++) {
- Node* a = R.leaf[i];
- R.ReducePhi(a, R.Phi(a, a, a));
- }
-
- for (size_t i = 0; i < kNumLeafs; i++) {
- Node* a = R.leaf[i];
- R.ReducePhi(a, R.Phi(R.self, a, a));
- R.ReducePhi(a, R.Phi(a, R.self, a));
- R.ReducePhi(a, R.Phi(a, a, R.self));
- }
-
- for (size_t i = 1; i < kNumLeafs; i++) {
- Node* a = R.leaf[i], *b = R.leaf[0];
- Node* phi1 = R.Phi(b, a, a);
- R.ReducePhi(phi1, phi1);
-
- Node* phi2 = R.Phi(a, b, a);
- R.ReducePhi(phi2, phi2);
-
- Node* phi3 = R.Phi(a, a, b);
- R.ReducePhi(phi3, phi3);
- }
-}
-
-
-TEST(CReducePhi4) {
- ControlReducerTester R;
-
- for (size_t i = 0; i < kNumLeafs; i++) {
- Node* a = R.leaf[i];
- R.ReducePhi(a, R.Phi(a, a, a, a));
- }
-
- for (size_t i = 0; i < kNumLeafs; i++) {
- Node* a = R.leaf[i];
- R.ReducePhi(a, R.Phi(R.self, a, a, a));
- R.ReducePhi(a, R.Phi(a, R.self, a, a));
- R.ReducePhi(a, R.Phi(a, a, R.self, a));
- R.ReducePhi(a, R.Phi(a, a, a, R.self));
-
- R.ReducePhi(a, R.Phi(R.self, R.self, a, a));
- R.ReducePhi(a, R.Phi(a, R.self, R.self, a));
- R.ReducePhi(a, R.Phi(a, a, R.self, R.self));
- R.ReducePhi(a, R.Phi(R.self, a, a, R.self));
- }
-
- for (size_t i = 1; i < kNumLeafs; i++) {
- Node* a = R.leaf[i], *b = R.leaf[0];
- Node* phi1 = R.Phi(b, a, a, a);
- R.ReducePhi(phi1, phi1);
-
- Node* phi2 = R.Phi(a, b, a, a);
- R.ReducePhi(phi2, phi2);
-
- Node* phi3 = R.Phi(a, a, b, a);
- R.ReducePhi(phi3, phi3);
-
- Node* phi4 = R.Phi(a, a, a, b);
- R.ReducePhi(phi4, phi4);
- }
-}
-
-
-TEST(CReducePhi_iterative1) {
- ControlReducerTester R;
-
- R.ReducePhiIterative(R.leaf[0], R.Phi(R.leaf[0], R.Phi(R.leaf[0])));
- R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0]), R.leaf[0]));
-}
-
-
-TEST(CReducePhi_iterative2) {
- ControlReducerTester R;
-
- R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0]), R.Phi(R.leaf[0])));
-}
-
-
-TEST(CReducePhi_iterative3) {
- ControlReducerTester R;
-
- R.ReducePhiIterative(R.leaf[0],
- R.Phi(R.leaf[0], R.Phi(R.leaf[0], R.leaf[0])));
- R.ReducePhiIterative(R.leaf[0],
- R.Phi(R.Phi(R.leaf[0], R.leaf[0]), R.leaf[0]));
-}
-
-
-TEST(CReducePhi_iterative4) {
- ControlReducerTester R;
-
- R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0], R.leaf[0]),
- R.Phi(R.leaf[0], R.leaf[0])));
-
- Node* p1 = R.Phi(R.leaf[0], R.leaf[0]);
- R.ReducePhiIterative(R.leaf[0], R.Phi(p1, p1));
-
- Node* p2 = R.Phi(R.leaf[0], R.leaf[0], R.leaf[0]);
- R.ReducePhiIterative(R.leaf[0], R.Phi(p2, p2, p2));
-
- Node* p3 = R.Phi(R.leaf[0], R.leaf[0], R.leaf[0]);
- R.ReducePhiIterative(R.leaf[0], R.Phi(p3, p3, R.leaf[0]));
-}
-
-
-TEST(CReducePhi_iterative_self1) {
- ControlReducerTester R;
-
- R.ReducePhiIterative(R.leaf[0], R.Phi(R.leaf[0], R.Phi(R.leaf[0], R.self)));
- R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0], R.self), R.leaf[0]));
-}
-
-
-TEST(CReducePhi_iterative_self2) {
- ControlReducerTester R;
-
- R.ReducePhiIterative(
- R.leaf[0], R.Phi(R.Phi(R.leaf[0], R.self), R.Phi(R.leaf[0], R.self)));
- R.ReducePhiIterative(
- R.leaf[0], R.Phi(R.Phi(R.self, R.leaf[0]), R.Phi(R.self, R.leaf[0])));
-
- Node* p1 = R.Phi(R.leaf[0], R.self);
- R.ReducePhiIterative(R.leaf[0], R.Phi(p1, p1));
-
- Node* p2 = R.Phi(R.self, R.leaf[0]);
- R.ReducePhiIterative(R.leaf[0], R.Phi(p2, p2));
-}
-
-
-TEST(EReducePhi1) {
- ControlReducerTester R;
-
- R.ReducePhi(R.leaf[0], R.EffectPhi(R.leaf[0]));
- R.ReducePhi(R.leaf[1], R.EffectPhi(R.leaf[1]));
- R.ReducePhi(R.leaf[2], R.EffectPhi(R.leaf[2]));
- R.ReducePhi(R.leaf[3], R.EffectPhi(R.leaf[3]));
-}
-
-
-TEST(EReducePhi1_dead) {
- ControlReducerTester R;
-
- R.ReducePhi(R.leaf[0], R.EffectPhi(R.leaf[0], R.dead));
- R.ReducePhi(R.leaf[1], R.EffectPhi(R.leaf[1], R.dead));
- R.ReducePhi(R.leaf[2], R.EffectPhi(R.leaf[2], R.dead));
- R.ReducePhi(R.leaf[3], R.EffectPhi(R.leaf[3], R.dead));
-
- R.ReducePhi(R.leaf[0], R.EffectPhi(R.dead, R.leaf[0]));
- R.ReducePhi(R.leaf[1], R.EffectPhi(R.dead, R.leaf[1]));
- R.ReducePhi(R.leaf[2], R.EffectPhi(R.dead, R.leaf[2]));
- R.ReducePhi(R.leaf[3], R.EffectPhi(R.dead, R.leaf[3]));
-}
-
-
-TEST(EReducePhi1_dead2) {
- ControlReducerTester R;
-
- R.ReducePhi(R.leaf[0], R.EffectPhi(R.leaf[0], R.dead, R.dead));
- R.ReducePhi(R.leaf[0], R.EffectPhi(R.dead, R.leaf[0], R.dead));
- R.ReducePhi(R.leaf[0], R.EffectPhi(R.dead, R.dead, R.leaf[0]));
-}
-
-
-TEST(CMergeReduce_simple1) {
- ControlReducerTester R;
-
- Node* merge = R.graph.NewNode(R.common.Merge(1), R.start);
- R.ReduceMerge(R.start, merge);
-}
-
-
-TEST(CMergeReduce_simple2) {
- ControlReducerTester R;
-
- Node* merge1 = R.graph.NewNode(R.common.Merge(1), R.start);
- Node* merge2 = R.graph.NewNode(R.common.Merge(1), merge1);
- R.ReduceMerge(merge1, merge2);
- R.ReduceMergeIterative(R.start, merge2);
-}
-
-
-TEST(CMergeReduce_none1) {
- ControlReducerTester R;
-
- Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, R.start);
- R.ReduceMerge(merge, merge);
-}
-
-
-TEST(CMergeReduce_none2) {
- ControlReducerTester R;
-
- Node* t = R.graph.NewNode(R.common.IfTrue(), R.start);
- Node* f = R.graph.NewNode(R.common.IfFalse(), R.start);
- Node* merge = R.graph.NewNode(R.common.Merge(2), t, f);
- R.ReduceMerge(merge, merge);
-}
-
-
-TEST(CMergeReduce_self3) {
- ControlReducerTester R;
-
- Node* merge =
- R.SetSelfReferences(R.graph.NewNode(R.common.Merge(2), R.start, R.self));
- R.ReduceMerge(merge, merge);
-}
-
-
-TEST(CMergeReduce_dead1) {
- ControlReducerTester R;
-
- Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, R.dead);
- R.ReduceMerge(R.start, merge);
-}
-
-
-TEST(CMergeReduce_dead2) {
- ControlReducerTester R;
-
- Node* merge1 = R.graph.NewNode(R.common.Merge(1), R.start);
- Node* merge2 = R.graph.NewNode(R.common.Merge(2), merge1, R.dead);
- R.ReduceMerge(merge1, merge2);
- R.ReduceMergeIterative(R.start, merge2);
-}
-
-
-TEST(CMergeReduce_dead_rm1a) {
- ControlReducerTester R;
-
- for (int i = 0; i < 3; i++) {
- Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start);
- merge->ReplaceInput(i, R.dead);
- R.ReduceMerge(merge, merge);
- CheckMerge(merge, R.start, R.start);
- }
-}
-
-
-TEST(CMergeReduce_dead_rm1b) {
- ControlReducerTester R;
-
- Node* t = R.graph.NewNode(R.common.IfTrue(), R.start);
- Node* f = R.graph.NewNode(R.common.IfFalse(), R.start);
- for (int i = 0; i < 2; i++) {
- Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead);
- for (int j = i + 1; j < 3; j++) {
- merge->ReplaceInput(i, t);
- merge->ReplaceInput(j, f);
- R.ReduceMerge(merge, merge);
- CheckMerge(merge, t, f);
- }
- }
-}
-
-
-TEST(CMergeReduce_dead_rm2) {
- ControlReducerTester R;
-
- for (int i = 0; i < 3; i++) {
- Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead);
- merge->ReplaceInput(i, R.start);
- R.ReduceMerge(R.start, merge);
- }
-}
-
-
-TEST(CLoopReduce_dead_rm1) {
- ControlReducerTester R;
-
- for (int i = 0; i < 3; i++) {
- Node* loop = R.graph.NewNode(R.common.Loop(3), R.dead, R.start, R.start);
- R.ReduceMerge(loop, loop);
- CheckLoop(loop, R.start, R.start);
- }
-}
-
-
-TEST(CMergeReduce_edit_phi1) {
- ControlReducerTester R;
-
- for (int i = 0; i < 3; i++) {
- Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start);
- merge->ReplaceInput(i, R.dead);
- Node* phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 3), R.leaf[0],
- R.leaf[1], R.leaf[2], merge);
- R.ReduceMerge(merge, merge);
- CHECK_EQ(IrOpcode::kPhi, phi->opcode());
- CHECK_EQ(2, phi->op()->ValueInputCount());
- CHECK_EQ(3, phi->InputCount());
- CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0));
- CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1));
- CHECK_EQ(merge, phi->InputAt(2));
- }
-}
-
-
-TEST(CMergeReduce_edit_effect_phi1) {
- ControlReducerTester R;
-
- for (int i = 0; i < 3; i++) {
- Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start);
- merge->ReplaceInput(i, R.dead);
- Node* phi = R.graph.NewNode(R.common.EffectPhi(3), R.leaf[0], R.leaf[1],
- R.leaf[2], merge);
- R.ReduceMerge(merge, merge);
- CHECK_EQ(IrOpcode::kEffectPhi, phi->opcode());
- CHECK_EQ(0, phi->op()->ValueInputCount());
- CHECK_EQ(2, phi->op()->EffectInputCount());
- CHECK_EQ(3, phi->InputCount());
- CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0));
- CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1));
- CHECK_EQ(merge, phi->InputAt(2));
- }
-}
-
-
-static const int kSelectorSize = 4;
-
-// Helper to select K of N nodes according to a mask, useful for the test below.
-struct Selector {
- int mask;
- int count;
- explicit Selector(int m) {
- mask = m;
- count = v8::base::bits::CountPopulation32(m);
- }
- bool is_selected(int i) { return (mask & (1 << i)) != 0; }
- void CheckNode(Node* node, IrOpcode::Value opcode, Node** inputs,
- Node* control) {
- CHECK_EQ(opcode, node->opcode());
- CHECK_EQ(count + (control != NULL ? 1 : 0), node->InputCount());
- int index = 0;
- for (int i = 0; i < kSelectorSize; i++) {
- if (mask & (1 << i)) {
- CHECK_EQ(inputs[i], node->InputAt(index++));
- }
- }
- CHECK_EQ(count, index);
- if (control != NULL) CHECK_EQ(control, node->InputAt(index++));
- }
- int single_index() {
- CHECK_EQ(1, count);
- return WhichPowerOf2(mask);
- }
-};
-
-
-TEST(CMergeReduce_exhaustive_4) {
- ControlReducerTester R;
- Node* controls[] = {
- R.graph.NewNode(R.common.Start(1)), R.graph.NewNode(R.common.Start(2)),
- R.graph.NewNode(R.common.Start(3)), R.graph.NewNode(R.common.Start(4))};
- Node* values[] = {R.jsgraph.Int32Constant(11), R.jsgraph.Int32Constant(22),
- R.jsgraph.Int32Constant(33), R.jsgraph.Int32Constant(44)};
- Node* effects[] = {
- R.jsgraph.Float64Constant(123.4), R.jsgraph.Float64Constant(223.4),
- R.jsgraph.Float64Constant(323.4), R.jsgraph.Float64Constant(423.4)};
-
- for (int mask = 0; mask < (1 << (kSelectorSize - 1)); mask++) {
- // Reduce a single merge with a given mask.
- Node* merge = R.graph.NewNode(R.common.Merge(4), controls[0], controls[1],
- controls[2], controls[3]);
- Node* phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 4), values[0],
- values[1], values[2], values[3], merge);
- Node* ephi = R.graph.NewNode(R.common.EffectPhi(4), effects[0], effects[1],
- effects[2], effects[3], merge);
-
- Node* phi_use =
- R.graph.NewNode(R.common.Phi(kMachAnyTagged, 1), phi, R.start);
- Node* ephi_use = R.graph.NewNode(R.common.EffectPhi(1), ephi, R.start);
-
- Selector selector(mask);
-
- for (int i = 0; i < kSelectorSize; i++) { // set up dead merge inputs.
- if (!selector.is_selected(i)) merge->ReplaceInput(i, R.dead);
- }
-
- Node* result =
- ControlReducer::ReduceMergeForTesting(&R.jsgraph, &R.common, merge);
-
- int count = selector.count;
- if (count == 0) {
- // result should be dead.
- CHECK_EQ(IrOpcode::kDead, result->opcode());
- } else if (count == 1) {
- // merge should be replaced with one of the controls.
- CHECK_EQ(controls[selector.single_index()], result);
- // Phis should have been directly replaced.
- CHECK_EQ(values[selector.single_index()], phi_use->InputAt(0));
- CHECK_EQ(effects[selector.single_index()], ephi_use->InputAt(0));
- } else {
- // Otherwise, nodes should be edited in place.
- CHECK_EQ(merge, result);
- selector.CheckNode(merge, IrOpcode::kMerge, controls, NULL);
- selector.CheckNode(phi, IrOpcode::kPhi, values, merge);
- selector.CheckNode(ephi, IrOpcode::kEffectPhi, effects, merge);
- CHECK_EQ(phi, phi_use->InputAt(0));
- CHECK_EQ(ephi, ephi_use->InputAt(0));
- CHECK_EQ(count, phi->op()->ValueInputCount());
- CHECK_EQ(count + 1, phi->InputCount());
- CHECK_EQ(count, ephi->op()->EffectInputCount());
- CHECK_EQ(count + 1, ephi->InputCount());
- }
- }
-}
-
-
-TEST(CMergeReduce_edit_many_phis1) {
- ControlReducerTester R;
-
- const int kPhiCount = 10;
- Node* phis[kPhiCount];
-
- for (int i = 0; i < 3; i++) {
- Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start);
- merge->ReplaceInput(i, R.dead);
- for (int j = 0; j < kPhiCount; j++) {
- phis[j] = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 3), R.leaf[0],
- R.leaf[1], R.leaf[2], merge);
- }
- R.ReduceMerge(merge, merge);
- for (int j = 0; j < kPhiCount; j++) {
- Node* phi = phis[j];
- CHECK_EQ(IrOpcode::kPhi, phi->opcode());
- CHECK_EQ(2, phi->op()->ValueInputCount());
- CHECK_EQ(3, phi->InputCount());
- CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0));
- CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1));
- CHECK_EQ(merge, phi->InputAt(2));
- }
- }
-}
-
-
-TEST(CMergeReduce_simple_chain1) {
- ControlReducerTester R;
- for (int i = 0; i < 5; i++) {
- Node* merge = R.graph.NewNode(R.common.Merge(1), R.start);
- for (int j = 0; j < i; j++) {
- merge = R.graph.NewNode(R.common.Merge(1), merge);
- }
- R.ReduceMergeIterative(R.start, merge);
- }
-}
-
-
-TEST(CMergeReduce_dead_chain1) {
- ControlReducerTester R;
- for (int i = 0; i < 5; i++) {
- Node* merge = R.graph.NewNode(R.common.Merge(1), R.dead);
- for (int j = 0; j < i; j++) {
- merge = R.graph.NewNode(R.common.Merge(1), merge);
- }
- Node* end = R.graph.NewNode(R.common.End(), merge);
- R.graph.SetEnd(end);
- R.ReduceGraph();
- CHECK(merge->IsDead());
- CHECK_EQ(NULL, end->InputAt(0)); // end dies.
- }
-}
-
-
-TEST(CMergeReduce_dead_chain2) {
- ControlReducerTester R;
- for (int i = 0; i < 5; i++) {
- Node* merge = R.graph.NewNode(R.common.Merge(1), R.start);
- for (int j = 0; j < i; j++) {
- merge = R.graph.NewNode(R.common.Merge(2), merge, R.dead);
- }
- R.ReduceMergeIterative(R.start, merge);
- }
-}
-
-
-struct Branch {
- Node* branch;
- Node* if_true;
- Node* if_false;
-
- Branch(ControlReducerTester& R, Node* cond, Node* control = NULL) {
- if (control == NULL) control = R.start;
- branch = R.graph.NewNode(R.common.Branch(), cond, control);
- if_true = R.graph.NewNode(R.common.IfTrue(), branch);
- if_false = R.graph.NewNode(R.common.IfFalse(), branch);
- }
-};
-
-
-// TODO(titzer): use the diamonds from src/compiler/diamond.h here.
-struct Diamond {
- Node* branch;
- Node* if_true;
- Node* if_false;
- Node* merge;
- Node* phi;
-
- Diamond(ControlReducerTester& R, Node* cond) {
- branch = R.graph.NewNode(R.common.Branch(), cond, R.start);
- if_true = R.graph.NewNode(R.common.IfTrue(), branch);
- if_false = R.graph.NewNode(R.common.IfFalse(), branch);
- merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false);
- phi = NULL;
- }
-
- Diamond(ControlReducerTester& R, Node* cond, Node* tv, Node* fv) {
- branch = R.graph.NewNode(R.common.Branch(), cond, R.start);
- if_true = R.graph.NewNode(R.common.IfTrue(), branch);
- if_false = R.graph.NewNode(R.common.IfFalse(), branch);
- merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false);
- phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 2), tv, fv, merge);
- }
-
- void chain(Diamond& that) { branch->ReplaceInput(1, that.merge); }
-
- // Nest {this} into either the if_true or if_false branch of {that}.
- void nest(Diamond& that, bool if_true) {
- if (if_true) {
- branch->ReplaceInput(1, that.if_true);
- that.merge->ReplaceInput(0, merge);
- } else {
- branch->ReplaceInput(1, that.if_false);
- that.merge->ReplaceInput(1, merge);
- }
- }
-};
-
-
-struct While {
- Node* branch;
- Node* if_true;
- Node* exit;
- Node* loop;
-
- While(ControlReducerTester& R, Node* cond) {
- loop = R.graph.NewNode(R.common.Loop(2), R.start, R.start);
- branch = R.graph.NewNode(R.common.Branch(), cond, loop);
- if_true = R.graph.NewNode(R.common.IfTrue(), branch);
- exit = R.graph.NewNode(R.common.IfFalse(), branch);
- loop->ReplaceInput(1, if_true);
- }
-
- void chain(Node* control) { loop->ReplaceInput(0, control); }
-};
-
-
-TEST(CBranchReduce_none1) {
- ControlReducerTester R;
- Diamond d(R, R.p0);
- R.ReduceBranch(d.branch, d.branch);
-}
-
-
-TEST(CBranchReduce_none2) {
- ControlReducerTester R;
- Diamond d1(R, R.p0);
- Diamond d2(R, R.p0);
- d2.chain(d1);
- R.ReduceBranch(d2.branch, d2.branch);
-}
-
-
-TEST(CBranchReduce_true) {
- ControlReducerTester R;
- Node* true_values[] = {
- R.one, R.jsgraph.Int32Constant(2),
- R.jsgraph.Int32Constant(0x7fffffff), R.jsgraph.Constant(1.0),
- R.jsgraph.Constant(22.1), R.jsgraph.TrueConstant()};
-
- for (size_t i = 0; i < arraysize(true_values); i++) {
- Diamond d(R, true_values[i]);
- Node* true_use = R.graph.NewNode(R.common.Merge(1), d.if_true);
- Node* false_use = R.graph.NewNode(R.common.Merge(1), d.if_false);
- R.ReduceBranch(R.start, d.branch);
- CHECK_EQ(R.start, true_use->InputAt(0));
- CHECK_EQ(IrOpcode::kDead, false_use->InputAt(0)->opcode());
- CHECK(d.if_true->IsDead()); // replaced
- CHECK(d.if_false->IsDead()); // replaced
- }
-}
-
-
-TEST(CBranchReduce_false) {
- ControlReducerTester R;
- Node* false_values[] = {R.zero, R.jsgraph.Constant(0.0),
- R.jsgraph.Constant(-0.0), R.jsgraph.FalseConstant()};
-
- for (size_t i = 0; i < arraysize(false_values); i++) {
- Diamond d(R, false_values[i]);
- Node* true_use = R.graph.NewNode(R.common.Merge(1), d.if_true);
- Node* false_use = R.graph.NewNode(R.common.Merge(1), d.if_false);
- R.ReduceBranch(R.start, d.branch);
- CHECK_EQ(R.start, false_use->InputAt(0));
- CHECK_EQ(IrOpcode::kDead, true_use->InputAt(0)->opcode());
- CHECK(d.if_true->IsDead()); // replaced
- CHECK(d.if_false->IsDead()); // replaced
- }
-}
-
-
-TEST(CDiamondReduce_true) {
- ControlReducerTester R;
- Diamond d1(R, R.one);
- R.ReduceMergeIterative(R.start, d1.merge);
-}
-
-
-TEST(CDiamondReduce_false) {
- ControlReducerTester R;
- Diamond d2(R, R.zero);
- R.ReduceMergeIterative(R.start, d2.merge);
-}
-
-
-TEST(CChainedDiamondsReduce_true_false) {
- ControlReducerTester R;
- Diamond d1(R, R.one);
- Diamond d2(R, R.zero);
- d2.chain(d1);
-
- R.ReduceMergeIterative(R.start, d2.merge);
-}
-
-
-TEST(CChainedDiamondsReduce_x_false) {
- ControlReducerTester R;
- Diamond d1(R, R.p0);
- Diamond d2(R, R.zero);
- d2.chain(d1);
-
- R.ReduceMergeIterative(d1.merge, d2.merge);
-}
-
-
-TEST(CChainedDiamondsReduce_false_x) {
- ControlReducerTester R;
- Diamond d1(R, R.zero);
- Diamond d2(R, R.p0);
- d2.chain(d1);
-
- R.ReduceMergeIterative(d2.merge, d2.merge);
- CheckInputs(d2.branch, R.p0, R.start);
-}
-
-
-TEST(CChainedDiamondsReduce_phi1) {
- ControlReducerTester R;
- Diamond d1(R, R.zero, R.one, R.zero); // foldable branch, phi.
- Diamond d2(R, d1.phi);
- d2.chain(d1);
-
- R.ReduceMergeIterative(R.start, d2.merge);
-}
-
-
-TEST(CChainedDiamondsReduce_phi2) {
- ControlReducerTester R;
- Diamond d1(R, R.p0, R.one, R.one); // redundant phi.
- Diamond d2(R, d1.phi);
- d2.chain(d1);
-
- R.ReduceMergeIterative(d1.merge, d2.merge);
-}
-
-
-TEST(CNestedDiamondsReduce_true_true_false) {
- ControlReducerTester R;
- Diamond d1(R, R.one);
- Diamond d2(R, R.zero);
- d2.nest(d1, true);
-
- R.ReduceMergeIterative(R.start, d1.merge);
-}
-
-
-TEST(CNestedDiamondsReduce_false_true_false) {
- ControlReducerTester R;
- Diamond d1(R, R.one);
- Diamond d2(R, R.zero);
- d2.nest(d1, false);
-
- R.ReduceMergeIterative(R.start, d1.merge);
-}
-
-
-TEST(CNestedDiamonds_xyz) {
- ControlReducerTester R;
-
- for (int a = 0; a < 2; a++) {
- for (int b = 0; b < 2; b++) {
- for (int c = 0; c < 2; c++) {
- Diamond d1(R, R.jsgraph.Int32Constant(a));
- Diamond d2(R, R.jsgraph.Int32Constant(b));
- d2.nest(d1, c);
-
- R.ReduceMergeIterative(R.start, d1.merge);
- }
- }
- }
-}
-
-
-TEST(CDeadLoop1) {
- ControlReducerTester R;
-
- Node* loop = R.graph.NewNode(R.common.Loop(1), R.start);
- Branch b(R, R.p0, loop);
- loop->ReplaceInput(0, b.if_true); // loop is not connected to start.
- Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, b.if_false);
- R.ReduceMergeIterative(R.start, merge);
- CHECK(b.if_true->IsDead());
- CHECK(b.if_false->IsDead());
-}
-
-
-TEST(CDeadLoop2) {
- ControlReducerTester R;
-
- While w(R, R.p0);
- Diamond d(R, R.zero);
- // if (0) { while (p0) ; } else { }
- w.branch->ReplaceInput(1, d.if_true);
- d.merge->ReplaceInput(0, w.exit);
-
- R.ReduceMergeIterative(R.start, d.merge);
- CHECK(d.if_true->IsDead());
- CHECK(d.if_false->IsDead());
-}
-
-
-TEST(CNonTermLoop1) {
- ControlReducerTester R;
- Node* loop =
- R.SetSelfReferences(R.graph.NewNode(R.common.Loop(2), R.start, R.self));
- R.ReduceGraph();
- Node* end = R.graph.end();
- CheckLoop(loop, R.start, loop);
- Node* merge = end->InputAt(0);
- CheckMerge(merge, R.start, loop);
-}
-
-
-TEST(CNonTermLoop2) {
- ControlReducerTester R;
- Diamond d(R, R.p0);
- Node* loop = R.SetSelfReferences(
- R.graph.NewNode(R.common.Loop(2), d.if_false, R.self));
- d.merge->ReplaceInput(1, R.dead);
- Node* end = R.graph.end();
- end->ReplaceInput(0, d.merge);
- R.ReduceGraph();
- CHECK_EQ(end, R.graph.end());
- CheckLoop(loop, d.if_false, loop);
- Node* merge = end->InputAt(0);
- CheckMerge(merge, d.if_true, loop);
-}
-
-
-TEST(NonTermLoop3) {
- ControlReducerTester R;
- Node* loop = R.graph.NewNode(R.common.Loop(2), R.start, R.start);
- Branch b(R, R.one, loop);
- loop->ReplaceInput(1, b.if_true);
- Node* end = R.graph.end();
- end->ReplaceInput(0, b.if_false);
-
- R.ReduceGraph();
-
- CHECK_EQ(end, R.graph.end());
- CheckInputs(end, loop);
- CheckInputs(loop, R.start, loop);
-}
-
-
-TEST(CNonTermLoop_terminate1) {
- ControlReducerTester R;
- Node* loop = R.graph.NewNode(R.common.Loop(2), R.start, R.start);
- Node* effect = R.SetSelfReferences(
- R.graph.NewNode(R.common.EffectPhi(2), R.start, R.self, loop));
- Branch b(R, R.one, loop);
- loop->ReplaceInput(1, b.if_true);
- Node* end = R.graph.end();
- end->ReplaceInput(0, b.if_false);
-
- R.ReduceGraph();
-
- CHECK_EQ(end, R.graph.end());
- CheckLoop(loop, R.start, loop);
- Node* terminate = end->InputAt(0);
- CHECK_EQ(IrOpcode::kTerminate, terminate->opcode());
- CHECK_EQ(2, terminate->InputCount());
- CHECK_EQ(1, terminate->op()->EffectInputCount());
- CHECK_EQ(1, terminate->op()->ControlInputCount());
- CheckInputs(terminate, effect, loop);
-}
-
-
-TEST(CNonTermLoop_terminate2) {
- ControlReducerTester R;
- Node* loop = R.graph.NewNode(R.common.Loop(2), R.start, R.start);
- Node* effect1 = R.SetSelfReferences(
- R.graph.NewNode(R.common.EffectPhi(2), R.start, R.self, loop));
- Node* effect2 = R.SetSelfReferences(
- R.graph.NewNode(R.common.EffectPhi(2), R.start, R.self, loop));
- Branch b(R, R.one, loop);
- loop->ReplaceInput(1, b.if_true);
- Node* end = R.graph.end();
- end->ReplaceInput(0, b.if_false);
-
- R.ReduceGraph();
-
- CheckLoop(loop, R.start, loop);
- CHECK_EQ(end, R.graph.end());
- Node* terminate = end->InputAt(0);
- CHECK_EQ(IrOpcode::kTerminate, terminate->opcode());
- CHECK_EQ(3, terminate->InputCount());
- CHECK_EQ(2, terminate->op()->EffectInputCount());
- CHECK_EQ(1, terminate->op()->ControlInputCount());
- Node* e0 = terminate->InputAt(0);
- Node* e1 = terminate->InputAt(1);
- CHECK(e0 == effect1 || e1 == effect1);
- CHECK(e0 == effect2 || e1 == effect2);
- CHECK_EQ(loop, terminate->InputAt(2));
-}
-
-
-TEST(CNonTermLoop_terminate_m1) {
- ControlReducerTester R;
- Node* loop =
- R.SetSelfReferences(R.graph.NewNode(R.common.Loop(2), R.start, R.self));
- Node* effect = R.SetSelfReferences(
- R.graph.NewNode(R.common.EffectPhi(2), R.start, R.self, loop));
- R.ReduceGraph();
- Node* end = R.graph.end();
- CHECK_EQ(R.start, loop->InputAt(0));
- CHECK_EQ(loop, loop->InputAt(1));
- Node* merge = end->InputAt(0);
- CHECK_EQ(IrOpcode::kMerge, merge->opcode());
- CHECK_EQ(2, merge->InputCount());
- CHECK_EQ(2, merge->op()->ControlInputCount());
- CHECK_EQ(R.start, merge->InputAt(0));
-
- Node* terminate = merge->InputAt(1);
- CHECK_EQ(IrOpcode::kTerminate, terminate->opcode());
- CHECK_EQ(2, terminate->InputCount());
- CHECK_EQ(1, terminate->op()->EffectInputCount());
- CHECK_EQ(1, terminate->op()->ControlInputCount());
- CHECK_EQ(effect, terminate->InputAt(0));
- CHECK_EQ(loop, terminate->InputAt(1));
-}
-
-
-TEST(CNonTermLoop_big1) {
- ControlReducerTester R;
- Branch b1(R, R.p0);
- Node* rt = R.graph.NewNode(R.common.Return(), R.one, R.start, b1.if_true);
-
- Branch b2(R, R.p0, b1.if_false);
- Node* rf = R.graph.NewNode(R.common.Return(), R.zero, R.start, b2.if_true);
- Node* loop = R.SetSelfReferences(
- R.graph.NewNode(R.common.Loop(2), b2.if_false, R.self));
- Node* merge = R.graph.NewNode(R.common.Merge(2), rt, rf);
- R.end->ReplaceInput(0, merge);
-
- R.ReduceGraph();
-
- CheckInputs(R.end, merge);
- CheckInputs(merge, rt, rf, loop);
- CheckInputs(loop, b2.if_false, loop);
-}
-
-
-TEST(CNonTermLoop_big2) {
- ControlReducerTester R;
- Branch b1(R, R.p0);
- Node* rt = R.graph.NewNode(R.common.Return(), R.one, R.start, b1.if_true);
-
- Branch b2(R, R.zero, b1.if_false);
- Node* rf = R.graph.NewNode(R.common.Return(), R.zero, R.start, b2.if_true);
- Node* loop = R.SetSelfReferences(
- R.graph.NewNode(R.common.Loop(2), b2.if_false, R.self));
- Node* merge = R.graph.NewNode(R.common.Merge(2), rt, rf);
- R.end->ReplaceInput(0, merge);
-
- R.ReduceGraph();
-
- Node* new_merge = R.end->InputAt(0); // old merge was reduced.
- CHECK_NE(merge, new_merge);
- CheckInputs(new_merge, rt, loop);
- CheckInputs(loop, b1.if_false, loop);
- CHECK(merge->IsDead());
- CHECK(rf->IsDead());
- CHECK(b2.if_true->IsDead());
-}
-
-
-TEST(Return1) {
- ControlReducerTester R;
- Node* ret = R.Return(R.one, R.start, R.start);
- R.ReduceGraph();
- CheckInputs(R.graph.end(), ret);
- CheckInputs(ret, R.one, R.start, R.start);
-}
-
-
-TEST(Return2) {
- ControlReducerTester R;
- Diamond d(R, R.one);
- Node* ret = R.Return(R.half, R.start, d.merge);
- R.ReduceGraph();
- CHECK(d.branch->IsDead());
- CHECK(d.if_true->IsDead());
- CHECK(d.if_false->IsDead());
- CHECK(d.merge->IsDead());
-
- CheckInputs(R.graph.end(), ret);
- CheckInputs(ret, R.half, R.start, R.start);
-}
-
-
-TEST(Return_true1) {
- ControlReducerTester R;
- Diamond d(R, R.one, R.half, R.zero);
- Node* ret = R.Return(d.phi, R.start, d.merge);
- R.ReduceGraph();
- CHECK(d.branch->IsDead());
- CHECK(d.if_true->IsDead());
- CHECK(d.if_false->IsDead());
- CHECK(d.merge->IsDead());
- CHECK(d.phi->IsDead());
-
- CheckInputs(R.graph.end(), ret);
- CheckInputs(ret, R.half, R.start, R.start);
-}
-
-
-TEST(Return_false1) {
- ControlReducerTester R;
- Diamond d(R, R.zero, R.one, R.half);
- Node* ret = R.Return(d.phi, R.start, d.merge);
- R.ReduceGraph();
- CHECK(d.branch->IsDead());
- CHECK(d.if_true->IsDead());
- CHECK(d.if_false->IsDead());
- CHECK(d.merge->IsDead());
- CHECK(d.phi->IsDead());
-
- CheckInputs(R.graph.end(), ret);
- CheckInputs(ret, R.half, R.start, R.start);
-}
-
-
-void CheckDeadDiamond(Diamond& d) {
- CHECK(d.branch->IsDead());
- CHECK(d.if_true->IsDead());
- CHECK(d.if_false->IsDead());
- CHECK(d.merge->IsDead());
- if (d.phi != NULL) CHECK(d.phi->IsDead());
-}
-
-
-void CheckLiveDiamond(Diamond& d, bool live_phi = true) {
- CheckInputs(d.merge, d.if_true, d.if_false);
- CheckInputs(d.if_true, d.branch);
- CheckInputs(d.if_false, d.branch);
- if (d.phi != NULL) {
- if (live_phi) {
- CHECK_EQ(3, d.phi->InputCount());
- CHECK_EQ(d.merge, d.phi->InputAt(2));
- } else {
- CHECK(d.phi->IsDead());
- }
- }
-}
-
-
-TEST(Return_effect1) {
- ControlReducerTester R;
- Diamond d(R, R.one);
- Node* e1 = R.jsgraph.Float64Constant(-100.1);
- Node* e2 = R.jsgraph.Float64Constant(+100.1);
- Node* effect = R.graph.NewNode(R.common.EffectPhi(2), e1, e2, d.merge);
- Node* ret = R.Return(R.p0, effect, d.merge);
- R.ReduceGraph();
- CheckDeadDiamond(d);
- CHECK(effect->IsDead());
-
- CheckInputs(R.graph.end(), ret);
- CheckInputs(ret, R.p0, e1, R.start);
-}
-
-
-TEST(Return_nested_diamonds1) {
- ControlReducerTester R;
- Diamond d1(R, R.p0, R.one, R.zero);
- Diamond d2(R, R.p0);
- Diamond d3(R, R.p0);
-
- d2.nest(d1, true);
- d3.nest(d1, false);
-
- Node* ret = R.Return(d1.phi, R.start, d1.merge);
-
- R.ReduceGraph(); // nothing should happen.
-
- CheckInputs(ret, d1.phi, R.start, d1.merge);
- CheckInputs(d1.phi, R.one, R.zero, d1.merge);
- CheckInputs(d1.merge, d2.merge, d3.merge);
- CheckLiveDiamond(d2);
- CheckLiveDiamond(d3);
-}
-
-
-TEST(Return_nested_diamonds_true1) {
- ControlReducerTester R;
- Diamond d1(R, R.one, R.one, R.zero);
- Diamond d2(R, R.p0);
- Diamond d3(R, R.p0);
-
- d2.nest(d1, true);
- d3.nest(d1, false);
-
- Node* ret = R.Return(d1.phi, R.start, d1.merge);
-
- R.ReduceGraph(); // d1 gets folded true.
-
- CheckInputs(ret, R.one, R.start, d2.merge);
- CheckInputs(d2.branch, R.p0, R.start);
- CheckDeadDiamond(d1);
- CheckLiveDiamond(d2);
- CheckDeadDiamond(d3);
-}
-
-
-TEST(Return_nested_diamonds_false1) {
- ControlReducerTester R;
- Diamond d1(R, R.zero, R.one, R.zero);
- Diamond d2(R, R.p0);
- Diamond d3(R, R.p0);
-
- d2.nest(d1, true);
- d3.nest(d1, false);
-
- Node* ret = R.Return(d1.phi, R.start, d1.merge);
-
- R.ReduceGraph(); // d1 gets folded false.
-
- CheckInputs(ret, R.zero, R.start, d3.merge);
- CheckInputs(d3.branch, R.p0, R.start);
- CheckDeadDiamond(d1);
- CheckDeadDiamond(d2);
- CheckLiveDiamond(d3);
-}
-
-
-TEST(Return_nested_diamonds_true_true1) {
- ControlReducerTester R;
- Diamond d1(R, R.one, R.one, R.zero);
- Diamond d2(R, R.one);
- Diamond d3(R, R.p0);
-
- d2.nest(d1, true);
- d3.nest(d1, false);
-
- Node* ret = R.Return(d1.phi, R.start, d1.merge);
-
- R.ReduceGraph(); // d1 and d2 both get folded true.
-
- CheckInputs(ret, R.one, R.start, R.start);
- CheckDeadDiamond(d1);
- CheckDeadDiamond(d2);
- CheckDeadDiamond(d3);
-}
-
-
-TEST(Return_nested_diamonds_true_false1) {
- ControlReducerTester R;
- Diamond d1(R, R.one, R.one, R.zero);
- Diamond d2(R, R.zero);
- Diamond d3(R, R.p0);
-
- d2.nest(d1, true);
- d3.nest(d1, false);
-
- Node* ret = R.Return(d1.phi, R.start, d1.merge);
-
- R.ReduceGraph(); // d1 gets folded true and d2 gets folded false.
-
- CheckInputs(ret, R.one, R.start, R.start);
- CheckDeadDiamond(d1);
- CheckDeadDiamond(d2);
- CheckDeadDiamond(d3);
-}
-
-
-TEST(Return_nested_diamonds2) {
- ControlReducerTester R;
- Node* x2 = R.jsgraph.Float64Constant(11.1);
- Node* y2 = R.jsgraph.Float64Constant(22.2);
- Node* x3 = R.jsgraph.Float64Constant(33.3);
- Node* y3 = R.jsgraph.Float64Constant(44.4);
-
- Diamond d2(R, R.p0, x2, y2);
- Diamond d3(R, R.p0, x3, y3);
- Diamond d1(R, R.p0, d2.phi, d3.phi);
-
- d2.nest(d1, true);
- d3.nest(d1, false);
-
- Node* ret = R.Return(d1.phi, R.start, d1.merge);
-
- R.ReduceGraph(); // nothing should happen.
-
- CheckInputs(ret, d1.phi, R.start, d1.merge);
- CheckInputs(d1.phi, d2.phi, d3.phi, d1.merge);
- CheckInputs(d1.merge, d2.merge, d3.merge);
- CheckLiveDiamond(d2);
- CheckLiveDiamond(d3);
-}
-
-
-TEST(Return_nested_diamonds_true2) {
- ControlReducerTester R;
- Node* x2 = R.jsgraph.Float64Constant(11.1);
- Node* y2 = R.jsgraph.Float64Constant(22.2);
- Node* x3 = R.jsgraph.Float64Constant(33.3);
- Node* y3 = R.jsgraph.Float64Constant(44.4);
-
- Diamond d2(R, R.p0, x2, y2);
- Diamond d3(R, R.p0, x3, y3);
- Diamond d1(R, R.one, d2.phi, d3.phi);
-
- d2.nest(d1, true);
- d3.nest(d1, false);
-
- Node* ret = R.Return(d1.phi, R.start, d1.merge);
-
- R.ReduceGraph(); // d1 gets folded true.
-
- CheckInputs(ret, d2.phi, R.start, d2.merge);
- CheckInputs(d2.branch, R.p0, R.start);
- CheckDeadDiamond(d1);
- CheckLiveDiamond(d2);
- CheckDeadDiamond(d3);
-}
-
-
-TEST(Return_nested_diamonds_true_true2) {
- ControlReducerTester R;
- Node* x2 = R.jsgraph.Float64Constant(11.1);
- Node* y2 = R.jsgraph.Float64Constant(22.2);
- Node* x3 = R.jsgraph.Float64Constant(33.3);
- Node* y3 = R.jsgraph.Float64Constant(44.4);
-
- Diamond d2(R, R.one, x2, y2);
- Diamond d3(R, R.p0, x3, y3);
- Diamond d1(R, R.one, d2.phi, d3.phi);
-
- d2.nest(d1, true);
- d3.nest(d1, false);
-
- Node* ret = R.Return(d1.phi, R.start, d1.merge);
-
- R.ReduceGraph(); // d1 gets folded true.
-
- CheckInputs(ret, x2, R.start, R.start);
- CheckDeadDiamond(d1);
- CheckDeadDiamond(d2);
- CheckDeadDiamond(d3);
-}
-
-
-TEST(Return_nested_diamonds_true_false2) {
- ControlReducerTester R;
- Node* x2 = R.jsgraph.Float64Constant(11.1);
- Node* y2 = R.jsgraph.Float64Constant(22.2);
- Node* x3 = R.jsgraph.Float64Constant(33.3);
- Node* y3 = R.jsgraph.Float64Constant(44.4);
-
- Diamond d2(R, R.zero, x2, y2);
- Diamond d3(R, R.p0, x3, y3);
- Diamond d1(R, R.one, d2.phi, d3.phi);
-
- d2.nest(d1, true);
- d3.nest(d1, false);
-
- Node* ret = R.Return(d1.phi, R.start, d1.merge);
-
- R.ReduceGraph(); // d1 gets folded true.
-
- CheckInputs(ret, y2, R.start, R.start);
- CheckDeadDiamond(d1);
- CheckDeadDiamond(d2);
- CheckDeadDiamond(d3);
-}
diff --git a/test/cctest/compiler/test-gap-resolver.cc b/test/cctest/compiler/test-gap-resolver.cc
index ea6f4ee..7f85088 100644
--- a/test/cctest/compiler/test-gap-resolver.cc
+++ b/test/cctest/compiler/test-gap-resolver.cc
@@ -7,19 +7,18 @@
#include "src/base/utils/random-number-generator.h"
#include "test/cctest/cctest.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
// The state of our move interpreter is the mapping of operands to values. Note
// that the actual values don't really matter, all we care about is equality.
class InterpreterState {
public:
- typedef std::vector<MoveOperands> Moves;
-
- void ExecuteInParallel(Moves moves) {
+ void ExecuteInParallel(const ParallelMove* moves) {
InterpreterState copy(*this);
- for (Moves::iterator it = moves.begin(); it != moves.end(); ++it) {
- if (!it->IsRedundant()) write(it->destination(), copy.read(it->source()));
+ for (const auto m : *moves) {
+ if (!m->IsRedundant()) write(m->destination(), copy.read(m->source()));
}
}
@@ -32,17 +31,41 @@
}
private:
+ struct Key {
+ bool is_constant;
+ bool is_float;
+ LocationOperand::LocationKind kind;
+ int index;
+
+ bool operator<(const Key& other) const {
+ if (this->is_constant != other.is_constant) {
+ return this->is_constant;
+ }
+ if (this->is_float != other.is_float) {
+ return this->is_float;
+ }
+ if (this->kind != other.kind) {
+ return this->kind < other.kind;
+ }
+ return this->index < other.index;
+ }
+
+ bool operator==(const Key& other) const {
+ return this->is_constant == other.is_constant &&
+ this->kind == other.kind && this->index == other.index;
+ }
+ };
+
// Internally, the state is a normalized permutation of (kind,index) pairs.
- typedef std::pair<InstructionOperand::Kind, int> Key;
typedef Key Value;
typedef std::map<Key, Value> OperandMap;
- Value read(const InstructionOperand* op) const {
+ Value read(const InstructionOperand& op) const {
OperandMap::const_iterator it = values_.find(KeyFor(op));
return (it == values_.end()) ? ValueFor(op) : it->second;
}
- void write(const InstructionOperand* op, Value v) {
+ void write(const InstructionOperand& op, Value v) {
if (v == ValueFor(op)) {
values_.erase(KeyFor(op));
} else {
@@ -50,12 +73,39 @@
}
}
- static Key KeyFor(const InstructionOperand* op) {
- return Key(op->kind(), op->index());
+ static Key KeyFor(const InstructionOperand& op) {
+ bool is_constant = op.IsConstant();
+ bool is_float = false;
+ LocationOperand::LocationKind kind;
+ int index;
+ if (!is_constant) {
+ if (op.IsRegister()) {
+ index = LocationOperand::cast(op).GetRegister().code();
+ } else if (op.IsDoubleRegister()) {
+ index = LocationOperand::cast(op).GetDoubleRegister().code();
+ } else {
+ index = LocationOperand::cast(op).index();
+ }
+ is_float = IsFloatingPoint(LocationOperand::cast(op).representation());
+ kind = LocationOperand::cast(op).location_kind();
+ } else {
+ index = ConstantOperand::cast(op).virtual_register();
+ kind = LocationOperand::REGISTER;
+ }
+ Key key = {is_constant, is_float, kind, index};
+ return key;
}
- static Value ValueFor(const InstructionOperand* op) {
- return Value(op->kind(), op->index());
+ static Value ValueFor(const InstructionOperand& op) { return KeyFor(op); }
+
+ static InstructionOperand FromKey(Key key) {
+ if (key.is_constant) {
+ return ConstantOperand(key.index);
+ }
+ return AllocatedOperand(
+ key.kind,
+ v8::internal::compiler::InstructionSequence::DefaultRepresentation(),
+ key.index);
}
friend std::ostream& operator<<(std::ostream& os,
@@ -63,10 +113,12 @@
for (OperandMap::const_iterator it = is.values_.begin();
it != is.values_.end(); ++it) {
if (it != is.values_.begin()) os << " ";
- InstructionOperand source(it->first.first, it->first.second);
- InstructionOperand destination(it->second.first, it->second.second);
- MoveOperands mo(&source, &destination);
- PrintableMoveOperands pmo = {RegisterConfiguration::ArchDefault(), &mo};
+ InstructionOperand source = FromKey(it->first);
+ InstructionOperand destination = FromKey(it->second);
+ MoveOperands mo(source, destination);
+ PrintableMoveOperands pmo = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
+ &mo};
os << pmo;
}
return os;
@@ -79,30 +131,31 @@
// An abstract interpreter for moves, swaps and parallel moves.
class MoveInterpreter : public GapResolver::Assembler {
public:
- virtual void AssembleMove(InstructionOperand* source,
- InstructionOperand* destination) OVERRIDE {
- InterpreterState::Moves moves;
- moves.push_back(MoveOperands(source, destination));
+ explicit MoveInterpreter(Zone* zone) : zone_(zone) {}
+
+ void AssembleMove(InstructionOperand* source,
+ InstructionOperand* destination) override {
+ ParallelMove* moves = new (zone_) ParallelMove(zone_);
+ moves->AddMove(*source, *destination);
state_.ExecuteInParallel(moves);
}
- virtual void AssembleSwap(InstructionOperand* source,
- InstructionOperand* destination) OVERRIDE {
- InterpreterState::Moves moves;
- moves.push_back(MoveOperands(source, destination));
- moves.push_back(MoveOperands(destination, source));
+ void AssembleSwap(InstructionOperand* source,
+ InstructionOperand* destination) override {
+ ParallelMove* moves = new (zone_) ParallelMove(zone_);
+ moves->AddMove(*source, *destination);
+ moves->AddMove(*destination, *source);
state_.ExecuteInParallel(moves);
}
- void AssembleParallelMove(const ParallelMove* pm) {
- InterpreterState::Moves moves(pm->move_operands()->begin(),
- pm->move_operands()->end());
+ void AssembleParallelMove(const ParallelMove* moves) {
state_.ExecuteInParallel(moves);
}
InterpreterState state() const { return state_; }
private:
+ Zone* const zone_;
InterpreterState state_;
};
@@ -113,11 +166,11 @@
ParallelMove* Create(int size) {
ParallelMove* parallel_move = new (main_zone()) ParallelMove(main_zone());
- std::set<InstructionOperand*, InstructionOperandComparator> seen;
+ std::set<InstructionOperand, CompareOperandModuloType> seen;
for (int i = 0; i < size; ++i) {
- MoveOperands mo(CreateRandomOperand(), CreateRandomOperand());
+ MoveOperands mo(CreateRandomOperand(true), CreateRandomOperand(false));
if (!mo.IsRedundant() && seen.find(mo.destination()) == seen.end()) {
- parallel_move->AddMove(mo.source(), mo.destination(), main_zone());
+ parallel_move->AddMove(mo.source(), mo.destination());
seen.insert(mo.destination());
}
}
@@ -125,30 +178,57 @@
}
private:
- struct InstructionOperandComparator {
- bool operator()(const InstructionOperand* x,
- const InstructionOperand* y) const {
- return (x->kind() < y->kind()) ||
- (x->kind() == y->kind() && x->index() < y->index());
- }
- };
-
- InstructionOperand* CreateRandomOperand() {
- int index = rng_->NextInt(6);
- switch (rng_->NextInt(5)) {
+ MachineRepresentation RandomRepresentation() {
+ int index = rng_->NextInt(3);
+ switch (index) {
case 0:
- return ConstantOperand::Create(index, main_zone());
+ return MachineRepresentation::kWord32;
case 1:
- return StackSlotOperand::Create(index, main_zone());
+ return MachineRepresentation::kWord64;
case 2:
- return DoubleStackSlotOperand::Create(index, main_zone());
- case 3:
- return RegisterOperand::Create(index, main_zone());
- case 4:
- return DoubleRegisterOperand::Create(index, main_zone());
+ return MachineRepresentation::kTagged;
}
UNREACHABLE();
- return NULL;
+ return MachineRepresentation::kNone;
+ }
+
+ MachineRepresentation RandomDoubleRepresentation() {
+ int index = rng_->NextInt(2);
+ if (index == 0) return MachineRepresentation::kFloat64;
+ return MachineRepresentation::kFloat32;
+ }
+
+ InstructionOperand CreateRandomOperand(bool is_source) {
+ int index = rng_->NextInt(7);
+ // destination can't be Constant.
+ switch (rng_->NextInt(is_source ? 7 : 6)) {
+ case 0:
+ return AllocatedOperand(LocationOperand::STACK_SLOT,
+ RandomRepresentation(), index);
+ case 1:
+ return AllocatedOperand(LocationOperand::STACK_SLOT,
+ RandomDoubleRepresentation(), index);
+ case 2:
+ return AllocatedOperand(LocationOperand::REGISTER,
+ RandomRepresentation(), index);
+ case 3:
+ return AllocatedOperand(LocationOperand::REGISTER,
+ RandomDoubleRepresentation(), index);
+ case 4:
+ return ExplicitOperand(
+ LocationOperand::REGISTER, RandomRepresentation(),
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableGeneralCode(1));
+ case 5:
+ return ExplicitOperand(
+ LocationOperand::STACK_SLOT, RandomRepresentation(),
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableGeneralCode(index));
+ case 6:
+ return ConstantOperand(index);
+ }
+ UNREACHABLE();
+ return InstructionOperand();
}
private:
@@ -163,10 +243,10 @@
ParallelMove* pm = pmc.Create(size);
// Note: The gap resolver modifies the ParallelMove, so interpret first.
- MoveInterpreter mi1;
+ MoveInterpreter mi1(pmc.main_zone());
mi1.AssembleParallelMove(pm);
- MoveInterpreter mi2;
+ MoveInterpreter mi2(pmc.main_zone());
GapResolver resolver(&mi2);
resolver.Resolve(pm);
@@ -174,3 +254,7 @@
}
}
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-graph-reducer.cc b/test/cctest/compiler/test-graph-reducer.cc
deleted file mode 100644
index 70b57b9..0000000
--- a/test/cctest/compiler/test-graph-reducer.cc
+++ /dev/null
@@ -1,622 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-
-#include "graph-tester.h"
-#include "src/compiler/graph-reducer.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-const uint8_t OPCODE_A0 = 10;
-const uint8_t OPCODE_A1 = 11;
-const uint8_t OPCODE_A2 = 12;
-const uint8_t OPCODE_B0 = 20;
-const uint8_t OPCODE_B1 = 21;
-const uint8_t OPCODE_B2 = 22;
-const uint8_t OPCODE_C0 = 30;
-const uint8_t OPCODE_C1 = 31;
-const uint8_t OPCODE_C2 = 32;
-
-static Operator OPA0(OPCODE_A0, Operator::kNoWrite, "opa0", 0, 0, 0, 0, 0, 0);
-static Operator OPA1(OPCODE_A1, Operator::kNoWrite, "opa1", 1, 0, 0, 0, 0, 0);
-static Operator OPA2(OPCODE_A2, Operator::kNoWrite, "opa2", 2, 0, 0, 0, 0, 0);
-static Operator OPB0(OPCODE_B0, Operator::kNoWrite, "opa0", 0, 0, 0, 0, 0, 0);
-static Operator OPB1(OPCODE_B1, Operator::kNoWrite, "opa1", 1, 0, 0, 0, 0, 0);
-static Operator OPB2(OPCODE_B2, Operator::kNoWrite, "opa2", 2, 0, 0, 0, 0, 0);
-static Operator OPC0(OPCODE_C0, Operator::kNoWrite, "opc0", 0, 0, 0, 0, 0, 0);
-static Operator OPC1(OPCODE_C1, Operator::kNoWrite, "opc1", 1, 0, 0, 0, 0, 0);
-static Operator OPC2(OPCODE_C2, Operator::kNoWrite, "opc2", 2, 0, 0, 0, 0, 0);
-
-
-// Replaces all "A" operators with "B" operators without creating new nodes.
-class InPlaceABReducer : public Reducer {
- public:
- virtual Reduction Reduce(Node* node) {
- switch (node->op()->opcode()) {
- case OPCODE_A0:
- CHECK_EQ(0, node->InputCount());
- node->set_op(&OPB0);
- return Replace(node);
- case OPCODE_A1:
- CHECK_EQ(1, node->InputCount());
- node->set_op(&OPB1);
- return Replace(node);
- case OPCODE_A2:
- CHECK_EQ(2, node->InputCount());
- node->set_op(&OPB2);
- return Replace(node);
- }
- return NoChange();
- }
-};
-
-
-// Replaces all "A" operators with "B" operators by allocating new nodes.
-class NewABReducer : public Reducer {
- public:
- explicit NewABReducer(Graph* graph) : graph_(graph) {}
- virtual Reduction Reduce(Node* node) {
- switch (node->op()->opcode()) {
- case OPCODE_A0:
- CHECK_EQ(0, node->InputCount());
- return Replace(graph_->NewNode(&OPB0));
- case OPCODE_A1:
- CHECK_EQ(1, node->InputCount());
- return Replace(graph_->NewNode(&OPB1, node->InputAt(0)));
- case OPCODE_A2:
- CHECK_EQ(2, node->InputCount());
- return Replace(
- graph_->NewNode(&OPB2, node->InputAt(0), node->InputAt(1)));
- }
- return NoChange();
- }
- Graph* graph_;
-};
-
-
-// Replaces all "B" operators with "C" operators without creating new nodes.
-class InPlaceBCReducer : public Reducer {
- public:
- virtual Reduction Reduce(Node* node) {
- switch (node->op()->opcode()) {
- case OPCODE_B0:
- CHECK_EQ(0, node->InputCount());
- node->set_op(&OPC0);
- return Replace(node);
- case OPCODE_B1:
- CHECK_EQ(1, node->InputCount());
- node->set_op(&OPC1);
- return Replace(node);
- case OPCODE_B2:
- CHECK_EQ(2, node->InputCount());
- node->set_op(&OPC2);
- return Replace(node);
- }
- return NoChange();
- }
-};
-
-
-// Wraps all "OPA0" nodes in "OPB1" operators by allocating new nodes.
-class A0Wrapper FINAL : public Reducer {
- public:
- explicit A0Wrapper(Graph* graph) : graph_(graph) {}
- virtual Reduction Reduce(Node* node) OVERRIDE {
- switch (node->op()->opcode()) {
- case OPCODE_A0:
- CHECK_EQ(0, node->InputCount());
- return Replace(graph_->NewNode(&OPB1, node));
- }
- return NoChange();
- }
- Graph* graph_;
-};
-
-
-// Wraps all "OPB0" nodes in two "OPC1" operators by allocating new nodes.
-class B0Wrapper FINAL : public Reducer {
- public:
- explicit B0Wrapper(Graph* graph) : graph_(graph) {}
- virtual Reduction Reduce(Node* node) OVERRIDE {
- switch (node->op()->opcode()) {
- case OPCODE_B0:
- CHECK_EQ(0, node->InputCount());
- return Replace(graph_->NewNode(&OPC1, graph_->NewNode(&OPC1, node)));
- }
- return NoChange();
- }
- Graph* graph_;
-};
-
-
-// Replaces all "OPA1" nodes with the first input.
-class A1Forwarder : public Reducer {
- virtual Reduction Reduce(Node* node) {
- switch (node->op()->opcode()) {
- case OPCODE_A1:
- CHECK_EQ(1, node->InputCount());
- return Replace(node->InputAt(0));
- }
- return NoChange();
- }
-};
-
-
-// Replaces all "OPB1" nodes with the first input.
-class B1Forwarder : public Reducer {
- virtual Reduction Reduce(Node* node) {
- switch (node->op()->opcode()) {
- case OPCODE_B1:
- CHECK_EQ(1, node->InputCount());
- return Replace(node->InputAt(0));
- }
- return NoChange();
- }
-};
-
-
-// Swaps the inputs to "OP2A" and "OP2B" nodes based on ids.
-class AB2Sorter : public Reducer {
- virtual Reduction Reduce(Node* node) {
- switch (node->op()->opcode()) {
- case OPCODE_A2:
- case OPCODE_B2:
- CHECK_EQ(2, node->InputCount());
- Node* x = node->InputAt(0);
- Node* y = node->InputAt(1);
- if (x->id() > y->id()) {
- node->ReplaceInput(0, y);
- node->ReplaceInput(1, x);
- return Replace(node);
- }
- }
- return NoChange();
- }
-};
-
-
-// Simply records the nodes visited.
-class ReducerRecorder : public Reducer {
- public:
- explicit ReducerRecorder(Zone* zone)
- : set(NodeSet::key_compare(), NodeSet::allocator_type(zone)) {}
- virtual Reduction Reduce(Node* node) {
- set.insert(node);
- return NoChange();
- }
- void CheckContains(Node* node) {
- CHECK_EQ(1, static_cast<int>(set.count(node)));
- }
- NodeSet set;
-};
-
-
-TEST(ReduceGraphFromEnd1) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* end = graph.NewNode(&OPA1, n1);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph, graph.zone());
- ReducerRecorder recorder(graph.zone());
- reducer.AddReducer(&recorder);
- reducer.ReduceGraph();
- recorder.CheckContains(n1);
- recorder.CheckContains(end);
-}
-
-
-TEST(ReduceGraphFromEnd2) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* n2 = graph.NewNode(&OPA1, n1);
- Node* n3 = graph.NewNode(&OPA1, n1);
- Node* end = graph.NewNode(&OPA2, n2, n3);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph, graph.zone());
- ReducerRecorder recorder(graph.zone());
- reducer.AddReducer(&recorder);
- reducer.ReduceGraph();
- recorder.CheckContains(n1);
- recorder.CheckContains(n2);
- recorder.CheckContains(n3);
- recorder.CheckContains(end);
-}
-
-
-TEST(ReduceInPlace1) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* end = graph.NewNode(&OPA1, n1);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph, graph.zone());
- InPlaceABReducer r;
- reducer.AddReducer(&r);
-
- // Tests A* => B* with in-place updates.
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPB0, n1->op());
- CHECK_EQ(&OPB1, end->op());
- CHECK_EQ(n1, end->InputAt(0));
- }
-}
-
-
-TEST(ReduceInPlace2) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* n2 = graph.NewNode(&OPA1, n1);
- Node* n3 = graph.NewNode(&OPA1, n1);
- Node* end = graph.NewNode(&OPA2, n2, n3);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph, graph.zone());
- InPlaceABReducer r;
- reducer.AddReducer(&r);
-
- // Tests A* => B* with in-place updates.
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPB0, n1->op());
- CHECK_EQ(&OPB1, n2->op());
- CHECK_EQ(n1, n2->InputAt(0));
- CHECK_EQ(&OPB1, n3->op());
- CHECK_EQ(n1, n3->InputAt(0));
- CHECK_EQ(&OPB2, end->op());
- CHECK_EQ(n2, end->InputAt(0));
- CHECK_EQ(n3, end->InputAt(1));
- }
-}
-
-
-TEST(ReduceNew1) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* n2 = graph.NewNode(&OPA1, n1);
- Node* n3 = graph.NewNode(&OPA1, n1);
- Node* end = graph.NewNode(&OPA2, n2, n3);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph, graph.zone());
- NewABReducer r(&graph);
- reducer.AddReducer(&r);
-
- // Tests A* => B* while creating new nodes.
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- if (i == 0) {
- CHECK_NE(before, graph.NodeCount());
- } else {
- CHECK_EQ(before, graph.NodeCount());
- }
- Node* nend = graph.end();
- CHECK_NE(end, nend); // end() should be updated too.
-
- Node* nn2 = nend->InputAt(0);
- Node* nn3 = nend->InputAt(1);
- Node* nn1 = nn2->InputAt(0);
-
- CHECK_EQ(nn1, nn3->InputAt(0));
-
- CHECK_EQ(&OPB0, nn1->op());
- CHECK_EQ(&OPB1, nn2->op());
- CHECK_EQ(&OPB1, nn3->op());
- CHECK_EQ(&OPB2, nend->op());
- }
-}
-
-
-TEST(Wrapping1) {
- GraphTester graph;
-
- Node* end = graph.NewNode(&OPA0);
- graph.SetEnd(end);
- CHECK_EQ(1, graph.NodeCount());
-
- GraphReducer reducer(&graph, graph.zone());
- A0Wrapper r(&graph);
- reducer.AddReducer(&r);
-
- reducer.ReduceGraph();
- CHECK_EQ(2, graph.NodeCount());
-
- Node* nend = graph.end();
- CHECK_NE(end, nend);
- CHECK_EQ(&OPB1, nend->op());
- CHECK_EQ(1, nend->InputCount());
- CHECK_EQ(end, nend->InputAt(0));
-}
-
-
-TEST(Wrapping2) {
- GraphTester graph;
-
- Node* end = graph.NewNode(&OPB0);
- graph.SetEnd(end);
- CHECK_EQ(1, graph.NodeCount());
-
- GraphReducer reducer(&graph, graph.zone());
- B0Wrapper r(&graph);
- reducer.AddReducer(&r);
-
- reducer.ReduceGraph();
- CHECK_EQ(3, graph.NodeCount());
-
- Node* nend = graph.end();
- CHECK_NE(end, nend);
- CHECK_EQ(&OPC1, nend->op());
- CHECK_EQ(1, nend->InputCount());
-
- Node* n1 = nend->InputAt(0);
- CHECK_NE(end, n1);
- CHECK_EQ(&OPC1, n1->op());
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(end, n1->InputAt(0));
-}
-
-
-TEST(Forwarding1) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* end = graph.NewNode(&OPA1, n1);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph, graph.zone());
- A1Forwarder r;
- reducer.AddReducer(&r);
-
- // Tests A1(x) => x
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPA0, n1->op());
- CHECK_EQ(n1, graph.end());
- }
-}
-
-
-TEST(Forwarding2) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* n2 = graph.NewNode(&OPA1, n1);
- Node* n3 = graph.NewNode(&OPA1, n1);
- Node* end = graph.NewNode(&OPA2, n2, n3);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph, graph.zone());
- A1Forwarder r;
- reducer.AddReducer(&r);
-
- // Tests reducing A2(A1(x), A1(y)) => A2(x, y).
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPA0, n1->op());
- CHECK_EQ(n1, end->InputAt(0));
- CHECK_EQ(n1, end->InputAt(1));
- CHECK_EQ(&OPA2, end->op());
- CHECK_EQ(0, n2->UseCount());
- CHECK_EQ(0, n3->UseCount());
- }
-}
-
-
-TEST(Forwarding3) {
- // Tests reducing a chain of A1(A1(A1(A1(x)))) => x.
- for (int i = 0; i < 8; i++) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* end = n1;
- for (int j = 0; j < i; j++) {
- end = graph.NewNode(&OPA1, end);
- }
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph, graph.zone());
- A1Forwarder r;
- reducer.AddReducer(&r);
-
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPA0, n1->op());
- CHECK_EQ(n1, graph.end());
- }
- }
-}
-
-
-TEST(ReduceForward1) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* n2 = graph.NewNode(&OPA1, n1);
- Node* n3 = graph.NewNode(&OPA1, n1);
- Node* end = graph.NewNode(&OPA2, n2, n3);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph, graph.zone());
- InPlaceABReducer r;
- B1Forwarder f;
- reducer.AddReducer(&r);
- reducer.AddReducer(&f);
-
- // Tests first reducing A => B, then B1(x) => x.
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPB0, n1->op());
- CHECK(n2->IsDead());
- CHECK_EQ(n1, end->InputAt(0));
- CHECK(n3->IsDead());
- CHECK_EQ(n1, end->InputAt(0));
- CHECK_EQ(&OPB2, end->op());
- CHECK_EQ(0, n2->UseCount());
- CHECK_EQ(0, n3->UseCount());
- }
-}
-
-
-TEST(Sorter1) {
- HandleAndZoneScope scope;
- AB2Sorter r;
- for (int i = 0; i < 6; i++) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* n2 = graph.NewNode(&OPA1, n1);
- Node* n3 = graph.NewNode(&OPA1, n1);
- Node* end = NULL; // Initialize to please the compiler.
-
- if (i == 0) end = graph.NewNode(&OPA2, n2, n3);
- if (i == 1) end = graph.NewNode(&OPA2, n3, n2);
- if (i == 2) end = graph.NewNode(&OPA2, n2, n1);
- if (i == 3) end = graph.NewNode(&OPA2, n1, n2);
- if (i == 4) end = graph.NewNode(&OPA2, n3, n1);
- if (i == 5) end = graph.NewNode(&OPA2, n1, n3);
-
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph, graph.zone());
- reducer.AddReducer(&r);
-
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPA0, n1->op());
- CHECK_EQ(&OPA1, n2->op());
- CHECK_EQ(&OPA1, n3->op());
- CHECK_EQ(&OPA2, end->op());
- CHECK_EQ(end, graph.end());
- CHECK(end->InputAt(0)->id() <= end->InputAt(1)->id());
- }
-}
-
-
-// Generate a node graph with the given permutations.
-void GenDAG(Graph* graph, int* p3, int* p2, int* p1) {
- Node* level4 = graph->NewNode(&OPA0);
- Node* level3[] = {graph->NewNode(&OPA1, level4),
- graph->NewNode(&OPA1, level4)};
-
- Node* level2[] = {graph->NewNode(&OPA1, level3[p3[0]]),
- graph->NewNode(&OPA1, level3[p3[1]]),
- graph->NewNode(&OPA1, level3[p3[0]]),
- graph->NewNode(&OPA1, level3[p3[1]])};
-
- Node* level1[] = {graph->NewNode(&OPA2, level2[p2[0]], level2[p2[1]]),
- graph->NewNode(&OPA2, level2[p2[2]], level2[p2[3]])};
-
- Node* end = graph->NewNode(&OPA2, level1[p1[0]], level1[p1[1]]);
- graph->SetEnd(end);
-}
-
-
-TEST(SortForwardReduce) {
- GraphTester graph;
-
- // Tests combined reductions on a series of DAGs.
- for (int j = 0; j < 2; j++) {
- int p3[] = {j, 1 - j};
- for (int m = 0; m < 2; m++) {
- int p1[] = {m, 1 - m};
- for (int k = 0; k < 24; k++) { // All permutations of 0, 1, 2, 3
- int p2[] = {-1, -1, -1, -1};
- int n = k;
- for (int d = 4; d >= 1; d--) { // Construct permutation.
- int p = n % d;
- for (int z = 0; z < 4; z++) {
- if (p2[z] == -1) {
- if (p == 0) p2[z] = d - 1;
- p--;
- }
- }
- n = n / d;
- }
-
- GenDAG(&graph, p3, p2, p1);
-
- GraphReducer reducer(&graph, graph.zone());
- AB2Sorter r1;
- A1Forwarder r2;
- InPlaceABReducer r3;
- reducer.AddReducer(&r1);
- reducer.AddReducer(&r2);
- reducer.AddReducer(&r3);
-
- reducer.ReduceGraph();
-
- Node* end = graph.end();
- CHECK_EQ(&OPB2, end->op());
- Node* n1 = end->InputAt(0);
- Node* n2 = end->InputAt(1);
- CHECK_NE(n1, n2);
- CHECK(n1->id() < n2->id());
- CHECK_EQ(&OPB2, n1->op());
- CHECK_EQ(&OPB2, n2->op());
- Node* n4 = n1->InputAt(0);
- CHECK_EQ(&OPB0, n4->op());
- CHECK_EQ(n4, n1->InputAt(1));
- CHECK_EQ(n4, n2->InputAt(0));
- CHECK_EQ(n4, n2->InputAt(1));
- }
- }
- }
-}
-
-
-TEST(Order) {
- // Test that the order of reducers doesn't matter, as they should be
- // rerun for changed nodes.
- for (int i = 0; i < 2; i++) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* end = graph.NewNode(&OPA1, n1);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph, graph.zone());
- InPlaceABReducer abr;
- InPlaceBCReducer bcr;
- if (i == 0) {
- reducer.AddReducer(&abr);
- reducer.AddReducer(&bcr);
- } else {
- reducer.AddReducer(&bcr);
- reducer.AddReducer(&abr);
- }
-
- // Tests A* => C* with in-place updates.
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPC0, n1->op());
- CHECK_EQ(&OPC1, end->op());
- CHECK_EQ(n1, end->InputAt(0));
- }
- }
-}
diff --git a/test/cctest/compiler/test-graph-visualizer.cc b/test/cctest/compiler/test-graph-visualizer.cc
index ce3e6b7..48be46c 100644
--- a/test/cctest/compiler/test-graph-visualizer.cc
+++ b/test/cctest/compiler/test-graph-visualizer.cc
@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-#include "test/cctest/cctest.h"
-
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
#include "src/compiler/graph-visualizer.h"
@@ -14,10 +11,19 @@
#include "src/compiler/operator.h"
#include "src/compiler/schedule.h"
#include "src/compiler/scheduler.h"
+#include "src/compiler/source-position.h"
#include "src/compiler/verifier.h"
+#include "test/cctest/cctest.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+static Operator dummy_operator1(IrOpcode::kParameter, Operator::kNoWrite,
+ "dummy", 1, 0, 0, 1, 0, 0);
+static Operator dummy_operator6(IrOpcode::kParameter, Operator::kNoWrite,
+ "dummy", 6, 0, 0, 1, 0, 0);
+
TEST(NodeWithNullInputReachableFromEnd) {
HandleAndZoneScope scope;
@@ -27,13 +33,14 @@
Node* start = graph.NewNode(common.Start(0));
graph.SetStart(start);
Node* k = graph.NewNode(common.Int32Constant(0));
- Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 1), k, start);
+ Node* phi =
+ graph.NewNode(common.Phi(MachineRepresentation::kTagged, 1), k, start);
phi->ReplaceInput(0, NULL);
graph.SetEnd(phi);
OFStream os(stdout);
- os << AsDOT(graph);
- os << AsJSON(graph);
+ SourcePositionTable table(&graph);
+ os << AsJSON(graph, &table);
}
@@ -45,13 +52,14 @@
Node* start = graph.NewNode(common.Start(0));
graph.SetStart(start);
Node* k = graph.NewNode(common.Int32Constant(0));
- Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 1), k, start);
+ Node* phi =
+ graph.NewNode(common.Phi(MachineRepresentation::kTagged, 1), k, start);
phi->ReplaceInput(1, NULL);
graph.SetEnd(phi);
OFStream os(stdout);
- os << AsDOT(graph);
- os << AsJSON(graph);
+ SourcePositionTable table(&graph);
+ os << AsJSON(graph, &table);
}
@@ -63,13 +71,14 @@
Node* start = graph.NewNode(common.Start(0));
graph.SetStart(start);
Node* k = graph.NewNode(common.Int32Constant(0));
- Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 1), k, start);
+ Node* phi =
+ graph.NewNode(common.Phi(MachineRepresentation::kTagged, 1), k, start);
phi->ReplaceInput(0, NULL);
graph.SetEnd(start);
OFStream os(stdout);
- os << AsDOT(graph);
- os << AsJSON(graph);
+ SourcePositionTable table(&graph);
+ os << AsJSON(graph, &table);
}
@@ -85,6 +94,37 @@
graph.SetEnd(merge);
OFStream os(stdout);
- os << AsDOT(graph);
- os << AsJSON(graph);
+ SourcePositionTable table(&graph);
+ os << AsJSON(graph, &table);
}
+
+
+TEST(NodeNetworkOfDummiesReachableFromEnd) {
+ HandleAndZoneScope scope;
+ Graph graph(scope.main_zone());
+ CommonOperatorBuilder common(scope.main_zone());
+
+ Node* start = graph.NewNode(common.Start(0));
+ graph.SetStart(start);
+ Node* n2 = graph.NewNode(&dummy_operator1, graph.start());
+ Node* n3 = graph.NewNode(&dummy_operator1, graph.start());
+ Node* n4 = graph.NewNode(&dummy_operator1, n2);
+ Node* n5 = graph.NewNode(&dummy_operator1, n2);
+ Node* n6 = graph.NewNode(&dummy_operator1, n3);
+ Node* n7 = graph.NewNode(&dummy_operator1, n3);
+ Node* n8 = graph.NewNode(&dummy_operator1, n5);
+ Node* n9 = graph.NewNode(&dummy_operator1, n5);
+ Node* n10 = graph.NewNode(&dummy_operator1, n9);
+ Node* n11 = graph.NewNode(&dummy_operator1, n9);
+ Node* end_dependencies[6] = {n4, n8, n10, n11, n6, n7};
+ Node* end = graph.NewNode(&dummy_operator6, 6, end_dependencies);
+ graph.SetEnd(end);
+
+ OFStream os(stdout);
+ SourcePositionTable table(&graph);
+ os << AsJSON(graph, &table);
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-instruction.cc b/test/cctest/compiler/test-instruction.cc
index 294812f..4de3373 100644
--- a/test/cctest/compiler/test-instruction.cc
+++ b/test/cctest/compiler/test-instruction.cc
@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-#include "test/cctest/cctest.h"
-
#include "src/compiler/code-generator.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
@@ -15,10 +12,11 @@
#include "src/compiler/operator.h"
#include "src/compiler/schedule.h"
#include "src/compiler/scheduler.h"
-#include "src/lithium.h"
+#include "test/cctest/cctest.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
typedef v8::internal::compiler::Instruction TestInstr;
typedef v8::internal::compiler::InstructionSequence TestInstrSeq;
@@ -27,20 +25,14 @@
class InstructionTester : public HandleAndZoneScope {
public: // We're all friends here.
InstructionTester()
- : isolate(main_isolate()),
- graph(zone()),
+ : graph(zone()),
schedule(zone()),
- info(static_cast<HydrogenCodeStub*>(NULL), main_isolate()),
- linkage(zone(), &info),
common(zone()),
machine(zone()),
code(NULL) {}
- Isolate* isolate;
Graph graph;
Schedule schedule;
- CompilationInfoWithZone info;
- Linkage linkage;
CommonOperatorBuilder common;
MachineOperatorBuilder machine;
TestInstrSeq* code;
@@ -51,11 +43,12 @@
if (schedule.rpo_order()->size() == 0) {
// Compute the RPO order.
Scheduler::ComputeSpecialRPO(main_zone(), &schedule);
- DCHECK(schedule.rpo_order()->size() > 0);
+ CHECK_NE(0u, schedule.rpo_order()->size());
}
InstructionBlocks* instruction_blocks =
TestInstrSeq::InstructionBlocksFor(main_zone(), &schedule);
- code = new (main_zone()) TestInstrSeq(main_zone(), instruction_blocks);
+ code = new (main_zone())
+ TestInstrSeq(main_isolate(), main_zone(), instruction_blocks);
}
Node* Int32Constant(int32_t val) {
@@ -88,15 +81,16 @@
return code->AddInstruction(instr);
}
- UnallocatedOperand* NewUnallocated(int vreg) {
- UnallocatedOperand* unallocated =
- new (zone()) UnallocatedOperand(UnallocatedOperand::ANY);
- unallocated->set_virtual_register(vreg);
- return unallocated;
+ UnallocatedOperand Unallocated(int vreg) {
+ return UnallocatedOperand(UnallocatedOperand::ANY, vreg);
+ }
+
+ RpoNumber RpoFor(BasicBlock* block) {
+ return RpoNumber::FromInt(block->rpo_number());
}
InstructionBlock* BlockAt(BasicBlock* block) {
- return code->InstructionBlockAt(block->GetRpoNumber());
+ return code->InstructionBlockAt(RpoFor(block));
}
BasicBlock* GetBasicBlock(int instruction_index) {
const InstructionBlock* block =
@@ -131,13 +125,9 @@
BasicBlockVector* blocks = R.schedule.rpo_order();
CHECK_EQ(static_cast<int>(blocks->size()), R.code->InstructionBlockCount());
- int index = 0;
- for (BasicBlockVectorIter i = blocks->begin(); i != blocks->end();
- i++, index++) {
- BasicBlock* block = *i;
+ for (auto block : *blocks) {
CHECK_EQ(block->rpo_number(), R.BlockAt(block)->rpo_number().ToInt());
- CHECK_EQ(block->id().ToInt(), R.BlockAt(block)->id().ToInt());
- CHECK_EQ(NULL, block->loop_end());
+ CHECK(!block->loop_end());
}
}
@@ -156,23 +146,23 @@
R.allocCode();
- R.code->StartBlock(b0->GetRpoNumber());
+ R.code->StartBlock(R.RpoFor(b0));
int i0 = R.NewInstr();
int i1 = R.NewInstr();
- R.code->EndBlock(b0->GetRpoNumber());
- R.code->StartBlock(b1->GetRpoNumber());
+ R.code->EndBlock(R.RpoFor(b0));
+ R.code->StartBlock(R.RpoFor(b1));
int i2 = R.NewInstr();
int i3 = R.NewInstr();
int i4 = R.NewInstr();
int i5 = R.NewInstr();
- R.code->EndBlock(b1->GetRpoNumber());
- R.code->StartBlock(b2->GetRpoNumber());
+ R.code->EndBlock(R.RpoFor(b1));
+ R.code->StartBlock(R.RpoFor(b2));
int i6 = R.NewInstr();
int i7 = R.NewInstr();
int i8 = R.NewInstr();
- R.code->EndBlock(b2->GetRpoNumber());
- R.code->StartBlock(b3->GetRpoNumber());
- R.code->EndBlock(b3->GetRpoNumber());
+ R.code->EndBlock(R.RpoFor(b2));
+ R.code->StartBlock(R.RpoFor(b3));
+ R.code->EndBlock(R.RpoFor(b3));
CHECK_EQ(b0, R.GetBasicBlock(i0));
CHECK_EQ(b0, R.GetBasicBlock(i1));
@@ -208,20 +198,13 @@
R.allocCode();
TestInstr* i0 = TestInstr::New(R.zone(), 100);
- TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl();
- R.code->StartBlock(b0->GetRpoNumber());
+ TestInstr* g = TestInstr::New(R.zone(), 103);
+ R.code->StartBlock(R.RpoFor(b0));
R.code->AddInstruction(i0);
R.code->AddInstruction(g);
- R.code->EndBlock(b0->GetRpoNumber());
+ R.code->EndBlock(R.RpoFor(b0));
- CHECK_EQ(true, R.code->InstructionAt(0)->IsBlockStart());
-
- CHECK_EQ(true, R.code->IsGapAt(0)); // Label
- CHECK_EQ(true, R.code->IsGapAt(1)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(2)); // i0
- CHECK_EQ(true, R.code->IsGapAt(3)); // Gap
- CHECK_EQ(true, R.code->IsGapAt(4)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(5)); // g
+ CHECK(R.code->instructions().size() == 2);
}
@@ -235,36 +218,20 @@
R.allocCode();
TestInstr* i0 = TestInstr::New(R.zone(), 100);
- TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl();
- R.code->StartBlock(b0->GetRpoNumber());
+ TestInstr* g = TestInstr::New(R.zone(), 103);
+ R.code->StartBlock(R.RpoFor(b0));
R.code->AddInstruction(i0);
R.code->AddInstruction(g);
- R.code->EndBlock(b0->GetRpoNumber());
+ R.code->EndBlock(R.RpoFor(b0));
TestInstr* i1 = TestInstr::New(R.zone(), 102);
- TestInstr* g1 = TestInstr::New(R.zone(), 104)->MarkAsControl();
- R.code->StartBlock(b1->GetRpoNumber());
+ TestInstr* g1 = TestInstr::New(R.zone(), 104);
+ R.code->StartBlock(R.RpoFor(b1));
R.code->AddInstruction(i1);
R.code->AddInstruction(g1);
- R.code->EndBlock(b1->GetRpoNumber());
+ R.code->EndBlock(R.RpoFor(b1));
- CHECK_EQ(true, R.code->InstructionAt(0)->IsBlockStart());
-
- CHECK_EQ(true, R.code->IsGapAt(0)); // Label
- CHECK_EQ(true, R.code->IsGapAt(1)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(2)); // i0
- CHECK_EQ(true, R.code->IsGapAt(3)); // Gap
- CHECK_EQ(true, R.code->IsGapAt(4)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(5)); // g
-
- CHECK_EQ(true, R.code->InstructionAt(6)->IsBlockStart());
-
- CHECK_EQ(true, R.code->IsGapAt(6)); // Label
- CHECK_EQ(true, R.code->IsGapAt(7)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(8)); // i1
- CHECK_EQ(true, R.code->IsGapAt(9)); // Gap
- CHECK_EQ(true, R.code->IsGapAt(10)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(11)); // g1
+ CHECK(R.code->instructions().size() == 4);
}
@@ -276,43 +243,32 @@
R.allocCode();
TestInstr* i0 = TestInstr::New(R.zone(), 100);
- TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl();
- R.code->StartBlock(b0->GetRpoNumber());
+ TestInstr* g = TestInstr::New(R.zone(), 103);
+ R.code->StartBlock(R.RpoFor(b0));
R.code->AddInstruction(i0);
R.code->AddInstruction(g);
- R.code->EndBlock(b0->GetRpoNumber());
+ R.code->EndBlock(R.RpoFor(b0));
- CHECK_EQ(true, R.code->InstructionAt(0)->IsBlockStart());
+ CHECK(R.code->instructions().size() == 2);
- CHECK_EQ(true, R.code->IsGapAt(0)); // Label
- CHECK_EQ(true, R.code->IsGapAt(1)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(2)); // i0
- CHECK_EQ(true, R.code->IsGapAt(3)); // Gap
- CHECK_EQ(true, R.code->IsGapAt(4)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(5)); // g
-
- int indexes[] = {0, 1, 3, 4, -1};
- for (int i = 0; indexes[i] >= 0; i++) {
- int index = indexes[i];
-
- UnallocatedOperand* op1 = R.NewUnallocated(index + 6);
- UnallocatedOperand* op2 = R.NewUnallocated(index + 12);
-
- R.code->AddGapMove(index, op1, op2);
- GapInstruction* gap = R.code->GapAt(index);
- ParallelMove* move = gap->GetParallelMove(GapInstruction::START);
- CHECK_NE(NULL, move);
- const ZoneList<MoveOperands>* move_operands = move->move_operands();
- CHECK_EQ(1, move_operands->length());
- MoveOperands* cur = &move_operands->at(0);
- CHECK_EQ(op1, cur->source());
- CHECK_EQ(op2, cur->destination());
+ int index = 0;
+ for (auto instr : R.code->instructions()) {
+ UnallocatedOperand op1 = R.Unallocated(index++);
+ UnallocatedOperand op2 = R.Unallocated(index++);
+ instr->GetOrCreateParallelMove(TestInstr::START, R.zone())
+ ->AddMove(op1, op2);
+ ParallelMove* move = instr->GetParallelMove(TestInstr::START);
+ CHECK(move);
+ CHECK_EQ(1u, move->size());
+ MoveOperands* cur = move->at(0);
+ CHECK(op1.Equals(cur->source()));
+ CHECK(op2.Equals(cur->destination()));
}
}
TEST(InstructionOperands) {
- Zone zone(CcTest::InitIsolateOnce());
+ Zone zone;
{
TestInstr* i = TestInstr::New(&zone, 101);
@@ -321,23 +277,24 @@
CHECK_EQ(0, static_cast<int>(i->TempCount()));
}
- InstructionOperand* outputs[] = {
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER)};
+ int vreg = 15;
+ InstructionOperand outputs[] = {
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg)};
- InstructionOperand* inputs[] = {
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER)};
+ InstructionOperand inputs[] = {
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg)};
- InstructionOperand* temps[] = {
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER)};
+ InstructionOperand temps[] = {
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg),
+ UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg)};
for (size_t i = 0; i < arraysize(outputs); i++) {
for (size_t j = 0; j < arraysize(inputs); j++) {
@@ -349,17 +306,21 @@
CHECK(k == m->TempCount());
for (size_t z = 0; z < i; z++) {
- CHECK_EQ(outputs[z], m->OutputAt(z));
+ CHECK(outputs[z].Equals(*m->OutputAt(z)));
}
for (size_t z = 0; z < j; z++) {
- CHECK_EQ(inputs[z], m->InputAt(z));
+ CHECK(inputs[z].Equals(*m->InputAt(z)));
}
for (size_t z = 0; z < k; z++) {
- CHECK_EQ(temps[z], m->TempAt(z));
+ CHECK(temps[z].Equals(*m->TempAt(z)));
}
}
}
}
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-js-constant-cache.cc b/test/cctest/compiler/test-js-constant-cache.cc
index 8588f66..06169f3 100644
--- a/test/cctest/compiler/test-js-constant-cache.cc
+++ b/test/cctest/compiler/test-js-constant-cache.cc
@@ -2,26 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "src/assembler.h"
#include "src/compiler/js-graph.h"
-#include "src/compiler/node-properties-inl.h"
+#include "src/compiler/node-properties.h"
#include "src/compiler/typer.h"
#include "src/types.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/value-helper.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
class JSCacheTesterHelper {
protected:
- explicit JSCacheTesterHelper(Zone* zone)
+ JSCacheTesterHelper(Isolate* isolate, Zone* zone)
: main_graph_(zone),
main_common_(zone),
main_javascript_(zone),
- main_typer_(&main_graph_, MaybeHandle<Context>()),
+ main_typer_(isolate, &main_graph_),
main_machine_(zone) {}
Graph main_graph_;
CommonOperatorBuilder main_common_;
@@ -37,19 +36,20 @@
public JSGraph {
public:
JSConstantCacheTester()
- : JSCacheTesterHelper(main_zone()),
- JSGraph(&main_graph_, &main_common_, &main_javascript_,
- &main_machine_) {
+ : JSCacheTesterHelper(main_isolate(), main_zone()),
+ JSGraph(main_isolate(), &main_graph_, &main_common_, &main_javascript_,
+ nullptr, &main_machine_) {
main_graph_.SetStart(main_graph_.NewNode(common()->Start(0)));
- main_graph_.SetEnd(main_graph_.NewNode(common()->End()));
+ main_graph_.SetEnd(
+ main_graph_.NewNode(common()->End(1), main_graph_.start()));
main_typer_.Run();
}
- Type* upper(Node* node) { return NodeProperties::GetBounds(node).upper; }
+ Type* TypeOf(Node* node) { return NodeProperties::GetType(node); }
- Handle<Object> handle(Node* node) {
+ Handle<HeapObject> handle(Node* node) {
CHECK_EQ(IrOpcode::kHeapConstant, node->opcode());
- return OpParameter<Unique<Object> >(node).handle();
+ return OpParameter<Handle<HeapObject>>(node);
}
Factory* factory() { return main_isolate()->factory(); }
@@ -65,11 +65,11 @@
CHECK_EQ(zero, T.Constant(0));
CHECK_NE(zero, T.Constant(-0.0));
CHECK_NE(zero, T.Constant(1.0));
- CHECK_NE(zero, T.Constant(v8::base::OS::nan_value()));
+ CHECK_NE(zero, T.Constant(std::numeric_limits<double>::quiet_NaN()));
CHECK_NE(zero, T.Float64Constant(0));
CHECK_NE(zero, T.Int32Constant(0));
- Type* t = T.upper(zero);
+ Type* t = T.TypeOf(zero);
CHECK(t->Is(Type::Number()));
CHECK(t->Is(Type::Integral32()));
@@ -90,7 +90,7 @@
CHECK_EQ(minus_zero, T.Constant(-0.0));
CHECK_NE(zero, minus_zero);
- Type* t = T.upper(minus_zero);
+ Type* t = T.TypeOf(minus_zero);
CHECK(t->Is(Type::Number()));
CHECK(t->Is(Type::MinusZero()));
@@ -103,10 +103,10 @@
double zero_value = OpParameter<double>(zero);
double minus_zero_value = OpParameter<double>(minus_zero);
- CHECK_EQ(0.0, zero_value);
- CHECK_NE(-0.0, zero_value);
- CHECK_EQ(-0.0, minus_zero_value);
- CHECK_NE(0.0, minus_zero_value);
+ CHECK(bit_cast<uint64_t>(0.0) == bit_cast<uint64_t>(zero_value));
+ CHECK(bit_cast<uint64_t>(-0.0) != bit_cast<uint64_t>(zero_value));
+ CHECK(bit_cast<uint64_t>(0.0) != bit_cast<uint64_t>(minus_zero_value));
+ CHECK(bit_cast<uint64_t>(-0.0) == bit_cast<uint64_t>(minus_zero_value));
}
@@ -119,11 +119,11 @@
CHECK_EQ(zero, T.ZeroConstant());
CHECK_NE(zero, T.Constant(-0.0));
CHECK_NE(zero, T.Constant(1.0));
- CHECK_NE(zero, T.Constant(v8::base::OS::nan_value()));
+ CHECK_NE(zero, T.Constant(std::numeric_limits<double>::quiet_NaN()));
CHECK_NE(zero, T.Float64Constant(0));
CHECK_NE(zero, T.Int32Constant(0));
- Type* t = T.upper(zero);
+ Type* t = T.TypeOf(zero);
CHECK(t->Is(Type::Number()));
CHECK(t->Is(Type::Integral32()));
@@ -144,11 +144,11 @@
CHECK_EQ(one, T.Constant(1.0));
CHECK_NE(one, T.Constant(1.01));
CHECK_NE(one, T.Constant(-1.01));
- CHECK_NE(one, T.Constant(v8::base::OS::nan_value()));
+ CHECK_NE(one, T.Constant(std::numeric_limits<double>::quiet_NaN()));
CHECK_NE(one, T.Float64Constant(1.0));
CHECK_NE(one, T.Int32Constant(1));
- Type* t = T.upper(one);
+ Type* t = T.TypeOf(one);
CHECK(t->Is(Type::Number()));
CHECK(t->Is(Type::Integral32()));
@@ -169,11 +169,11 @@
CHECK_EQ(one, T.Constant(1.0));
CHECK_NE(one, T.Constant(1.01));
CHECK_NE(one, T.Constant(-1.01));
- CHECK_NE(one, T.Constant(v8::base::OS::nan_value()));
+ CHECK_NE(one, T.Constant(std::numeric_limits<double>::quiet_NaN()));
CHECK_NE(one, T.Float64Constant(1.0));
CHECK_NE(one, T.Int32Constant(1));
- Type* t = T.upper(one);
+ Type* t = T.TypeOf(one);
CHECK(t->Is(Type::Number()));
CHECK(t->Is(Type::Integral32()));
@@ -233,7 +233,7 @@
FOR_FLOAT64_INPUTS(i) {
double value = *i;
Node* node = T.Constant(value);
- CHECK(T.upper(node)->Is(Type::Of(value, T.main_zone())));
+ CHECK(T.TypeOf(node)->Is(Type::Of(value, T.main_zone())));
}
}
@@ -280,15 +280,15 @@
TEST(OddballTypes) {
JSConstantCacheTester T;
- CHECK(T.upper(T.UndefinedConstant())->Is(Type::Undefined()));
+ CHECK(T.TypeOf(T.UndefinedConstant())->Is(Type::Undefined()));
// TODO(dcarney): figure this out.
- // CHECK(T.upper(T.TheHoleConstant())->Is(Type::Internal()));
- CHECK(T.upper(T.TrueConstant())->Is(Type::Boolean()));
- CHECK(T.upper(T.FalseConstant())->Is(Type::Boolean()));
- CHECK(T.upper(T.NullConstant())->Is(Type::Null()));
- CHECK(T.upper(T.ZeroConstant())->Is(Type::Number()));
- CHECK(T.upper(T.OneConstant())->Is(Type::Number()));
- CHECK(T.upper(T.NaNConstant())->Is(Type::NaN()));
+ // CHECK(T.TypeOf(T.TheHoleConstant())->Is(Type::Internal()));
+ CHECK(T.TypeOf(T.TrueConstant())->Is(Type::Boolean()));
+ CHECK(T.TypeOf(T.FalseConstant())->Is(Type::Boolean()));
+ CHECK(T.TypeOf(T.NullConstant())->Is(Type::Null()));
+ CHECK(T.TypeOf(T.ZeroConstant())->Is(Type::Number()));
+ CHECK(T.TypeOf(T.OneConstant())->Is(Type::Number()));
+ CHECK(T.TypeOf(T.NaNConstant())->Is(Type::NaN()));
}
@@ -335,7 +335,7 @@
25, 15, 30, 31, 45, 46, 47, 48};
for (size_t i = 0; i < arraysize(constants); i++) {
- int count_before = T.graph()->NodeCount();
+ size_t count_before = T.graph()->NodeCount();
NodeVector nodes_before(T.main_zone());
T.GetCachedNodes(&nodes_before);
Node* n = T.Int32Constant(constants[i]);
@@ -357,7 +357,7 @@
11, 11, -33.3, -33.3, -22, -11};
for (size_t i = 0; i < arraysize(constants); i++) {
- int count_before = T.graph()->NodeCount();
+ size_t count_before = T.graph()->NodeCount();
NodeVector nodes_before(T.main_zone());
T.GetCachedNodes(&nodes_before);
Node* n = T.Float64Constant(constants[i]);
@@ -379,7 +379,7 @@
19, 20, 20, 21, 21, 22, 23, 24, 25};
for (size_t i = 0; i < arraysize(constants); i++) {
- int count_before = T.graph()->NodeCount();
+ size_t count_before = T.graph()->NodeCount();
NodeVector nodes_before(T.main_zone());
T.GetCachedNodes(&nodes_before);
Node* n = T.Int64Constant(constants[i]);
@@ -401,7 +401,7 @@
11, 11, -33.3, -33.3, -22, -11};
for (size_t i = 0; i < arraysize(constants); i++) {
- int count_before = T.graph()->NodeCount();
+ size_t count_before = T.graph()->NodeCount();
NodeVector nodes_before(T.main_zone());
T.GetCachedNodes(&nodes_before);
Node* n = T.Constant(constants[i]);
@@ -428,7 +428,7 @@
ExternalReference::address_of_one_half()};
for (size_t i = 0; i < arraysize(constants); i++) {
- int count_before = T.graph()->NodeCount();
+ size_t count_before = T.graph()->NodeCount();
NodeVector nodes_before(T.main_zone());
T.GetCachedNodes(&nodes_before);
Node* n = T.ExternalConstant(constants[i]);
@@ -472,3 +472,7 @@
CHECK(Contains(&nodes, constants[i]));
}
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-js-context-specialization.cc b/test/cctest/compiler/test-js-context-specialization.cc
index fb7bd94..43b7665 100644
--- a/test/cctest/compiler/test-js-context-specialization.cc
+++ b/test/cctest/compiler/test-js-context-specialization.cc
@@ -3,50 +3,56 @@
// found in the LICENSE file.
#include "src/compiler/js-context-specialization.h"
+#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/node-matchers.h"
-#include "src/compiler/node-properties-inl.h"
+#include "src/compiler/node-properties.h"
#include "src/compiler/source-position.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/function-tester.h"
#include "test/cctest/compiler/graph-builder-tester.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
-class ContextSpecializationTester : public HandleAndZoneScope,
- public DirectGraphBuilder {
+class ContextSpecializationTester : public HandleAndZoneScope {
public:
ContextSpecializationTester()
- : DirectGraphBuilder(new (main_zone()) Graph(main_zone())),
+ : graph_(new (main_zone()) Graph(main_zone())),
common_(main_zone()),
javascript_(main_zone()),
machine_(main_zone()),
simplified_(main_zone()),
- jsgraph_(graph(), common(), &javascript_, &machine_),
- info_(main_isolate(), main_zone()) {}
+ jsgraph_(main_isolate(), graph(), common(), &javascript_, &simplified_,
+ &machine_),
+ reducer_(main_zone(), graph()),
+ spec_(&reducer_, jsgraph(), MaybeHandle<Context>()) {}
+ JSContextSpecialization* spec() { return &spec_; }
Factory* factory() { return main_isolate()->factory(); }
CommonOperatorBuilder* common() { return &common_; }
JSOperatorBuilder* javascript() { return &javascript_; }
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
JSGraph* jsgraph() { return &jsgraph_; }
- CompilationInfo* info() { return &info_; }
+ Graph* graph() { return graph_; }
private:
+ Graph* graph_;
CommonOperatorBuilder common_;
JSOperatorBuilder javascript_;
MachineOperatorBuilder machine_;
SimplifiedOperatorBuilder simplified_;
JSGraph jsgraph_;
- CompilationInfo info_;
+ GraphReducer reducer_;
+ JSContextSpecialization spec_;
};
TEST(ReduceJSLoadContext) {
ContextSpecializationTester t;
- Node* start = t.NewNode(t.common()->Start(0));
+ Node* start = t.graph()->NewNode(t.common()->Start(0));
t.graph()->SetStart(start);
// Make a context and initialize it a bit for this test.
@@ -56,41 +62,40 @@
subcontext2->set_previous(*subcontext1);
subcontext1->set_previous(*native);
Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!");
- const int slot = Context::GLOBAL_OBJECT_INDEX;
+ const int slot = Context::NATIVE_CONTEXT_INDEX;
native->set(slot, *expected);
Node* const_context = t.jsgraph()->Constant(native);
Node* deep_const_context = t.jsgraph()->Constant(subcontext2);
- Node* param_context = t.NewNode(t.common()->Parameter(0), start);
- JSContextSpecializer spec(t.info(), t.jsgraph(), const_context);
+ Node* param_context = t.graph()->NewNode(t.common()->Parameter(0), start);
{
// Mutable slot, constant context, depth = 0 => do nothing.
- Node* load = t.NewNode(t.javascript()->LoadContext(0, 0, false),
- const_context, const_context, start);
- Reduction r = spec.ReduceJSLoadContext(load);
+ Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, 0, false),
+ const_context, const_context, start);
+ Reduction r = t.spec()->Reduce(load);
CHECK(!r.Changed());
}
{
// Mutable slot, non-constant context, depth = 0 => do nothing.
- Node* load = t.NewNode(t.javascript()->LoadContext(0, 0, false),
- param_context, param_context, start);
- Reduction r = spec.ReduceJSLoadContext(load);
+ Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, 0, false),
+ param_context, param_context, start);
+ Reduction r = t.spec()->Reduce(load);
CHECK(!r.Changed());
}
{
// Mutable slot, constant context, depth > 0 => fold-in parent context.
- Node* load = t.NewNode(
+ Node* load = t.graph()->NewNode(
t.javascript()->LoadContext(2, Context::GLOBAL_EVAL_FUN_INDEX, false),
deep_const_context, deep_const_context, start);
- Reduction r = spec.ReduceJSLoadContext(load);
+ Reduction r = t.spec()->Reduce(load);
CHECK(r.Changed());
Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0);
CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode());
- HeapObjectMatcher<Context> match(new_context_input);
- CHECK_EQ(*native, *match.Value().handle());
+ HeapObjectMatcher match(new_context_input);
+ CHECK_EQ(*native, *match.Value());
ContextAccess access = OpParameter<ContextAccess>(r.replacement());
CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index()));
CHECK_EQ(0, static_cast<int>(access.depth()));
@@ -99,15 +104,15 @@
{
// Immutable slot, constant context, depth = 0 => specialize.
- Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true),
- const_context, const_context, start);
- Reduction r = spec.ReduceJSLoadContext(load);
+ Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true),
+ const_context, const_context, start);
+ Reduction r = t.spec()->Reduce(load);
CHECK(r.Changed());
CHECK(r.replacement() != load);
- HeapObjectMatcher<Object> match(r.replacement());
+ HeapObjectMatcher match(r.replacement());
CHECK(match.HasValue());
- CHECK_EQ(*expected, *match.Value().handle());
+ CHECK_EQ(*expected, *match.Value());
}
// TODO(titzer): test with other kinds of contexts, e.g. a function context.
@@ -118,7 +123,7 @@
TEST(ReduceJSStoreContext) {
ContextSpecializationTester t;
- Node* start = t.NewNode(t.common()->Start(0));
+ Node* start = t.graph()->NewNode(t.common()->Start(0));
t.graph()->SetStart(start);
// Make a context and initialize it a bit for this test.
@@ -128,49 +133,51 @@
subcontext2->set_previous(*subcontext1);
subcontext1->set_previous(*native);
Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!");
- const int slot = Context::GLOBAL_OBJECT_INDEX;
+ const int slot = Context::NATIVE_CONTEXT_INDEX;
native->set(slot, *expected);
Node* const_context = t.jsgraph()->Constant(native);
Node* deep_const_context = t.jsgraph()->Constant(subcontext2);
- Node* param_context = t.NewNode(t.common()->Parameter(0), start);
- JSContextSpecializer spec(t.info(), t.jsgraph(), const_context);
+ Node* param_context = t.graph()->NewNode(t.common()->Parameter(0), start);
{
// Mutable slot, constant context, depth = 0 => do nothing.
- Node* load = t.NewNode(t.javascript()->StoreContext(0, 0), const_context,
- const_context, start);
- Reduction r = spec.ReduceJSStoreContext(load);
+ Node* load =
+ t.graph()->NewNode(t.javascript()->StoreContext(0, 0), const_context,
+ const_context, const_context, start, start);
+ Reduction r = t.spec()->Reduce(load);
CHECK(!r.Changed());
}
{
// Mutable slot, non-constant context, depth = 0 => do nothing.
- Node* load = t.NewNode(t.javascript()->StoreContext(0, 0), param_context,
- param_context, start);
- Reduction r = spec.ReduceJSStoreContext(load);
+ Node* load =
+ t.graph()->NewNode(t.javascript()->StoreContext(0, 0), param_context,
+ param_context, const_context, start, start);
+ Reduction r = t.spec()->Reduce(load);
CHECK(!r.Changed());
}
{
// Immutable slot, constant context, depth = 0 => do nothing.
- Node* load = t.NewNode(t.javascript()->StoreContext(0, slot), const_context,
- const_context, start);
- Reduction r = spec.ReduceJSStoreContext(load);
+ Node* load =
+ t.graph()->NewNode(t.javascript()->StoreContext(0, slot), const_context,
+ const_context, const_context, start, start);
+ Reduction r = t.spec()->Reduce(load);
CHECK(!r.Changed());
}
{
// Mutable slot, constant context, depth > 0 => fold-in parent context.
- Node* load = t.NewNode(
+ Node* load = t.graph()->NewNode(
t.javascript()->StoreContext(2, Context::GLOBAL_EVAL_FUN_INDEX),
- deep_const_context, deep_const_context, start);
- Reduction r = spec.ReduceJSStoreContext(load);
+ deep_const_context, deep_const_context, const_context, start, start);
+ Reduction r = t.spec()->Reduce(load);
CHECK(r.Changed());
Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0);
CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode());
- HeapObjectMatcher<Context> match(new_context_input);
- CHECK_EQ(*native, *match.Value().handle());
+ HeapObjectMatcher match(new_context_input);
+ CHECK_EQ(*native, *match.Value());
ContextAccess access = OpParameter<ContextAccess>(r.replacement());
CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index()));
CHECK_EQ(0, static_cast<int>(access.depth()));
@@ -188,40 +195,43 @@
TEST(SpecializeToContext) {
ContextSpecializationTester t;
- Node* start = t.NewNode(t.common()->Start(0));
+ Node* start = t.graph()->NewNode(t.common()->Start(0));
t.graph()->SetStart(start);
// Make a context and initialize it a bit for this test.
Handle<Context> native = t.factory()->NewNativeContext();
Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!");
- const int slot = Context::GLOBAL_OBJECT_INDEX;
+ const int slot = Context::NATIVE_CONTEXT_INDEX;
native->set(slot, *expected);
- t.info()->SetContext(native);
Node* const_context = t.jsgraph()->Constant(native);
- Node* param_context = t.NewNode(t.common()->Parameter(0), start);
- JSContextSpecializer spec(t.info(), t.jsgraph(), const_context);
+ Node* param_context = t.graph()->NewNode(t.common()->Parameter(0), start);
{
// Check that specialization replaces values and forwards effects
// correctly, and folds values from constant and non-constant contexts
Node* effect_in = start;
- Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true),
- const_context, const_context, effect_in);
+ Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true),
+ const_context, const_context, effect_in);
- Node* value_use = t.NewNode(t.simplified()->ChangeTaggedToInt32(), load);
- Node* other_load = t.NewNode(t.javascript()->LoadContext(0, slot, true),
- param_context, param_context, load);
+ Node* value_use =
+ t.graph()->NewNode(t.simplified()->ChangeTaggedToInt32(), load);
+ Node* other_load =
+ t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true),
+ param_context, param_context, load);
Node* effect_use = other_load;
Node* other_use =
- t.NewNode(t.simplified()->ChangeTaggedToInt32(), other_load);
+ t.graph()->NewNode(t.simplified()->ChangeTaggedToInt32(), other_load);
- Node* add = t.NewNode(t.javascript()->Add(), value_use, other_use,
- param_context, other_load, start);
+ Node* add = t.graph()->NewNode(
+ t.javascript()->Add(LanguageMode::SLOPPY, BinaryOperationHints::Any()),
+ value_use, other_use, param_context, t.jsgraph()->EmptyFrameState(),
+ t.jsgraph()->EmptyFrameState(), other_load, start);
- Node* ret = t.NewNode(t.common()->Return(), add, effect_use, start);
- Node* end = t.NewNode(t.common()->End(), ret);
+ Node* ret =
+ t.graph()->NewNode(t.common()->Return(), add, effect_use, start);
+ Node* end = t.graph()->NewNode(t.common()->End(1), ret);
USE(end);
t.graph()->SetEnd(end);
@@ -230,7 +240,9 @@
CheckEffectInput(load, effect_use);
// Perform the reduction on the entire graph.
- GraphReducer graph_reducer(t.graph(), t.main_zone());
+ GraphReducer graph_reducer(t.main_zone(), t.graph());
+ JSContextSpecialization spec(&graph_reducer, t.jsgraph(),
+ MaybeHandle<Context>());
graph_reducer.AddReducer(&spec);
graph_reducer.ReduceGraph();
@@ -241,9 +253,9 @@
CHECK_EQ(other_load, other_use->InputAt(0));
Node* replacement = value_use->InputAt(0);
- HeapObjectMatcher<Object> match(replacement);
+ HeapObjectMatcher match(replacement);
CHECK(match.HasValue());
- CHECK_EQ(*expected, *match.Value().handle());
+ CHECK_EQ(*expected, *match.Value());
}
// TODO(titzer): clean up above test and test more complicated effects.
}
@@ -304,3 +316,7 @@
CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsNaN());
}
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-js-typed-lowering.cc b/test/cctest/compiler/test-js-typed-lowering.cc
index 3023837..c8b7734 100644
--- a/test/cctest/compiler/test-js-typed-lowering.cc
+++ b/test/cctest/compiler/test-js-typed-lowering.cc
@@ -2,17 +2,33 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/compiler/graph-inl.h"
+#include "src/compilation-dependencies.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-typed-lowering.h"
#include "src/compiler/machine-operator.h"
-#include "src/compiler/node-properties-inl.h"
+#include "src/compiler/node-properties.h"
#include "src/compiler/opcodes.h"
+#include "src/compiler/operator-properties.h"
+#include "src/compiler/simplified-operator.h"
#include "src/compiler/typer.h"
#include "test/cctest/cctest.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+#ifndef TEST_WITH_STRONG
+#define TEST_WITH_STRONG(Name) \
+ static void Test##Name(); \
+ static void TestWithStrong##Name(LanguageMode language_mode); \
+ CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, true, true); \
+ static void Test##Name() { \
+ TestWithStrong##Name(LanguageMode::SLOPPY); \
+ TestWithStrong##Name(LanguageMode::STRONG); \
+ } \
+ static void TestWithStrong##Name(LanguageMode language_mode)
+#endif
+
class JSTypedLoweringTester : public HandleAndZoneScope {
public:
@@ -24,11 +40,12 @@
machine(main_zone()),
simplified(main_zone()),
common(main_zone()),
+ deps(main_isolate(), main_zone()),
graph(main_zone()),
- typer(&graph, MaybeHandle<Context>()),
+ typer(main_isolate(), &graph),
context_node(NULL) {
graph.SetStart(graph.NewNode(common.Start(num_parameters)));
- graph.SetEnd(graph.NewNode(common.End()));
+ graph.SetEnd(graph.NewNode(common.End(1), graph.start()));
typer.Run();
}
@@ -39,26 +56,25 @@
MachineOperatorBuilder machine;
SimplifiedOperatorBuilder simplified;
CommonOperatorBuilder common;
+ CompilationDependencies deps;
Graph graph;
Typer typer;
Node* context_node;
+ BinaryOperationHints const hints = BinaryOperationHints::Any();
Node* Parameter(Type* t, int32_t index = 0) {
Node* n = graph.NewNode(common.Parameter(index), graph.start());
- NodeProperties::SetBounds(n, Bounds(Type::None(), t));
+ NodeProperties::SetType(n, t);
return n;
}
Node* UndefinedConstant() {
- Unique<HeapObject> unique = Unique<HeapObject>::CreateImmovable(
- isolate->factory()->undefined_value());
- return graph.NewNode(common.HeapConstant(unique));
+ Handle<HeapObject> value = isolate->factory()->undefined_value();
+ return graph.NewNode(common.HeapConstant(value));
}
Node* HeapConstant(Handle<HeapObject> constant) {
- Unique<HeapObject> unique =
- Unique<HeapObject>::CreateUninitialized(constant);
- return graph.NewNode(common.HeapConstant(unique));
+ return graph.NewNode(common.HeapConstant(constant));
}
Node* EmptyFrameState(Node* context) {
@@ -66,17 +82,22 @@
Node* locals = graph.NewNode(common.StateValues(0));
Node* stack = graph.NewNode(common.StateValues(0));
- Node* state_node =
- graph.NewNode(common.FrameState(JS_FRAME, BailoutId(0),
- OutputFrameStateCombine::Ignore()),
- parameters, locals, stack, context, UndefinedConstant());
+ Node* state_node = graph.NewNode(
+ common.FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(),
+ nullptr),
+ parameters, locals, stack, context, UndefinedConstant(), graph.start());
return state_node;
}
Node* reduce(Node* node) {
- JSGraph jsgraph(&graph, &common, &javascript, &machine);
- JSTypedLowering reducer(&jsgraph, main_zone());
+ JSGraph jsgraph(main_isolate(), &graph, &common, &javascript, &simplified,
+ &machine);
+ // TODO(titzer): mock the GraphReducer here for better unit testing.
+ GraphReducer graph_reducer(main_zone(), &graph);
+ JSTypedLowering reducer(&graph_reducer, &deps,
+ JSTypedLowering::kDeoptimizationEnabled, &jsgraph,
+ main_zone());
Reduction reduction = reducer.Reduce(node);
if (reduction.Changed()) return reduction.replacement();
return node;
@@ -93,14 +114,12 @@
Node* control() { return start(); }
- void CheckPureBinop(IrOpcode::Value expected, Node* node) {
+ void CheckBinop(IrOpcode::Value expected, Node* node) {
CHECK_EQ(expected, node->opcode());
- CHECK_EQ(2, node->InputCount()); // should not have context, effect, etc.
}
- void CheckPureBinop(const Operator* expected, Node* node) {
+ void CheckBinop(const Operator* expected, Node* node) {
CHECK_EQ(expected->opcode(), node->op()->opcode());
- CHECK_EQ(2, node->InputCount()); // should not have context, effect, etc.
}
Node* ReduceUnop(const Operator* op, Type* input_type) {
@@ -113,18 +132,48 @@
Node* Binop(const Operator* op, Node* left, Node* right) {
// JS binops also require context, effect, and control
- return graph.NewNode(op, left, right, context(), start(), control());
+ std::vector<Node*> inputs;
+ inputs.push_back(left);
+ inputs.push_back(right);
+ if (OperatorProperties::HasContextInput(op)) {
+ inputs.push_back(context());
+ }
+ for (int i = 0; i < OperatorProperties::GetFrameStateInputCount(op); i++) {
+ inputs.push_back(EmptyFrameState(context()));
+ }
+ if (op->EffectInputCount() > 0) {
+ inputs.push_back(start());
+ }
+ if (op->ControlInputCount() > 0) {
+ inputs.push_back(control());
+ }
+ return graph.NewNode(op, static_cast<int>(inputs.size()),
+ &(inputs.front()));
}
Node* Unop(const Operator* op, Node* input) {
// JS unops also require context, effect, and control
- return graph.NewNode(op, input, context(), start(), control());
+ if (OperatorProperties::GetFrameStateInputCount(op) > 0) {
+ CHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(op));
+ return graph.NewNode(op, input, context(), EmptyFrameState(context()),
+ start(), control());
+ } else {
+ return graph.NewNode(op, input, context(), start(), control());
+ }
}
Node* UseForEffect(Node* node) {
// TODO(titzer): use EffectPhi after fixing EffectCount
- return graph.NewNode(javascript.ToNumber(), node, context(), node,
- control());
+ if (OperatorProperties::GetFrameStateInputCount(javascript.ToNumber()) >
+ 0) {
+ CHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(
+ javascript.ToNumber()));
+ return graph.NewNode(javascript.ToNumber(), node, context(),
+ EmptyFrameState(context()), node, control());
+ } else {
+ return graph.NewNode(javascript.ToNumber(), node, context(), node,
+ control());
+ }
}
void CheckEffectInput(Node* effect, Node* use) {
@@ -155,9 +204,9 @@
CheckHandle(isolate->factory()->false_value(), result);
}
- void CheckHandle(Handle<Object> expected, Node* result) {
+ void CheckHandle(Handle<HeapObject> expected, Node* result) {
CHECK_EQ(IrOpcode::kHeapConstant, result->opcode());
- Handle<Object> value = OpParameter<Unique<Object> >(result).handle();
+ Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(result);
CHECK_EQ(*expected, *value);
}
};
@@ -166,24 +215,17 @@
Type::String()};
-static Type* kInt32Types[] = {
- Type::UnsignedSmall(), Type::NegativeSigned32(),
- Type::NonNegativeSigned32(), Type::SignedSmall(),
- Type::Signed32(), Type::Unsigned32(),
- Type::Integral32()};
+static Type* kInt32Types[] = {Type::UnsignedSmall(), Type::Negative32(),
+ Type::Unsigned31(), Type::SignedSmall(),
+ Type::Signed32(), Type::Unsigned32(),
+ Type::Integral32()};
static Type* kNumberTypes[] = {
- Type::UnsignedSmall(), Type::NegativeSigned32(),
- Type::NonNegativeSigned32(), Type::SignedSmall(),
- Type::Signed32(), Type::Unsigned32(),
- Type::Integral32(), Type::MinusZero(),
- Type::NaN(), Type::OrderedNumber(),
- Type::PlainNumber(), Type::Number()};
-
-
-static Type* kJSTypes[] = {Type::Undefined(), Type::Null(), Type::Boolean(),
- Type::Number(), Type::String(), Type::Object()};
+ Type::UnsignedSmall(), Type::Negative32(), Type::Unsigned31(),
+ Type::SignedSmall(), Type::Signed32(), Type::Unsigned32(),
+ Type::Integral32(), Type::MinusZero(), Type::NaN(),
+ Type::OrderedNumber(), Type::PlainNumber(), Type::Number()};
static Type* I32Type(bool is_signed) {
@@ -198,7 +240,7 @@
// TODO(turbofan): Lowering of StringAdd is disabled for now.
#if 0
-TEST(StringBinops) {
+TEST_WITH_STRONG(StringBinops) {
JSTypedLoweringTester R;
for (size_t i = 0; i < arraysize(kStringTypes); ++i) {
@@ -207,10 +249,10 @@
for (size_t j = 0; j < arraysize(kStringTypes); ++j) {
Node* p1 = R.Parameter(kStringTypes[j], 1);
- Node* add = R.Binop(R.javascript.Add(), p0, p1);
+ Node* add = R.Binop(R.javascript.Add(language_mode), p0, p1);
Node* r = R.reduce(add);
- R.CheckPureBinop(IrOpcode::kStringAdd, r);
+ R.CheckBinop(IrOpcode::kStringAdd, r);
CHECK_EQ(p0, r->InputAt(0));
CHECK_EQ(p1, r->InputAt(1));
}
@@ -219,29 +261,35 @@
#endif
-TEST(AddNumber1) {
+TEST_WITH_STRONG(AddNumber1) {
JSTypedLoweringTester R;
for (size_t i = 0; i < arraysize(kNumberTypes); ++i) {
Node* p0 = R.Parameter(kNumberTypes[i], 0);
Node* p1 = R.Parameter(kNumberTypes[i], 1);
- Node* add = R.Binop(R.javascript.Add(), p0, p1);
+ Node* add = R.Binop(
+ R.javascript.Add(language_mode, BinaryOperationHints::Any()), p0, p1);
Node* r = R.reduce(add);
- R.CheckPureBinop(IrOpcode::kNumberAdd, r);
+ R.CheckBinop(IrOpcode::kNumberAdd, r);
CHECK_EQ(p0, r->InputAt(0));
CHECK_EQ(p1, r->InputAt(1));
}
}
-TEST(NumberBinops) {
+TEST_WITH_STRONG(NumberBinops) {
JSTypedLoweringTester R;
const Operator* ops[] = {
- R.javascript.Add(), R.simplified.NumberAdd(),
- R.javascript.Subtract(), R.simplified.NumberSubtract(),
- R.javascript.Multiply(), R.simplified.NumberMultiply(),
- R.javascript.Divide(), R.simplified.NumberDivide(),
- R.javascript.Modulus(), R.simplified.NumberModulus(),
+ R.javascript.Add(language_mode, R.hints),
+ R.simplified.NumberAdd(),
+ R.javascript.Subtract(language_mode, R.hints),
+ R.simplified.NumberSubtract(),
+ R.javascript.Multiply(language_mode, R.hints),
+ R.simplified.NumberMultiply(),
+ R.javascript.Divide(language_mode, R.hints),
+ R.simplified.NumberDivide(),
+ R.javascript.Modulus(language_mode, R.hints),
+ R.simplified.NumberModulus(),
};
for (size_t i = 0; i < arraysize(kNumberTypes); ++i) {
@@ -254,7 +302,7 @@
Node* add = R.Binop(ops[k], p0, p1);
Node* r = R.reduce(add);
- R.CheckPureBinop(ops[k + 1], r);
+ R.CheckBinop(ops[k + 1], r);
CHECK_EQ(p0, r->InputAt(0));
CHECK_EQ(p1, r->InputAt(1));
}
@@ -264,8 +312,8 @@
static void CheckToI32(Node* old_input, Node* new_input, bool is_signed) {
- Type* old_type = NodeProperties::GetBounds(old_input).upper;
- Type* new_type = NodeProperties::GetBounds(new_input).upper;
+ Type* old_type = NodeProperties::GetType(old_input);
+ Type* new_type = NodeProperties::GetType(new_input);
Type* expected_type = I32Type(is_signed);
CHECK(new_type->Is(expected_type));
if (old_type->Is(expected_type)) {
@@ -281,21 +329,22 @@
// A helper class for testing lowering of bitwise shift operators.
class JSBitwiseShiftTypedLoweringTester : public JSTypedLoweringTester {
public:
+ explicit JSBitwiseShiftTypedLoweringTester(LanguageMode language_mode)
+ : JSTypedLoweringTester(), language_mode_(language_mode) {
+ int i = 0;
+ set(i++, javascript.ShiftLeft(language_mode_, hints), true);
+ set(i++, simplified.NumberShiftLeft(), false);
+ set(i++, javascript.ShiftRight(language_mode_, hints), true);
+ set(i++, simplified.NumberShiftRight(), false);
+ set(i++, javascript.ShiftRightLogical(language_mode_, hints), false);
+ set(i++, simplified.NumberShiftRightLogical(), false);
+ }
static const int kNumberOps = 6;
const Operator* ops[kNumberOps];
bool signedness[kNumberOps];
- JSBitwiseShiftTypedLoweringTester() {
- int i = 0;
- set(i++, javascript.ShiftLeft(), true);
- set(i++, machine.Word32Shl(), false);
- set(i++, javascript.ShiftRight(), true);
- set(i++, machine.Word32Sar(), false);
- set(i++, javascript.ShiftRightLogical(), false);
- set(i++, machine.Word32Shr(), false);
- }
-
private:
+ LanguageMode language_mode_;
void set(int idx, const Operator* op, bool s) {
ops[idx] = op;
signedness[idx] = s;
@@ -304,15 +353,14 @@
TEST(Int32BitwiseShifts) {
- JSBitwiseShiftTypedLoweringTester R;
+ JSBitwiseShiftTypedLoweringTester R(LanguageMode::SLOPPY);
- Type* types[] = {Type::SignedSmall(), Type::UnsignedSmall(),
- Type::NegativeSigned32(), Type::NonNegativeSigned32(),
- Type::Unsigned32(), Type::Signed32(),
- Type::MinusZero(), Type::NaN(),
- Type::Undefined(), Type::Null(),
- Type::Boolean(), Type::Number(),
- Type::PlainNumber(), Type::String()};
+ Type* types[] = {
+ Type::SignedSmall(), Type::UnsignedSmall(), Type::Negative32(),
+ Type::Unsigned31(), Type::Unsigned32(), Type::Signed32(),
+ Type::MinusZero(), Type::NaN(), Type::Undefined(),
+ Type::Null(), Type::Boolean(), Type::Number(),
+ Type::PlainNumber(), Type::String()};
for (size_t i = 0; i < arraysize(types); ++i) {
Node* p0 = R.Parameter(types[i], 0);
@@ -324,19 +372,12 @@
Node* add = R.Binop(R.ops[k], p0, p1);
Node* r = R.reduce(add);
- R.CheckPureBinop(R.ops[k + 1], r);
+ R.CheckBinop(R.ops[k + 1], r);
Node* r0 = r->InputAt(0);
Node* r1 = r->InputAt(1);
CheckToI32(p0, r0, R.signedness[k]);
-
- if (r1->opcode() == IrOpcode::kWord32And) {
- R.CheckPureBinop(IrOpcode::kWord32And, r1);
- CheckToI32(p1, r1->InputAt(0), R.signedness[k + 1]);
- R.CheckInt32Constant(0x1F, r1->InputAt(1));
- } else {
- CheckToI32(p1, r1, R.signedness[k]);
- }
+ CheckToI32(p1, r1, false);
}
}
}
@@ -346,21 +387,22 @@
// A helper class for testing lowering of bitwise operators.
class JSBitwiseTypedLoweringTester : public JSTypedLoweringTester {
public:
+ explicit JSBitwiseTypedLoweringTester(LanguageMode language_mode)
+ : JSTypedLoweringTester(), language_mode_(language_mode) {
+ int i = 0;
+ set(i++, javascript.BitwiseOr(language_mode_, hints), true);
+ set(i++, simplified.NumberBitwiseOr(), true);
+ set(i++, javascript.BitwiseXor(language_mode_, hints), true);
+ set(i++, simplified.NumberBitwiseXor(), true);
+ set(i++, javascript.BitwiseAnd(language_mode_, hints), true);
+ set(i++, simplified.NumberBitwiseAnd(), true);
+ }
static const int kNumberOps = 6;
const Operator* ops[kNumberOps];
bool signedness[kNumberOps];
- JSBitwiseTypedLoweringTester() {
- int i = 0;
- set(i++, javascript.BitwiseOr(), true);
- set(i++, machine.Word32Or(), true);
- set(i++, javascript.BitwiseXor(), true);
- set(i++, machine.Word32Xor(), true);
- set(i++, javascript.BitwiseAnd(), true);
- set(i++, machine.Word32And(), true);
- }
-
private:
+ LanguageMode language_mode_;
void set(int idx, const Operator* op, bool s) {
ops[idx] = op;
signedness[idx] = s;
@@ -369,7 +411,7 @@
TEST(Int32BitwiseBinops) {
- JSBitwiseTypedLoweringTester R;
+ JSBitwiseTypedLoweringTester R(LanguageMode::SLOPPY);
Type* types[] = {
Type::SignedSmall(), Type::UnsignedSmall(), Type::Unsigned32(),
@@ -388,7 +430,7 @@
Node* add = R.Binop(R.ops[k], p0, p1);
Node* r = R.reduce(add);
- R.CheckPureBinop(R.ops[k + 1], r);
+ R.CheckBinop(R.ops[k + 1], r);
CheckToI32(p0, r->InputAt(0), R.signedness[k]);
CheckToI32(p1, r->InputAt(1), R.signedness[k + 1]);
@@ -426,8 +468,9 @@
for (size_t i = 0; i < arraysize(types); i++) {
Node* n = R.Parameter(types[i]);
- Node* c = R.graph.NewNode(R.javascript.ToNumber(), n, R.context(),
- R.start(), R.start());
+ Node* c =
+ R.graph.NewNode(R.javascript.ToNumber(), n, R.context(),
+ R.EmptyFrameState(R.context()), R.start(), R.start());
Node* effect_use = R.UseForEffect(c);
Node* add = R.graph.NewNode(R.simplified.ReferenceEqual(Type::Any()), n, c);
@@ -462,7 +505,7 @@
// Note that either outcome below is correct. It only depends on whether
// the types of constants are eagerly computed or only computed by the
// typing pass.
- if (NodeProperties::GetBounds(n).upper->Is(Type::Number())) {
+ if (NodeProperties::GetType(n)->Is(Type::Number())) {
// If number constants are eagerly typed, then reduction should
// remove the ToNumber.
CHECK_EQ(n, r);
@@ -488,42 +531,6 @@
}
-TEST(JSToBoolean) {
- JSTypedLoweringTester R;
- const Operator* op = R.javascript.ToBoolean();
-
- { // ToBoolean(undefined)
- Node* r = R.ReduceUnop(op, Type::Undefined());
- R.CheckFalse(r);
- }
-
- { // ToBoolean(null)
- Node* r = R.ReduceUnop(op, Type::Null());
- R.CheckFalse(r);
- }
-
- { // ToBoolean(boolean)
- Node* r = R.ReduceUnop(op, Type::Boolean());
- CHECK_EQ(IrOpcode::kParameter, r->opcode());
- }
-
- { // ToBoolean(object)
- Node* r = R.ReduceUnop(op, Type::DetectableObject());
- R.CheckTrue(r);
- }
-
- { // ToBoolean(undetectable)
- Node* r = R.ReduceUnop(op, Type::Undetectable());
- R.CheckFalse(r);
- }
-
- { // ToBoolean(object)
- Node* r = R.ReduceUnop(op, Type::Object());
- CHECK_EQ(IrOpcode::kAnyToBoolean, r->opcode());
- }
-}
-
-
TEST(JSToString1) {
JSTypedLoweringTester R;
@@ -546,8 +553,7 @@
{ // ToString(boolean)
Node* r = R.ReduceUnop(op, Type::Boolean());
- // TODO(titzer): could be a branch
- CHECK_EQ(IrOpcode::kJSToString, r->opcode());
+ CHECK_EQ(IrOpcode::kSelect, r->opcode());
}
{ // ToString(number)
@@ -575,8 +581,9 @@
for (size_t i = 0; i < arraysize(types); i++) {
Node* n = R.Parameter(types[i]);
- Node* c = R.graph.NewNode(R.javascript.ToString(), n, R.context(),
- R.start(), R.start());
+ Node* c =
+ R.graph.NewNode(R.javascript.ToString(), n, R.context(),
+ R.EmptyFrameState(R.context()), R.start(), R.start());
Node* effect_use = R.UseForEffect(c);
Node* add = R.graph.NewNode(R.simplified.ReferenceEqual(Type::Any()), n, c);
@@ -596,14 +603,16 @@
}
-TEST(StringComparison) {
+TEST_WITH_STRONG(StringComparison) {
JSTypedLoweringTester R;
const Operator* ops[] = {
- R.javascript.LessThan(), R.simplified.StringLessThan(),
- R.javascript.LessThanOrEqual(), R.simplified.StringLessThanOrEqual(),
- R.javascript.GreaterThan(), R.simplified.StringLessThan(),
- R.javascript.GreaterThanOrEqual(), R.simplified.StringLessThanOrEqual()};
+ R.javascript.LessThan(language_mode), R.simplified.StringLessThan(),
+ R.javascript.LessThanOrEqual(language_mode),
+ R.simplified.StringLessThanOrEqual(),
+ R.javascript.GreaterThan(language_mode), R.simplified.StringLessThan(),
+ R.javascript.GreaterThanOrEqual(language_mode),
+ R.simplified.StringLessThanOrEqual()};
for (size_t i = 0; i < arraysize(kStringTypes); i++) {
Node* p0 = R.Parameter(kStringTypes[i], 0);
@@ -614,7 +623,7 @@
Node* cmp = R.Binop(ops[k], p0, p1);
Node* r = R.reduce(cmp);
- R.CheckPureBinop(ops[k + 1], r);
+ R.CheckBinop(ops[k + 1], r);
if (k >= 4) {
// GreaterThan and GreaterThanOrEqual commute the inputs
// and use the LessThan and LessThanOrEqual operators.
@@ -631,9 +640,9 @@
static void CheckIsConvertedToNumber(Node* val, Node* converted) {
- if (NodeProperties::GetBounds(val).upper->Is(Type::Number())) {
+ if (NodeProperties::GetType(val)->Is(Type::Number())) {
CHECK_EQ(val, converted);
- } else if (NodeProperties::GetBounds(val).upper->Is(Type::Boolean())) {
+ } else if (NodeProperties::GetType(val)->Is(Type::Boolean())) {
CHECK_EQ(IrOpcode::kBooleanToNumber, converted->opcode());
CHECK_EQ(val, converted->InputAt(0));
} else {
@@ -644,14 +653,16 @@
}
-TEST(NumberComparison) {
+TEST_WITH_STRONG(NumberComparison) {
JSTypedLoweringTester R;
const Operator* ops[] = {
- R.javascript.LessThan(), R.simplified.NumberLessThan(),
- R.javascript.LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
- R.javascript.GreaterThan(), R.simplified.NumberLessThan(),
- R.javascript.GreaterThanOrEqual(), R.simplified.NumberLessThanOrEqual()};
+ R.javascript.LessThan(language_mode), R.simplified.NumberLessThan(),
+ R.javascript.LessThanOrEqual(language_mode),
+ R.simplified.NumberLessThanOrEqual(),
+ R.javascript.GreaterThan(language_mode), R.simplified.NumberLessThan(),
+ R.javascript.GreaterThanOrEqual(language_mode),
+ R.simplified.NumberLessThanOrEqual()};
Node* const p0 = R.Parameter(Type::Number(), 0);
Node* const p1 = R.Parameter(Type::Number(), 1);
@@ -660,7 +671,7 @@
Node* cmp = R.Binop(ops[k], p0, p1);
Node* r = R.reduce(cmp);
- R.CheckPureBinop(ops[k + 1], r);
+ R.CheckBinop(ops[k + 1], r);
if (k >= 4) {
// GreaterThan and GreaterThanOrEqual commute the inputs
// and use the LessThan and LessThanOrEqual operators.
@@ -674,7 +685,7 @@
}
-TEST(MixedComparison1) {
+TEST_WITH_STRONG(MixedComparison1) {
JSTypedLoweringTester R;
Type* types[] = {Type::Number(), Type::String(),
@@ -686,18 +697,20 @@
for (size_t j = 0; j < arraysize(types); j++) {
Node* p1 = R.Parameter(types[j], 1);
{
- Node* cmp = R.Binop(R.javascript.LessThan(), p0, p1);
+ const Operator* less_than = R.javascript.LessThan(language_mode);
+ Node* cmp = R.Binop(less_than, p0, p1);
Node* r = R.reduce(cmp);
-
- if (!types[i]->Maybe(Type::String()) ||
- !types[j]->Maybe(Type::String())) {
- if (types[i]->Is(Type::String()) && types[j]->Is(Type::String())) {
- R.CheckPureBinop(R.simplified.StringLessThan(), r);
- } else {
- R.CheckPureBinop(R.simplified.NumberLessThan(), r);
- }
+ if (types[i]->Is(Type::String()) && types[j]->Is(Type::String())) {
+ R.CheckBinop(R.simplified.StringLessThan(), r);
+ } else if ((types[i]->Is(Type::Number()) &&
+ types[j]->Is(Type::Number())) ||
+ (!is_strong(language_mode) &&
+ (!types[i]->Maybe(Type::String()) ||
+ !types[j]->Maybe(Type::String())))) {
+ R.CheckBinop(R.simplified.NumberLessThan(), r);
} else {
- CHECK_EQ(cmp, r); // No reduction of mixed types.
+ // No reduction of mixed types.
+ CHECK_EQ(r->op(), less_than);
}
}
}
@@ -705,27 +718,7 @@
}
-TEST(UnaryNot) {
- JSTypedLoweringTester R;
- const Operator* opnot = R.javascript.UnaryNot();
-
- for (size_t i = 0; i < arraysize(kJSTypes); i++) {
- Node* orig = R.Unop(opnot, R.Parameter(kJSTypes[i]));
- Node* r = R.reduce(orig);
-
- if (r == orig && orig->opcode() == IrOpcode::kJSToBoolean) {
- // The original node was turned into a ToBoolean.
- CHECK_EQ(IrOpcode::kJSToBoolean, r->opcode());
- } else if (r->opcode() != IrOpcode::kHeapConstant) {
- CHECK_EQ(IrOpcode::kBooleanNot, r->opcode());
- }
- }
-}
-
-
-TEST(RemoveToNumberEffects) {
- FLAG_turbo_deoptimization = true;
-
+TEST_WITH_STRONG(RemoveToNumberEffects) {
JSTypedLoweringTester R;
Node* effect_use = NULL;
@@ -737,21 +730,27 @@
switch (i) {
case 0:
+ CHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(
+ R.javascript.ToNumber()));
effect_use = R.graph.NewNode(R.javascript.ToNumber(), p0, R.context(),
- ton, R.start());
+ frame_state, ton, R.start());
break;
case 1:
+ CHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(
+ R.javascript.ToNumber()));
effect_use = R.graph.NewNode(R.javascript.ToNumber(), ton, R.context(),
- ton, R.start());
+ frame_state, ton, R.start());
break;
case 2:
effect_use = R.graph.NewNode(R.common.EffectPhi(1), ton, R.start());
case 3:
- effect_use = R.graph.NewNode(R.javascript.Add(), ton, ton, R.context(),
+ effect_use = R.graph.NewNode(R.javascript.Add(language_mode, R.hints),
+ ton, ton, R.context(), frame_state,
frame_state, ton, R.start());
break;
case 4:
- effect_use = R.graph.NewNode(R.javascript.Add(), p0, p0, R.context(),
+ effect_use = R.graph.NewNode(R.javascript.Add(language_mode, R.hints),
+ p0, p0, R.context(), frame_state,
frame_state, ton, R.start());
break;
case 5:
@@ -777,7 +776,7 @@
}
}
- CHECK_EQ(NULL, effect_use); // should have done all cases above.
+ CHECK(!effect_use); // should have done all cases above.
}
@@ -845,20 +844,21 @@
Node* p1 = j == 1 ? l : r;
{
- Node* eq = strict ? R->graph.NewNode(R->javascript.StrictEqual(), p0, p1)
- : R->Binop(R->javascript.Equal(), p0, p1);
+ const Operator* op =
+ strict ? R->javascript.StrictEqual() : R->javascript.Equal();
+ Node* eq = R->Binop(op, p0, p1);
Node* r = R->reduce(eq);
- R->CheckPureBinop(expected, r);
+ R->CheckBinop(expected, r);
}
{
- Node* ne = strict
- ? R->graph.NewNode(R->javascript.StrictNotEqual(), p0, p1)
- : R->Binop(R->javascript.NotEqual(), p0, p1);
+ const Operator* op =
+ strict ? R->javascript.StrictNotEqual() : R->javascript.NotEqual();
+ Node* ne = R->Binop(op, p0, p1);
Node* n = R->reduce(ne);
CHECK_EQ(IrOpcode::kBooleanNot, n->opcode());
Node* r = n->InputAt(0);
- R->CheckPureBinop(expected, r);
+ R->CheckBinop(expected, r);
}
}
}
@@ -910,25 +910,33 @@
}
-TEST(RemovePureNumberBinopEffects) {
+TEST_WITH_STRONG(RemovePureNumberBinopEffects) {
JSTypedLoweringTester R;
const Operator* ops[] = {
- R.javascript.Equal(), R.simplified.NumberEqual(),
- R.javascript.Add(), R.simplified.NumberAdd(),
- R.javascript.Subtract(), R.simplified.NumberSubtract(),
- R.javascript.Multiply(), R.simplified.NumberMultiply(),
- R.javascript.Divide(), R.simplified.NumberDivide(),
- R.javascript.Modulus(), R.simplified.NumberModulus(),
- R.javascript.LessThan(), R.simplified.NumberLessThan(),
- R.javascript.LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
+ R.javascript.Equal(),
+ R.simplified.NumberEqual(),
+ R.javascript.Add(language_mode, R.hints),
+ R.simplified.NumberAdd(),
+ R.javascript.Subtract(language_mode, R.hints),
+ R.simplified.NumberSubtract(),
+ R.javascript.Multiply(language_mode, R.hints),
+ R.simplified.NumberMultiply(),
+ R.javascript.Divide(language_mode, R.hints),
+ R.simplified.NumberDivide(),
+ R.javascript.Modulus(language_mode, R.hints),
+ R.simplified.NumberModulus(),
+ R.javascript.LessThan(language_mode),
+ R.simplified.NumberLessThan(),
+ R.javascript.LessThanOrEqual(language_mode),
+ R.simplified.NumberLessThanOrEqual(),
};
for (size_t j = 0; j < arraysize(ops); j += 2) {
BinopEffectsTester B(ops[j], Type::Number(), Type::Number());
CHECK_EQ(ops[j + 1]->opcode(), B.result->op()->opcode());
- B.R.CheckPureBinop(B.result->opcode(), B.result);
+ B.R.CheckBinop(B.result->opcode(), B.result);
B.CheckNoOp(0);
B.CheckNoOp(1);
@@ -942,10 +950,12 @@
JSTypedLoweringTester R;
const Operator* ops[] = {
- R.javascript.Subtract(), R.simplified.NumberSubtract(),
- R.javascript.Multiply(), R.simplified.NumberMultiply(),
- R.javascript.Divide(), R.simplified.NumberDivide(),
- R.javascript.Modulus(), R.simplified.NumberModulus(),
+ R.javascript.Subtract(LanguageMode::SLOPPY, R.hints),
+ R.simplified.NumberSubtract(),
+ R.javascript.Multiply(LanguageMode::SLOPPY, R.hints),
+ R.simplified.NumberMultiply(),
+ R.javascript.Divide(LanguageMode::SLOPPY, R.hints),
+ R.simplified.NumberDivide(),
};
for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -968,11 +978,14 @@
JSTypedLoweringTester R;
const Operator* ops[] = {
- R.javascript.Add(), R.simplified.NumberAdd(),
- R.javascript.Subtract(), R.simplified.NumberSubtract(),
- R.javascript.Multiply(), R.simplified.NumberMultiply(),
- R.javascript.Divide(), R.simplified.NumberDivide(),
- R.javascript.Modulus(), R.simplified.NumberModulus(),
+ R.javascript.Add(LanguageMode::SLOPPY, R.hints),
+ R.simplified.NumberAdd(),
+ R.javascript.Subtract(LanguageMode::SLOPPY, R.hints),
+ R.simplified.NumberSubtract(),
+ R.javascript.Multiply(LanguageMode::SLOPPY, R.hints),
+ R.simplified.NumberMultiply(),
+ R.javascript.Divide(LanguageMode::SLOPPY, R.hints),
+ R.simplified.NumberDivide(),
};
for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -1007,8 +1020,10 @@
JSTypedLoweringTester R;
const Operator* ops[] = {
- R.javascript.GreaterThan(), R.simplified.NumberLessThan(),
- R.javascript.GreaterThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
+ R.javascript.GreaterThan(LanguageMode::SLOPPY),
+ R.simplified.NumberLessThan(),
+ R.javascript.GreaterThanOrEqual(LanguageMode::SLOPPY),
+ R.simplified.NumberLessThanOrEqual(),
};
for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -1055,14 +1070,13 @@
TEST(Int32BinopEffects) {
- JSBitwiseTypedLoweringTester R;
-
+ JSBitwiseTypedLoweringTester R(LanguageMode::SLOPPY);
for (int j = 0; j < R.kNumberOps; j += 2) {
bool signed_left = R.signedness[j], signed_right = R.signedness[j + 1];
BinopEffectsTester B(R.ops[j], I32Type(signed_left), I32Type(signed_right));
CHECK_EQ(R.ops[j + 1]->opcode(), B.result->op()->opcode());
- B.R.CheckPureBinop(B.result->opcode(), B.result);
+ B.R.CheckBinop(B.result->opcode(), B.result);
B.CheckNoOp(0);
B.CheckNoOp(1);
@@ -1075,7 +1089,7 @@
BinopEffectsTester B(R.ops[j], Type::Number(), Type::Number());
CHECK_EQ(R.ops[j + 1]->opcode(), B.result->op()->opcode());
- B.R.CheckPureBinop(B.result->opcode(), B.result);
+ B.R.CheckBinop(B.result->opcode(), B.result);
B.CheckConvertedInput(NumberToI32(signed_left), 0, false);
B.CheckConvertedInput(NumberToI32(signed_right), 1, false);
@@ -1087,7 +1101,7 @@
bool signed_left = R.signedness[j], signed_right = R.signedness[j + 1];
BinopEffectsTester B(R.ops[j], Type::Number(), Type::Primitive());
- B.R.CheckPureBinop(B.result->opcode(), B.result);
+ B.R.CheckBinop(B.result->opcode(), B.result);
Node* i0 = B.CheckConvertedInput(NumberToI32(signed_left), 0, false);
Node* i1 = B.CheckConvertedInput(NumberToI32(signed_right), 1, false);
@@ -1104,7 +1118,7 @@
bool signed_left = R.signedness[j], signed_right = R.signedness[j + 1];
BinopEffectsTester B(R.ops[j], Type::Primitive(), Type::Number());
- B.R.CheckPureBinop(B.result->opcode(), B.result);
+ B.R.CheckBinop(B.result->opcode(), B.result);
Node* i0 = B.CheckConvertedInput(NumberToI32(signed_left), 0, false);
Node* i1 = B.CheckConvertedInput(NumberToI32(signed_right), 1, false);
@@ -1121,7 +1135,7 @@
bool signed_left = R.signedness[j], signed_right = R.signedness[j + 1];
BinopEffectsTester B(R.ops[j], Type::Primitive(), Type::Primitive());
- B.R.CheckPureBinop(B.result->opcode(), B.result);
+ B.R.CheckBinop(B.result->opcode(), B.result);
Node* i0 = B.CheckConvertedInput(NumberToI32(signed_left), 0, false);
Node* i1 = B.CheckConvertedInput(NumberToI32(signed_right), 1, false);
@@ -1137,9 +1151,9 @@
}
-TEST(Int32AddNarrowing) {
+TEST_WITH_STRONG(Int32AddNarrowing) {
{
- JSBitwiseTypedLoweringTester R;
+ JSBitwiseTypedLoweringTester R(language_mode);
for (int o = 0; o < R.kNumberOps; o += 2) {
for (size_t i = 0; i < arraysize(kInt32Types); i++) {
@@ -1162,7 +1176,7 @@
}
}
{
- JSBitwiseShiftTypedLoweringTester R;
+ JSBitwiseShiftTypedLoweringTester R(language_mode);
for (int o = 0; o < R.kNumberOps; o += 2) {
for (size_t i = 0; i < arraysize(kInt32Types); i++) {
@@ -1185,7 +1199,7 @@
}
}
{
- JSBitwiseTypedLoweringTester R;
+ JSBitwiseTypedLoweringTester R(language_mode);
for (int o = 0; o < R.kNumberOps; o += 2) {
Node* n0 = R.Parameter(I32Type(R.signedness[o]));
@@ -1209,7 +1223,7 @@
}
-TEST(Int32Comparisons) {
+TEST_WITH_STRONG(Int32Comparisons) {
JSTypedLoweringTester R;
struct Entry {
@@ -1221,16 +1235,17 @@
};
Entry ops[] = {
- {R.javascript.LessThan(), R.machine.Uint32LessThan(),
+ {R.javascript.LessThan(language_mode), R.machine.Uint32LessThan(),
R.machine.Int32LessThan(), R.simplified.NumberLessThan(), false},
- {R.javascript.LessThanOrEqual(), R.machine.Uint32LessThanOrEqual(),
- R.machine.Int32LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
- false},
- {R.javascript.GreaterThan(), R.machine.Uint32LessThan(),
+ {R.javascript.LessThanOrEqual(language_mode),
+ R.machine.Uint32LessThanOrEqual(), R.machine.Int32LessThanOrEqual(),
+ R.simplified.NumberLessThanOrEqual(), false},
+ {R.javascript.GreaterThan(language_mode), R.machine.Uint32LessThan(),
R.machine.Int32LessThan(), R.simplified.NumberLessThan(), true},
- {R.javascript.GreaterThanOrEqual(), R.machine.Uint32LessThanOrEqual(),
- R.machine.Int32LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
- true}};
+ {R.javascript.GreaterThanOrEqual(language_mode),
+ R.machine.Uint32LessThanOrEqual(), R.machine.Int32LessThanOrEqual(),
+ R.simplified.NumberLessThanOrEqual(), true}
+ };
for (size_t o = 0; o < arraysize(ops); o++) {
for (size_t i = 0; i < arraysize(kNumberTypes); i++) {
@@ -1252,7 +1267,7 @@
} else {
expected = ops[o].num_op;
}
- R.CheckPureBinop(expected, r);
+ R.CheckBinop(expected, r);
if (ops[o].commute) {
CHECK_EQ(p1, r->InputAt(0));
CHECK_EQ(p0, r->InputAt(1));
@@ -1264,3 +1279,7 @@
}
}
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-jump-threading.cc b/test/cctest/compiler/test-jump-threading.cc
index 74bf43d..8c02012 100644
--- a/test/cctest/compiler/test-jump-threading.cc
+++ b/test/cctest/compiler/test-jump-threading.cc
@@ -2,25 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-#include "test/cctest/cctest.h"
-
#include "src/compiler/instruction.h"
#include "src/compiler/instruction-codes.h"
#include "src/compiler/jump-threading.h"
+#include "test/cctest/cctest.h"
namespace v8 {
namespace internal {
namespace compiler {
-typedef BasicBlock::RpoNumber RpoNumber;
-
class TestCode : public HandleAndZoneScope {
public:
TestCode()
: HandleAndZoneScope(),
blocks_(main_zone()),
- sequence_(main_zone(), &blocks_),
+ sequence_(main_isolate(), main_zone(), &blocks_),
rpo_number_(RpoNumber::FromInt(0)),
current_(NULL) {}
@@ -31,9 +27,9 @@
int Jump(int target) {
Start();
- InstructionOperand* ops[] = {UseRpo(target)};
- sequence_.AddInstruction(Instruction::New(main_zone(), kArchJmp, 0, NULL, 1,
- ops, 0, NULL)->MarkAsControl());
+ InstructionOperand ops[] = {UseRpo(target)};
+ sequence_.AddInstruction(
+ Instruction::New(main_zone(), kArchJmp, 0, NULL, 1, ops, 0, NULL));
int pos = static_cast<int>(sequence_.instructions().size() - 1);
End();
return pos;
@@ -44,11 +40,11 @@
}
int Branch(int ttarget, int ftarget) {
Start();
- InstructionOperand* ops[] = {UseRpo(ttarget), UseRpo(ftarget)};
+ InstructionOperand ops[] = {UseRpo(ttarget), UseRpo(ftarget)};
InstructionCode code = 119 | FlagsModeField::encode(kFlags_branch) |
FlagsConditionField::encode(kEqual);
- sequence_.AddInstruction(Instruction::New(main_zone(), code, 0, NULL, 2,
- ops, 0, NULL)->MarkAsControl());
+ sequence_.AddInstruction(
+ Instruction::New(main_zone(), code, 0, NULL, 2, ops, 0, NULL));
int pos = static_cast<int>(sequence_.instructions().size() - 1);
End();
return pos;
@@ -61,15 +57,18 @@
Start();
sequence_.AddInstruction(Instruction::New(main_zone(), kArchNop));
int index = static_cast<int>(sequence_.instructions().size()) - 1;
- sequence_.AddGapMove(index, RegisterOperand::Create(13, main_zone()),
- RegisterOperand::Create(13, main_zone()));
+ AddGapMove(index, AllocatedOperand(LocationOperand::REGISTER,
+ MachineRepresentation::kWord32, 13),
+ AllocatedOperand(LocationOperand::REGISTER,
+ MachineRepresentation::kWord32, 13));
}
void NonRedundantMoves() {
Start();
sequence_.AddInstruction(Instruction::New(main_zone(), kArchNop));
int index = static_cast<int>(sequence_.instructions().size()) - 1;
- sequence_.AddGapMove(index, ImmediateOperand::Create(11, main_zone()),
- RegisterOperand::Create(11, main_zone()));
+ AddGapMove(index, ConstantOperand(11),
+ AllocatedOperand(LocationOperand::REGISTER,
+ MachineRepresentation::kWord32, 11));
}
void Other() {
Start();
@@ -81,15 +80,14 @@
current_ = NULL;
rpo_number_ = RpoNumber::FromInt(rpo_number_.ToInt() + 1);
}
- InstructionOperand* UseRpo(int num) {
- int index = sequence_.AddImmediate(Constant(RpoNumber::FromInt(num)));
- return ImmediateOperand::Create(index, main_zone());
+ InstructionOperand UseRpo(int num) {
+ return sequence_.AddImmediate(Constant(RpoNumber::FromInt(num)));
}
void Start(bool deferred = false) {
if (current_ == NULL) {
- current_ = new (main_zone()) InstructionBlock(
- main_zone(), BasicBlock::Id::FromInt(rpo_number_.ToInt()),
- rpo_number_, RpoNumber::Invalid(), RpoNumber::Invalid(), deferred);
+ current_ = new (main_zone())
+ InstructionBlock(main_zone(), rpo_number_, RpoNumber::Invalid(),
+ RpoNumber::Invalid(), deferred, false);
blocks_.push_back(current_);
sequence_.StartBlock(rpo_number_);
}
@@ -98,11 +96,17 @@
CHECK(current_ == NULL);
Start(true);
}
+ void AddGapMove(int index, const InstructionOperand& from,
+ const InstructionOperand& to) {
+ sequence_.InstructionAt(index)
+ ->GetOrCreateParallelMove(Instruction::START, main_zone())
+ ->AddMove(from, to);
+ }
};
void VerifyForwarding(TestCode& code, int count, int* expected) {
- Zone local_zone(code.main_isolate());
+ Zone local_zone;
ZoneVector<RpoNumber> result(&local_zone);
JumpThreading::ComputeForwarding(&local_zone, result, &code.sequence_);
diff --git a/test/cctest/compiler/test-linkage.cc b/test/cctest/compiler/test-linkage.cc
index 117caf2..939b144 100644
--- a/test/cctest/compiler/test-linkage.cc
+++ b/test/cctest/compiler/test-linkage.cc
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
+#include "src/code-stubs.h"
#include "src/compiler.h"
+#include "src/parsing/parser.h"
#include "src/zone.h"
#include "src/compiler/common-operator.h"
@@ -17,10 +17,9 @@
#include "src/compiler/schedule.h"
#include "test/cctest/cctest.h"
-#if V8_TURBOFAN_TARGET
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
"dummy", 0, 0, 0, 0, 0, 0);
@@ -32,37 +31,37 @@
->NewStringFromUtf8(CStrVector(source))
.ToHandleChecked();
Handle<SharedFunctionInfo> shared_function = Compiler::CompileScript(
- source_code, Handle<String>(), 0, 0, false,
- Handle<Context>(isolate->native_context()), NULL, NULL,
- v8::ScriptCompiler::kNoCompileOptions, NOT_NATIVES_CODE);
+ source_code, Handle<String>(), 0, 0, v8::ScriptOriginOptions(),
+ Handle<Object>(), Handle<Context>(isolate->native_context()), NULL, NULL,
+ v8::ScriptCompiler::kNoCompileOptions, NOT_NATIVES_CODE, false);
return isolate->factory()->NewFunctionFromSharedFunctionInfo(
shared_function, isolate->native_context());
}
TEST(TestLinkageCreate) {
- InitializedHandleScope handles;
+ HandleAndZoneScope handles;
Handle<JSFunction> function = Compile("a + b");
- CompilationInfoWithZone info(function);
- Linkage linkage(info.zone(), &info);
+ ParseInfo parse_info(handles.main_zone(), function);
+ CompilationInfo info(&parse_info);
+ CallDescriptor* descriptor = Linkage::ComputeIncoming(info.zone(), &info);
+ CHECK(descriptor);
}
TEST(TestLinkageJSFunctionIncoming) {
- InitializedHandleScope handles;
-
const char* sources[] = {"(function() { })", "(function(a) { })",
"(function(a,b) { })", "(function(a,b,c) { })"};
for (int i = 0; i < 3; i++) {
- i::HandleScope handles(CcTest::i_isolate());
- Handle<JSFunction> function = v8::Utils::OpenHandle(
- *v8::Handle<v8::Function>::Cast(CompileRun(sources[i])));
- CompilationInfoWithZone info(function);
- Linkage linkage(info.zone(), &info);
-
- CallDescriptor* descriptor = linkage.GetIncomingDescriptor();
- CHECK_NE(NULL, descriptor);
+ HandleAndZoneScope handles;
+ Handle<JSFunction> function =
+ Handle<JSFunction>::cast(v8::Utils::OpenHandle(
+ *v8::Local<v8::Function>::Cast(CompileRun(sources[i]))));
+ ParseInfo parse_info(handles.main_zone(), function);
+ CompilationInfo info(&parse_info);
+ CallDescriptor* descriptor = Linkage::ComputeIncoming(info.zone(), &info);
+ CHECK(descriptor);
CHECK_EQ(1 + i, static_cast<int>(descriptor->JSParameterCount()));
CHECK_EQ(1, static_cast<int>(descriptor->ReturnCount()));
@@ -74,24 +73,28 @@
TEST(TestLinkageCodeStubIncoming) {
Isolate* isolate = CcTest::InitIsolateOnce();
- CompilationInfoWithZone info(static_cast<HydrogenCodeStub*>(NULL), isolate);
- Linkage linkage(info.zone(), &info);
- // TODO(titzer): test linkage creation with a bonafide code stub.
- // this just checks current behavior.
- CHECK_EQ(NULL, linkage.GetIncomingDescriptor());
+ Zone zone;
+ ToNumberStub stub(isolate);
+ CompilationInfo info(&stub, isolate, &zone);
+ CallDescriptor* descriptor = Linkage::ComputeIncoming(&zone, &info);
+ CHECK(descriptor);
+ CHECK_EQ(0, static_cast<int>(descriptor->StackParameterCount()));
+ CHECK_EQ(1, static_cast<int>(descriptor->ReturnCount()));
+ CHECK_EQ(Operator::kNoProperties, descriptor->properties());
+ CHECK_EQ(false, descriptor->IsJSFunctionCall());
}
TEST(TestLinkageJSCall) {
HandleAndZoneScope handles;
Handle<JSFunction> function = Compile("a + c");
- CompilationInfoWithZone info(function);
- Linkage linkage(info.zone(), &info);
+ ParseInfo parse_info(handles.main_zone(), function);
+ CompilationInfo info(&parse_info);
for (int i = 0; i < 32; i++) {
- CallDescriptor* descriptor =
- linkage.GetJSCallDescriptor(i, CallDescriptor::kNoFlags);
- CHECK_NE(NULL, descriptor);
+ CallDescriptor* descriptor = Linkage::GetJSCallDescriptor(
+ info.zone(), false, i, CallDescriptor::kNoFlags);
+ CHECK(descriptor);
CHECK_EQ(i, static_cast<int>(descriptor->JSParameterCount()));
CHECK_EQ(1, static_cast<int>(descriptor->ReturnCount()));
CHECK_EQ(Operator::kNoProperties, descriptor->properties());
@@ -109,5 +112,6 @@
// TODO(titzer): test linkage creation for outgoing stub calls.
}
-
-#endif // V8_TURBOFAN_TARGET
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-loop-analysis.cc b/test/cctest/compiler/test-loop-analysis.cc
index 9c11268..68bfc28 100644
--- a/test/cctest/compiler/test-loop-analysis.cc
+++ b/test/cctest/compiler/test-loop-analysis.cc
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "src/compiler/access-builder.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
@@ -20,14 +18,15 @@
#include "src/compiler/verifier.h"
#include "test/cctest/cctest.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
static Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0,
0, 1, 0, 0);
static Operator kIntLt(IrOpcode::kInt32LessThan, Operator::kPure,
"Int32LessThan", 2, 0, 0, 1, 0, 0);
-static Operator kStore(IrOpcode::kStore, Operator::kNoProperties, "Store", 0, 2,
+static Operator kStore(IrOpcode::kStore, Operator::kNoProperties, "Store", 1, 1,
1, 0, 1, 0);
static const int kNumLeafs = 4;
@@ -39,9 +38,9 @@
: isolate(main_isolate()),
common(main_zone()),
graph(main_zone()),
- jsgraph(&graph, &common, NULL, NULL),
+ jsgraph(main_isolate(), &graph, &common, nullptr, nullptr, nullptr),
start(graph.NewNode(common.Start(1))),
- end(graph.NewNode(common.End(), start)),
+ end(graph.NewNode(common.End(1), start)),
p0(graph.NewNode(common.Parameter(0), start)),
zero(jsgraph.Int32Constant(0)),
one(jsgraph.OneConstant()),
@@ -112,7 +111,8 @@
}
const Operator* op(int count, bool effect) {
- return effect ? common.EffectPhi(count) : common.Phi(kMachAnyTagged, count);
+ return effect ? common.EffectPhi(count)
+ : common.Phi(MachineRepresentation::kTagged, count);
}
Node* Return(Node* val, Node* effect, Node* control) {
@@ -127,7 +127,7 @@
OFStream os(stdout);
os << AsRPO(graph);
}
- Zone zone(isolate);
+ Zone zone;
loop_tree = LoopFinder::BuildLoopTree(&graph, &zone);
}
return loop_tree;
@@ -136,7 +136,7 @@
void CheckLoop(Node** header, int header_count, Node** body, int body_count) {
LoopTree* tree = GetLoopTree();
LoopTree::Loop* loop = tree->ContainingLoop(header[0]);
- CHECK_NE(NULL, loop);
+ CHECK(loop);
CHECK(header_count == static_cast<int>(loop->HeaderSize()));
for (int i = 0; i < header_count; i++) {
@@ -146,6 +146,7 @@
}
CHECK_EQ(body_count, static_cast<int>(loop->BodySize()));
+ // TODO(turbofan): O(n^2) set equivalence in this test.
for (int i = 0; i < body_count; i++) {
// Each body node should be contained in the loop.
CHECK(tree->Contains(loop, body[i]));
@@ -154,7 +155,6 @@
}
void CheckRangeContains(NodeRange range, Node* node) {
- // O(n) ftw.
CHECK_NE(range.end(), std::find(range.begin(), range.end(), node));
}
@@ -164,7 +164,7 @@
Node* header = chain[i];
// Each header should be in a loop.
LoopTree::Loop* loop = tree->ContainingLoop(header);
- CHECK_NE(NULL, loop);
+ CHECK(loop);
// Check parentage.
LoopTree::Loop* parent =
i == 0 ? NULL : tree->ContainingLoop(chain[i - 1]);
@@ -178,6 +178,8 @@
}
}
}
+
+ Zone* zone() { return main_zone(); }
};
@@ -232,8 +234,7 @@
Node* store;
explicit StoreLoop(While& w)
- : base(w.t.jsgraph.Int32Constant(12)),
- val(w.t.jsgraph.Int32Constant(13)) {
+ : base(w.t.graph.start()), val(w.t.jsgraph.Int32Constant(13)) {
Build(w);
}
@@ -241,7 +242,7 @@
void Build(While& w) {
phi = w.t.graph.NewNode(w.t.op(2, true), base, base, w.loop);
- store = w.t.graph.NewNode(&kStore, phi, val, w.loop);
+ store = w.t.graph.NewNode(&kStore, val, phi, w.loop);
phi->ReplaceInput(1, store);
}
};
@@ -262,6 +263,23 @@
}
+TEST(LaLoop1phi) {
+ // One loop with a simple phi.
+ LoopFinderTester t;
+ While w(t, t.p0);
+ Node* phi = t.graph.NewNode(t.common.Phi(MachineRepresentation::kTagged, 2),
+ t.zero, t.one, w.loop);
+ t.Return(phi, t.start, w.exit);
+
+ Node* chain[] = {w.loop};
+ t.CheckNestedLoops(chain, 1);
+
+ Node* header[] = {w.loop, phi};
+ Node* body[] = {w.branch, w.if_true};
+ t.CheckLoop(header, 2, body, 2);
+}
+
+
TEST(LaLoop1c) {
// One loop with a counter.
LoopFinderTester t;
@@ -451,6 +469,41 @@
}
+TEST(LaNestedLoop1x) {
+ // One loop nested in another.
+ LoopFinderTester t;
+ While w1(t, t.p0);
+ While w2(t, t.p0);
+ w2.nest(w1);
+
+ const Operator* op = t.common.Phi(MachineRepresentation::kWord32, 2);
+ Node* p1a = t.graph.NewNode(op, t.p0, t.p0, w1.loop);
+ Node* p1b = t.graph.NewNode(op, t.p0, t.p0, w1.loop);
+ Node* p2a = t.graph.NewNode(op, p1a, t.p0, w2.loop);
+ Node* p2b = t.graph.NewNode(op, p1b, t.p0, w2.loop);
+
+ p1a->ReplaceInput(1, p2b);
+ p1b->ReplaceInput(1, p2a);
+
+ p2a->ReplaceInput(1, p2b);
+ p2b->ReplaceInput(1, p2a);
+
+ t.Return(t.p0, t.start, w1.exit);
+
+ Node* chain[] = {w1.loop, w2.loop};
+ t.CheckNestedLoops(chain, 2);
+
+ Node* h1[] = {w1.loop, p1a, p1b};
+ Node* b1[] = {w1.branch, w1.if_true, w2.loop, p2a,
+ p2b, w2.branch, w2.if_true, w2.exit};
+ t.CheckLoop(h1, 3, b1, 8);
+
+ Node* h2[] = {w2.loop, p2a, p2b};
+ Node* b2[] = {w2.branch, w2.if_true};
+ t.CheckLoop(h2, 3, b2, 2);
+}
+
+
TEST(LaNestedLoop2) {
// Two loops nested in an outer loop.
LoopFinderTester t;
@@ -636,8 +689,8 @@
Node* p3 = t.jsgraph.Int32Constant(33);
Node* loop = t.graph.NewNode(t.common.Loop(2), t.start, t.start);
- Node* phi =
- t.graph.NewNode(t.common.Phi(kMachInt32, 2), t.one, p1, loop);
+ Node* phi = t.graph.NewNode(
+ t.common.Phi(MachineRepresentation::kWord32, 2), t.one, p1, loop);
Node* cond = t.graph.NewNode(&kIntAdd, phi, p2);
Node* branch = t.graph.NewNode(t.common.Branch(), cond, loop);
Node* if_true = t.graph.NewNode(t.common.IfTrue(), branch);
@@ -661,7 +714,7 @@
void RunEdgeMatrix2(int i) {
- DCHECK(i >= 0 && i < 5);
+ CHECK(i >= 0 && i < 5);
for (int j = 0; j < 5; j++) {
for (int k = 0; k < 5; k++) {
LoopFinderTester t;
@@ -672,8 +725,8 @@
// outer loop.
Node* loop1 = t.graph.NewNode(t.common.Loop(2), t.start, t.start);
- Node* phi1 =
- t.graph.NewNode(t.common.Phi(kMachInt32, 2), t.one, p1, loop1);
+ Node* phi1 = t.graph.NewNode(
+ t.common.Phi(MachineRepresentation::kWord32, 2), t.one, p1, loop1);
Node* cond1 = t.graph.NewNode(&kIntAdd, phi1, t.one);
Node* branch1 = t.graph.NewNode(t.common.Branch(), cond1, loop1);
Node* if_true1 = t.graph.NewNode(t.common.IfTrue(), branch1);
@@ -681,8 +734,8 @@
// inner loop.
Node* loop2 = t.graph.NewNode(t.common.Loop(2), if_true1, t.start);
- Node* phi2 =
- t.graph.NewNode(t.common.Phi(kMachInt32, 2), t.one, p2, loop2);
+ Node* phi2 = t.graph.NewNode(
+ t.common.Phi(MachineRepresentation::kWord32, 2), t.one, p2, loop2);
Node* cond2 = t.graph.NewNode(&kIntAdd, phi2, p3);
Node* branch2 = t.graph.NewNode(t.common.Branch(), cond2, loop2);
Node* if_true2 = t.graph.NewNode(t.common.IfTrue(), branch2);
@@ -748,7 +801,8 @@
// L1 depth = 0
Node* loop1 = t.graph.NewNode(t.common.Loop(2), t.start, t.start);
- Node* phi1 = t.graph.NewNode(t.common.Phi(kMachInt32, 2), p1a, p1c, loop1);
+ Node* phi1 = t.graph.NewNode(t.common.Phi(MachineRepresentation::kWord32, 2),
+ p1a, p1c, loop1);
Node* cond1 = t.graph.NewNode(&kIntAdd, phi1, p1b);
Node* branch1 = t.graph.NewNode(t.common.Branch(), cond1, loop1);
Node* if_true1 = t.graph.NewNode(t.common.IfTrue(), branch1);
@@ -756,7 +810,8 @@
// L2 depth = 1
Node* loop2 = t.graph.NewNode(t.common.Loop(2), if_true1, t.start);
- Node* phi2 = t.graph.NewNode(t.common.Phi(kMachInt32, 2), p2a, p2c, loop2);
+ Node* phi2 = t.graph.NewNode(t.common.Phi(MachineRepresentation::kWord32, 2),
+ p2a, p2c, loop2);
Node* cond2 = t.graph.NewNode(&kIntAdd, phi2, p2b);
Node* branch2 = t.graph.NewNode(t.common.Branch(), cond2, loop2);
Node* if_true2 = t.graph.NewNode(t.common.IfTrue(), branch2);
@@ -764,7 +819,8 @@
// L3 depth = 2
Node* loop3 = t.graph.NewNode(t.common.Loop(2), if_true2, t.start);
- Node* phi3 = t.graph.NewNode(t.common.Phi(kMachInt32, 2), p3a, p3c, loop3);
+ Node* phi3 = t.graph.NewNode(t.common.Phi(MachineRepresentation::kWord32, 2),
+ p3a, p3c, loop3);
Node* cond3 = t.graph.NewNode(&kIntAdd, phi3, p3b);
Node* branch3 = t.graph.NewNode(t.common.Branch(), cond3, loop3);
Node* if_true3 = t.graph.NewNode(t.common.IfTrue(), branch3);
@@ -822,7 +878,7 @@
// Runs all combinations with a fixed {i}.
-void RunEdgeMatrix3_i(int i) {
+static void RunEdgeMatrix3_i(int i) {
for (int a = 0; a < 1; a++) {
for (int b = 0; b < 1; b++) {
for (int c = 0; c < 4; c++) {
@@ -860,3 +916,108 @@
TEST(LaEdgeMatrix3_5) { RunEdgeMatrix3_i(5); }
+
+
+static void RunManyChainedLoops_i(int count) {
+ LoopFinderTester t;
+ Node** nodes = t.zone()->NewArray<Node*>(count * 4);
+ Node* k11 = t.jsgraph.Int32Constant(11);
+ Node* k12 = t.jsgraph.Int32Constant(12);
+ Node* last = t.start;
+
+ // Build loops.
+ for (int i = 0; i < count; i++) {
+ Node* loop = t.graph.NewNode(t.common.Loop(2), last, t.start);
+ Node* phi = t.graph.NewNode(t.common.Phi(MachineRepresentation::kWord32, 2),
+ k11, k12, loop);
+ Node* branch = t.graph.NewNode(t.common.Branch(), phi, loop);
+ Node* if_true = t.graph.NewNode(t.common.IfTrue(), branch);
+ Node* exit = t.graph.NewNode(t.common.IfFalse(), branch);
+ loop->ReplaceInput(1, if_true);
+
+ nodes[i * 4 + 0] = loop;
+ nodes[i * 4 + 1] = phi;
+ nodes[i * 4 + 2] = branch;
+ nodes[i * 4 + 3] = if_true;
+
+ last = exit;
+ }
+
+ Node* ret = t.graph.NewNode(t.common.Return(), t.p0, t.start, last);
+ t.graph.SetEnd(ret);
+
+ // Verify loops.
+ for (int i = 0; i < count; i++) {
+ t.CheckLoop(nodes + i * 4, 2, nodes + i * 4 + 2, 2);
+ }
+}
+
+
+static void RunManyNestedLoops_i(int count) {
+ LoopFinderTester t;
+ Node** nodes = t.zone()->NewArray<Node*>(count * 5);
+ Node* k11 = t.jsgraph.Int32Constant(11);
+ Node* k12 = t.jsgraph.Int32Constant(12);
+ Node* outer = nullptr;
+ Node* entry = t.start;
+
+ // Build loops.
+ for (int i = 0; i < count; i++) {
+ Node* loop = t.graph.NewNode(t.common.Loop(2), entry, t.start);
+ Node* phi = t.graph.NewNode(t.common.Phi(MachineRepresentation::kWord32, 2),
+ k11, k12, loop);
+ Node* branch = t.graph.NewNode(t.common.Branch(), phi, loop);
+ Node* if_true = t.graph.NewNode(t.common.IfTrue(), branch);
+ Node* exit = t.graph.NewNode(t.common.IfFalse(), branch);
+
+ nodes[i * 5 + 0] = exit; // outside
+ nodes[i * 5 + 1] = loop; // header
+ nodes[i * 5 + 2] = phi; // header
+ nodes[i * 5 + 3] = branch; // body
+ nodes[i * 5 + 4] = if_true; // body
+
+ if (outer != nullptr) {
+ // inner loop.
+ outer->ReplaceInput(1, exit);
+ } else {
+ // outer loop.
+ Node* ret = t.graph.NewNode(t.common.Return(), t.p0, t.start, exit);
+ t.graph.SetEnd(ret);
+ }
+ outer = loop;
+ entry = if_true;
+ }
+ outer->ReplaceInput(1, entry); // innermost loop.
+
+ // Verify loops.
+ for (int i = 0; i < count; i++) {
+ int k = i * 5;
+ t.CheckLoop(nodes + k + 1, 2, nodes + k + 3, count * 5 - k - 3);
+ }
+}
+
+
+TEST(LaManyChained_30) { RunManyChainedLoops_i(30); }
+TEST(LaManyChained_31) { RunManyChainedLoops_i(31); }
+TEST(LaManyChained_32) { RunManyChainedLoops_i(32); }
+TEST(LaManyChained_33) { RunManyChainedLoops_i(33); }
+TEST(LaManyChained_34) { RunManyChainedLoops_i(34); }
+TEST(LaManyChained_62) { RunManyChainedLoops_i(62); }
+TEST(LaManyChained_63) { RunManyChainedLoops_i(63); }
+TEST(LaManyChained_64) { RunManyChainedLoops_i(64); }
+
+TEST(LaManyNested_30) { RunManyNestedLoops_i(30); }
+TEST(LaManyNested_31) { RunManyNestedLoops_i(31); }
+TEST(LaManyNested_32) { RunManyNestedLoops_i(32); }
+TEST(LaManyNested_33) { RunManyNestedLoops_i(33); }
+TEST(LaManyNested_34) { RunManyNestedLoops_i(34); }
+TEST(LaManyNested_62) { RunManyNestedLoops_i(62); }
+TEST(LaManyNested_63) { RunManyNestedLoops_i(63); }
+TEST(LaManyNested_64) { RunManyNestedLoops_i(64); }
+
+
+TEST(LaPhiTangle) { LoopFinderTester t; }
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-loop-assignment-analysis.cc b/test/cctest/compiler/test-loop-assignment-analysis.cc
index aabd95b..69f5e15 100644
--- a/test/cctest/compiler/test-loop-assignment-analysis.cc
+++ b/test/cctest/compiler/test-loop-assignment-analysis.cc
@@ -2,14 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/ast/scopes.h"
#include "src/compiler/ast-loop-assignment-analyzer.h"
-#include "src/parser.h"
-#include "src/rewriter.h"
-#include "src/scopes.h"
+#include "src/parsing/parser.h"
+#include "src/parsing/rewriter.h"
#include "test/cctest/cctest.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
namespace {
const int kBufferSize = 1024;
@@ -29,28 +30,29 @@
void CheckLoopAssignedCount(int expected, const char* var_name) {
// TODO(titzer): don't scope analyze every single time.
- CompilationInfo info(function, main_zone());
+ ParseInfo parse_info(main_zone(), function);
+ CompilationInfo info(&parse_info);
- CHECK(Parser::Parse(&info));
- CHECK(Rewriter::Rewrite(&info));
- CHECK(Scope::Analyze(&info));
+ CHECK(Parser::ParseStatic(&parse_info));
+ CHECK(Rewriter::Rewrite(&parse_info));
+ CHECK(Scope::Analyze(&parse_info));
- Scope* scope = info.function()->scope();
- AstValueFactory* factory = info.ast_value_factory();
- CHECK_NE(NULL, scope);
+ Scope* scope = info.literal()->scope();
+ AstValueFactory* factory = parse_info.ast_value_factory();
+ CHECK(scope);
if (result == NULL) {
AstLoopAssignmentAnalyzer analyzer(main_zone(), &info);
result = analyzer.Analyze();
- CHECK_NE(NULL, result);
+ CHECK(result);
}
const i::AstRawString* name = factory->GetOneByteString(var_name);
i::Variable* var = scope->Lookup(name);
- CHECK_NE(NULL, var);
+ CHECK(var);
- if (var->location() == Variable::UNALLOCATED) {
+ if (var->location() == VariableLocation::UNALLOCATED) {
CHECK_EQ(0, expected);
} else {
CHECK(var->IsStackAllocated());
@@ -58,7 +60,7 @@
}
}
};
-}
+} // namespace
TEST(SimpleLoop1) {
@@ -292,3 +294,7 @@
f.CheckLoopAssignedCount(5, "z");
f.CheckLoopAssignedCount(0, "w");
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-machine-operator-reducer.cc b/test/cctest/compiler/test-machine-operator-reducer.cc
index 648e1b9..86888e9 100644
--- a/test/cctest/compiler/test-machine-operator-reducer.cc
+++ b/test/cctest/compiler/test-machine-operator-reducer.cc
@@ -2,19 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "test/cctest/cctest.h"
-
#include "src/base/utils/random-number-generator.h"
#include "src/codegen.h"
-#include "src/compiler/graph-inl.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/machine-operator-reducer.h"
#include "src/compiler/operator-properties.h"
#include "src/compiler/typer.h"
+#include "test/cctest/cctest.h"
#include "test/cctest/compiler/value-helper.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
template <typename T>
const Operator* NewConstantOperator(CommonOperatorBuilder* common,
@@ -57,12 +56,12 @@
: isolate(main_isolate()),
binop(NULL),
unop(NULL),
- machine(main_zone(), kMachPtr, flags),
+ machine(main_zone(), MachineType::PointerRepresentation(), flags),
common(main_zone()),
graph(main_zone()),
javascript(main_zone()),
- typer(&graph, MaybeHandle<Context>()),
- jsgraph(&graph, &common, &javascript, &machine),
+ typer(isolate, &graph),
+ jsgraph(isolate, &graph, &common, &javascript, nullptr, &machine),
maxuint32(Constant<int32_t>(kMaxUInt32)) {
Node* s = graph.NewNode(common.Start(num_parameters));
graph.SetStart(s);
@@ -100,7 +99,7 @@
// the {expect} value.
template <typename T>
void CheckFoldBinop(volatile T expect, Node* a, Node* b) {
- CHECK_NE(NULL, binop);
+ CHECK(binop);
Node* n = CreateBinopNode(a, b);
MachineOperatorReducer reducer(&jsgraph);
Reduction reduction = reducer.Reduce(n);
@@ -112,7 +111,7 @@
// Check that the reduction of this binop applied to {a} and {b} yields
// the {expect} node.
void CheckBinop(Node* expect, Node* a, Node* b) {
- CHECK_NE(NULL, binop);
+ CHECK(binop);
Node* n = CreateBinopNode(a, b);
MachineOperatorReducer reducer(&jsgraph);
Reduction reduction = reducer.Reduce(n);
@@ -124,7 +123,7 @@
// this binop applied to {left_expect} and {right_expect}.
void CheckFoldBinop(Node* left_expect, Node* right_expect, Node* left,
Node* right) {
- CHECK_NE(NULL, binop);
+ CHECK(binop);
Node* n = CreateBinopNode(left, right);
MachineOperatorReducer reducer(&jsgraph);
Reduction reduction = reducer.Reduce(n);
@@ -139,7 +138,7 @@
template <typename T>
void CheckFoldBinop(volatile T left_expect, const Operator* op_expect,
Node* right_expect, Node* left, Node* right) {
- CHECK_NE(NULL, binop);
+ CHECK(binop);
Node* n = CreateBinopNode(left, right);
MachineOperatorReducer reducer(&jsgraph);
Reduction r = reducer.Reduce(n);
@@ -154,7 +153,7 @@
template <typename T>
void CheckFoldBinop(Node* left_expect, const Operator* op_expect,
volatile T right_expect, Node* left, Node* right) {
- CHECK_NE(NULL, binop);
+ CHECK(binop);
Node* n = CreateBinopNode(left, right);
MachineOperatorReducer reducer(&jsgraph);
Reduction r = reducer.Reduce(n);
@@ -360,7 +359,7 @@
static void CheckJsShift(ReducerTester* R) {
- DCHECK(R->machine.Word32ShiftIsSafe());
+ CHECK(R->machine.Word32ShiftIsSafe());
Node* x = R->Parameter(0);
Node* y = R->Parameter(1);
@@ -704,7 +703,8 @@
Node* base = R.Constant<int32_t>(11);
Node* index = R.Constant<int32_t>(4);
- Node* load = R.graph.NewNode(R.machine.Load(kMachInt32), base, index);
+ Node* load = R.graph.NewNode(R.machine.Load(MachineType::Int32()), base,
+ index, R.graph.start(), R.graph.start());
{
MachineOperatorReducer reducer(&R.jsgraph);
@@ -713,9 +713,10 @@
}
{
- Node* store = R.graph.NewNode(
- R.machine.Store(StoreRepresentation(kMachInt32, kNoWriteBarrier)), base,
- index, load);
+ Node* store =
+ R.graph.NewNode(R.machine.Store(StoreRepresentation(
+ MachineRepresentation::kWord32, kNoWriteBarrier)),
+ base, index, load, load, R.graph.start());
MachineOperatorReducer reducer(&R.jsgraph);
Reduction reduction = reducer.Reduce(store);
CHECK(!reduction.Changed()); // stores should not be reduced.
@@ -723,133 +724,6 @@
}
-static void CheckNans(ReducerTester* R) {
- Node* x = R->Parameter();
- std::vector<double> nans = ValueHelper::nan_vector();
- for (std::vector<double>::const_iterator pl = nans.begin(); pl != nans.end();
- ++pl) {
- for (std::vector<double>::const_iterator pr = nans.begin();
- pr != nans.end(); ++pr) {
- Node* nan1 = R->Constant<double>(*pl);
- Node* nan2 = R->Constant<double>(*pr);
- R->CheckBinop(nan1, x, nan1); // x op NaN => NaN
- R->CheckBinop(nan1, nan1, x); // NaN op x => NaN
- R->CheckBinop(nan1, nan2, nan1); // NaN op NaN => NaN
- }
- }
-}
-
-
-TEST(ReduceFloat64Add) {
- ReducerTester R;
- R.binop = R.machine.Float64Add();
-
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- double x = *pl, y = *pr;
- R.CheckFoldBinop<double>(x + y, x, y);
- }
- }
-
- FOR_FLOAT64_INPUTS(i) {
- Double tmp(*i);
- if (!tmp.IsSpecial() || tmp.IsInfinite()) {
- // Don't check NaNs as they are reduced more.
- R.CheckPutConstantOnRight(*i);
- }
- }
-
- CheckNans(&R);
-}
-
-
-TEST(ReduceFloat64Sub) {
- ReducerTester R;
- R.binop = R.machine.Float64Sub();
-
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- double x = *pl, y = *pr;
- R.CheckFoldBinop<double>(x - y, x, y);
- }
- }
-
- Node* zero = R.Constant<double>(0.0);
- Node* x = R.Parameter();
-
- R.CheckBinop(x, x, zero); // x - 0.0 => x
-
- CheckNans(&R);
-}
-
-
-TEST(ReduceFloat64Mul) {
- ReducerTester R;
- R.binop = R.machine.Float64Mul();
-
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- double x = *pl, y = *pr;
- R.CheckFoldBinop<double>(x * y, x, y);
- }
- }
-
- double inf = V8_INFINITY;
- R.CheckPutConstantOnRight(-inf);
- R.CheckPutConstantOnRight(-0.1);
- R.CheckPutConstantOnRight(0.1);
- R.CheckPutConstantOnRight(inf);
-
- Node* x = R.Parameter();
- Node* one = R.Constant<double>(1.0);
-
- R.CheckBinop(x, x, one); // x * 1.0 => x
- R.CheckBinop(x, one, x); // 1.0 * x => x
-
- CheckNans(&R);
-}
-
-
-TEST(ReduceFloat64Div) {
- ReducerTester R;
- R.binop = R.machine.Float64Div();
-
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- double x = *pl, y = *pr;
- R.CheckFoldBinop<double>(x / y, x, y);
- }
- }
-
- Node* x = R.Parameter();
- Node* one = R.Constant<double>(1.0);
-
- R.CheckBinop(x, x, one); // x / 1.0 => x
-
- CheckNans(&R);
-}
-
-
-TEST(ReduceFloat64Mod) {
- ReducerTester R;
- R.binop = R.machine.Float64Mod();
-
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- double x = *pl, y = *pr;
- R.CheckFoldBinop<double>(modulo(x, y), x, y);
- }
- }
-
- Node* x = R.Parameter();
- Node* zero = R.Constant<double>(0.0);
-
- R.CheckFoldBinop<double>(v8::base::OS::nan_value(), x, zero);
-
- CheckNans(&R);
-}
-
-
// TODO(titzer): test MachineOperatorReducer for Word64And
// TODO(titzer): test MachineOperatorReducer for Word64Or
// TODO(titzer): test MachineOperatorReducer for Word64Xor
@@ -870,3 +744,12 @@
// TODO(titzer): test MachineOperatorReducer for ChangeInt32ToFloat64
// TODO(titzer): test MachineOperatorReducer for ChangeFloat64ToInt32
// TODO(titzer): test MachineOperatorReducer for Float64Compare
+// TODO(titzer): test MachineOperatorReducer for Float64Add
+// TODO(titzer): test MachineOperatorReducer for Float64Sub
+// TODO(titzer): test MachineOperatorReducer for Float64Mul
+// TODO(titzer): test MachineOperatorReducer for Float64Div
+// TODO(titzer): test MachineOperatorReducer for Float64Mod
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-multiple-return.cc b/test/cctest/compiler/test-multiple-return.cc
new file mode 100644
index 0000000..7c08238
--- /dev/null
+++ b/test/cctest/compiler/test-multiple-return.cc
@@ -0,0 +1,118 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cmath>
+#include <functional>
+#include <limits>
+
+#include "src/assembler.h"
+#include "src/base/bits.h"
+#include "src/base/utils/random-number-generator.h"
+#include "src/codegen.h"
+#include "src/compiler.h"
+#include "src/compiler/linkage.h"
+#include "src/macro-assembler.h"
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/codegen-tester.h"
+#include "test/cctest/compiler/value-helper.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+namespace {
+
+CallDescriptor* GetCallDescriptor(Zone* zone, int return_count,
+ int param_count) {
+ MachineSignature::Builder msig(zone, return_count, param_count);
+ LocationSignature::Builder locations(zone, return_count, param_count);
+ const RegisterConfiguration* config =
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
+
+ // Add return location(s).
+ CHECK(return_count <= config->num_allocatable_general_registers());
+ for (int i = 0; i < return_count; i++) {
+ msig.AddReturn(MachineType::Int32());
+ locations.AddReturn(
+ LinkageLocation::ForRegister(config->allocatable_general_codes()[i]));
+ }
+
+ // Add register and/or stack parameter(s).
+ CHECK(param_count <= config->num_allocatable_general_registers());
+ for (int i = 0; i < param_count; i++) {
+ msig.AddParam(MachineType::Int32());
+ locations.AddParam(
+ LinkageLocation::ForRegister(config->allocatable_general_codes()[i]));
+ }
+
+ const RegList kCalleeSaveRegisters = 0;
+ const RegList kCalleeSaveFPRegisters = 0;
+
+ // The target for WASM calls is always a code object.
+ MachineType target_type = MachineType::AnyTagged();
+ LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
+ return new (zone) CallDescriptor( // --
+ CallDescriptor::kCallCodeObject, // kind
+ target_type, // target MachineType
+ target_loc, // target location
+ msig.Build(), // machine_sig
+ locations.Build(), // location_sig
+ 0, // js_parameter_count
+ compiler::Operator::kNoProperties, // properties
+ kCalleeSaveRegisters, // callee-saved registers
+ kCalleeSaveFPRegisters, // callee-saved fp regs
+ CallDescriptor::kNoFlags, // flags
+ "c-call");
+}
+} // namespace
+
+
+TEST(ReturnThreeValues) {
+ Zone zone;
+ CallDescriptor* desc = GetCallDescriptor(&zone, 3, 2);
+ HandleAndZoneScope handles;
+ RawMachineAssembler m(handles.main_isolate(),
+ new (handles.main_zone()) Graph(handles.main_zone()),
+ desc, MachineType::PointerRepresentation(),
+ InstructionSelector::SupportedMachineOperatorFlags());
+
+ Node* p0 = m.Parameter(0);
+ Node* p1 = m.Parameter(1);
+ Node* add = m.Int32Add(p0, p1);
+ Node* sub = m.Int32Sub(p0, p1);
+ Node* mul = m.Int32Mul(p0, p1);
+ m.Return(add, sub, mul);
+
+ CompilationInfo info("testing", handles.main_isolate(), handles.main_zone());
+ Handle<Code> code =
+ Pipeline::GenerateCodeForTesting(&info, desc, m.graph(), m.Export());
+#ifdef ENABLE_DISASSEMBLER
+ if (FLAG_print_code) {
+ OFStream os(stdout);
+ code->Disassemble("three_value", os);
+ }
+#endif
+
+ RawMachineAssemblerTester<int32_t> mt;
+ Node* a = mt.Int32Constant(123);
+ Node* b = mt.Int32Constant(456);
+ Node* ret3 = mt.AddNode(mt.common()->Call(desc), mt.HeapConstant(code), a, b);
+ Node* x = mt.AddNode(mt.common()->Projection(0), ret3);
+ Node* y = mt.AddNode(mt.common()->Projection(1), ret3);
+ Node* z = mt.AddNode(mt.common()->Projection(2), ret3);
+ Node* ret = mt.Int32Add(mt.Int32Add(x, y), z);
+ mt.Return(ret);
+#ifdef ENABLE_DISASSEMBLER
+ Handle<Code> code2 = mt.GetCode();
+ if (FLAG_print_code) {
+ OFStream os(stdout);
+ code2->Disassemble("three_value_call", os);
+ }
+#endif
+ CHECK_EQ((123 + 456) + (123 - 456) + (123 * 456), mt.Call());
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-node-algorithm.cc b/test/cctest/compiler/test-node-algorithm.cc
deleted file mode 100644
index 842d182..0000000
--- a/test/cctest/compiler/test-node-algorithm.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <vector>
-
-#include "src/v8.h"
-
-#include "graph-tester.h"
-#include "src/compiler/common-operator.h"
-#include "src/compiler/graph.h"
-#include "src/compiler/graph-inl.h"
-#include "src/compiler/graph-visualizer.h"
-#include "src/compiler/node.h"
-#include "src/compiler/operator.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
- "dummy", 0, 0, 0, 1, 0, 0);
-
-class PreNodeVisitor : public NullNodeVisitor {
- public:
- void Pre(Node* node) {
- printf("NODE ID: %d\n", node->id());
- nodes_.push_back(node);
- }
- std::vector<Node*> nodes_;
-};
-
-
-class PostNodeVisitor : public NullNodeVisitor {
- public:
- void Post(Node* node) {
- printf("NODE ID: %d\n", node->id());
- nodes_.push_back(node);
- }
- std::vector<Node*> nodes_;
-};
-
-
-TEST(TestInputNodePreOrderVisitSimple) {
- GraphWithStartNodeTester graph;
- Node* n2 = graph.NewNode(&dummy_operator, graph.start());
- Node* n3 = graph.NewNode(&dummy_operator, n2);
- Node* n4 = graph.NewNode(&dummy_operator, n2, n3);
- Node* n5 = graph.NewNode(&dummy_operator, n4, n2);
- graph.SetEnd(n5);
-
- PreNodeVisitor node_visitor;
- graph.VisitNodeInputsFromEnd(&node_visitor);
- CHECK_EQ(5, static_cast<int>(node_visitor.nodes_.size()));
- CHECK(n5->id() == node_visitor.nodes_[0]->id());
- CHECK(n4->id() == node_visitor.nodes_[1]->id());
- CHECK(n2->id() == node_visitor.nodes_[2]->id());
- CHECK(graph.start()->id() == node_visitor.nodes_[3]->id());
- CHECK(n3->id() == node_visitor.nodes_[4]->id());
-}
-
-
-TEST(TestPrintNodeGraphToNodeGraphviz) {
- GraphWithStartNodeTester graph;
- Node* n2 = graph.NewNode(&dummy_operator, graph.start());
- Node* n3 = graph.NewNode(&dummy_operator, graph.start());
- Node* n4 = graph.NewNode(&dummy_operator, n2);
- Node* n5 = graph.NewNode(&dummy_operator, n2);
- Node* n6 = graph.NewNode(&dummy_operator, n3);
- Node* n7 = graph.NewNode(&dummy_operator, n3);
- Node* n8 = graph.NewNode(&dummy_operator, n5);
- Node* n9 = graph.NewNode(&dummy_operator, n5);
- Node* n10 = graph.NewNode(&dummy_operator, n9);
- Node* n11 = graph.NewNode(&dummy_operator, n9);
- Node* end_dependencies[6] = {n4, n8, n10, n11, n6, n7};
- Node* n12 = graph.NewNode(&dummy_operator, 6, end_dependencies);
- graph.SetEnd(n12);
-
- OFStream os(stdout);
- os << AsDOT(graph);
-}
diff --git a/test/cctest/compiler/test-node-cache.cc b/test/cctest/compiler/test-node-cache.cc
deleted file mode 100644
index a48adb9..0000000
--- a/test/cctest/compiler/test-node-cache.cc
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-
-#include "graph-tester.h"
-#include "src/compiler/common-operator.h"
-#include "src/compiler/node-cache.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-TEST(Int32Constant_back_to_back) {
- GraphTester graph;
- Int32NodeCache cache;
-
- for (int i = -2000000000; i < 2000000000; i += 3315177) {
- Node** pos = cache.Find(graph.zone(), i);
- CHECK_NE(NULL, pos);
- for (int j = 0; j < 3; j++) {
- Node** npos = cache.Find(graph.zone(), i);
- CHECK_EQ(pos, npos);
- }
- }
-}
-
-
-TEST(Int32Constant_five) {
- GraphTester graph;
- Int32NodeCache cache;
- CommonOperatorBuilder common(graph.zone());
-
- int32_t constants[] = {static_cast<int32_t>(0x80000000), -77, 0, 1, -1};
-
- Node* nodes[arraysize(constants)];
-
- for (size_t i = 0; i < arraysize(constants); i++) {
- int32_t k = constants[i];
- Node* node = graph.NewNode(common.Int32Constant(k));
- *cache.Find(graph.zone(), k) = nodes[i] = node;
- }
-
- for (size_t i = 0; i < arraysize(constants); i++) {
- int32_t k = constants[i];
- CHECK_EQ(nodes[i], *cache.Find(graph.zone(), k));
- }
-}
-
-
-TEST(Int32Constant_hits) {
- GraphTester graph;
- Int32NodeCache cache;
- const int32_t kSize = 1500;
- Node** nodes = graph.zone()->NewArray<Node*>(kSize);
- CommonOperatorBuilder common(graph.zone());
-
- for (int i = 0; i < kSize; i++) {
- int32_t v = i * -55;
- nodes[i] = graph.NewNode(common.Int32Constant(v));
- *cache.Find(graph.zone(), v) = nodes[i];
- }
-
- int hits = 0;
- for (int i = 0; i < kSize; i++) {
- int32_t v = i * -55;
- Node** pos = cache.Find(graph.zone(), v);
- if (*pos != NULL) {
- CHECK_EQ(nodes[i], *pos);
- hits++;
- }
- }
- CHECK_LT(4, hits);
-}
-
-
-TEST(Int64Constant_back_to_back) {
- GraphTester graph;
- Int64NodeCache cache;
-
- for (int64_t i = -2000000000; i < 2000000000; i += 3315177) {
- Node** pos = cache.Find(graph.zone(), i);
- CHECK_NE(NULL, pos);
- for (int j = 0; j < 3; j++) {
- Node** npos = cache.Find(graph.zone(), i);
- CHECK_EQ(pos, npos);
- }
- }
-}
-
-
-TEST(Int64Constant_hits) {
- GraphTester graph;
- Int64NodeCache cache;
- const int32_t kSize = 1500;
- Node** nodes = graph.zone()->NewArray<Node*>(kSize);
- CommonOperatorBuilder common(graph.zone());
-
- for (int i = 0; i < kSize; i++) {
- int64_t v = static_cast<int64_t>(i) * static_cast<int64_t>(5003001);
- nodes[i] = graph.NewNode(common.Int32Constant(i));
- *cache.Find(graph.zone(), v) = nodes[i];
- }
-
- int hits = 0;
- for (int i = 0; i < kSize; i++) {
- int64_t v = static_cast<int64_t>(i) * static_cast<int64_t>(5003001);
- Node** pos = cache.Find(graph.zone(), v);
- if (*pos != NULL) {
- CHECK_EQ(nodes[i], *pos);
- hits++;
- }
- }
- CHECK_LT(4, hits);
-}
-
-
-static bool Contains(NodeVector* nodes, Node* n) {
- for (size_t i = 0; i < nodes->size(); i++) {
- if (nodes->at(i) == n) return true;
- }
- return false;
-}
-
-
-TEST(NodeCache_GetCachedNodes_int32) {
- GraphTester graph;
- Int32NodeCache cache;
- CommonOperatorBuilder common(graph.zone());
-
- int32_t constants[] = {0, 311, 12, 13, 14, 555, -555, -44, -33, -22, -11,
- 0, 311, 311, 412, 412, 11, 11, -33, -33, -22, -11};
-
- for (size_t i = 0; i < arraysize(constants); i++) {
- int32_t k = constants[i];
- Node** pos = cache.Find(graph.zone(), k);
- if (*pos != NULL) {
- NodeVector nodes(graph.zone());
- cache.GetCachedNodes(&nodes);
- CHECK(Contains(&nodes, *pos));
- } else {
- NodeVector nodes(graph.zone());
- Node* n = graph.NewNode(common.Int32Constant(k));
- *pos = n;
- cache.GetCachedNodes(&nodes);
- CHECK(Contains(&nodes, n));
- }
- }
-}
-
-
-TEST(NodeCache_GetCachedNodes_int64) {
- GraphTester graph;
- Int64NodeCache cache;
- CommonOperatorBuilder common(graph.zone());
-
- int64_t constants[] = {0, 311, 12, 13, 14, 555, -555, -44, -33, -22, -11,
- 0, 311, 311, 412, 412, 11, 11, -33, -33, -22, -11};
-
- for (size_t i = 0; i < arraysize(constants); i++) {
- int64_t k = constants[i];
- Node** pos = cache.Find(graph.zone(), k);
- if (*pos != NULL) {
- NodeVector nodes(graph.zone());
- cache.GetCachedNodes(&nodes);
- CHECK(Contains(&nodes, *pos));
- } else {
- NodeVector nodes(graph.zone());
- Node* n = graph.NewNode(common.Int64Constant(k));
- *pos = n;
- cache.GetCachedNodes(&nodes);
- CHECK(Contains(&nodes, n));
- }
- }
-}
diff --git a/test/cctest/compiler/test-node.cc b/test/cctest/compiler/test-node.cc
index eafabd3..de1c2c0 100644
--- a/test/cctest/compiler/test-node.cc
+++ b/test/cctest/compiler/test-node.cc
@@ -4,242 +4,233 @@
#include <functional>
-#include "src/v8.h"
-
-#include "graph-tester.h"
+#include "src/compiler/graph.h"
#include "src/compiler/node.h"
#include "src/compiler/operator.h"
+#include "test/cctest/cctest.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
-static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
- "dummy", 0, 0, 0, 1, 0, 0);
+#define NONE reinterpret_cast<Node*>(1)
-TEST(NodeAllocation) {
- GraphTester graph;
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
- CHECK(n2->id() != n1->id());
-}
+static Operator dummy_operator0(IrOpcode::kParameter, Operator::kNoWrite,
+ "dummy", 0, 0, 0, 1, 0, 0);
+static Operator dummy_operator1(IrOpcode::kParameter, Operator::kNoWrite,
+ "dummy", 1, 0, 0, 1, 0, 0);
+static Operator dummy_operator2(IrOpcode::kParameter, Operator::kNoWrite,
+ "dummy", 2, 0, 0, 1, 0, 0);
+static Operator dummy_operator3(IrOpcode::kParameter, Operator::kNoWrite,
+ "dummy", 3, 0, 0, 1, 0, 0);
+
+#define CHECK_USES(node, ...) \
+ do { \
+ Node* __array[] = {__VA_ARGS__}; \
+ int __size = \
+ __array[0] != NONE ? static_cast<int>(arraysize(__array)) : 0; \
+ CheckUseChain(node, __array, __size); \
+ } while (false)
-TEST(NodeWithOpcode) {
- GraphTester graph;
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
- CHECK(n1->op() == &dummy_operator);
- CHECK(n2->op() == &dummy_operator);
-}
+namespace {
+
+typedef std::multiset<Node*, std::less<Node*>> NodeMSet;
-TEST(NodeInputs1) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- CHECK_EQ(1, n2->InputCount());
- CHECK(n0 == n2->InputAt(0));
-}
-
-
-TEST(NodeInputs2) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
- CHECK_EQ(2, n2->InputCount());
- CHECK(n0 == n2->InputAt(0));
- CHECK(n1 == n2->InputAt(1));
-}
-
-
-TEST(NodeInputs3) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1, n1);
- CHECK_EQ(3, n2->InputCount());
- CHECK(n0 == n2->InputAt(0));
- CHECK(n1 == n2->InputAt(1));
- CHECK(n1 == n2->InputAt(2));
-}
-
-
-TEST(NodeInputIteratorEmpty) {
- GraphTester graph;
- Node* n1 = graph.NewNode(&dummy_operator);
- Node::Inputs::iterator i(n1->inputs().begin());
- int input_count = 0;
- for (; i != n1->inputs().end(); ++i) {
- input_count++;
+void CheckUseChain(Node* node, Node** uses, int use_count) {
+ // Check ownership.
+ if (use_count == 1) CHECK(node->OwnedBy(uses[0]));
+ if (use_count > 1) {
+ for (int i = 0; i < use_count; i++) {
+ CHECK(!node->OwnedBy(uses[i]));
+ }
}
- CHECK_EQ(0, input_count);
-}
+ // Check the self-reported use count.
+ CHECK_EQ(use_count, node->UseCount());
-TEST(NodeInputIteratorOne) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node::Inputs::iterator i(n1->inputs().begin());
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(n0, *i);
- ++i;
- CHECK(n1->inputs().end() == i);
-}
-
-
-TEST(NodeUseIteratorEmpty) {
- GraphTester graph;
- Node* n1 = graph.NewNode(&dummy_operator);
- int use_count = 0;
- for (Edge const edge : n1->use_edges()) {
- USE(edge);
- use_count++;
+ // Build the expectation set.
+ NodeMSet expect_set;
+ for (int i = 0; i < use_count; i++) {
+ expect_set.insert(uses[i]);
}
- CHECK_EQ(0, use_count);
+
+ {
+ // Check that iterating over the uses gives the right counts.
+ NodeMSet use_set;
+ for (auto use : node->uses()) {
+ use_set.insert(use);
+ }
+ CHECK(expect_set == use_set);
+ }
+
+ {
+ // Check that iterating over the use edges gives the right counts,
+ // input indices, from(), and to() pointers.
+ NodeMSet use_set;
+ for (auto edge : node->use_edges()) {
+ CHECK_EQ(node, edge.to());
+ CHECK_EQ(node, edge.from()->InputAt(edge.index()));
+ use_set.insert(edge.from());
+ }
+ CHECK(expect_set == use_set);
+ }
+
+ {
+ // Check the use nodes actually have the node as inputs.
+ for (Node* use : node->uses()) {
+ size_t count = 0;
+ for (Node* input : use->inputs()) {
+ if (input == node) count++;
+ }
+ CHECK_EQ(count, expect_set.count(use));
+ }
+ }
}
-TEST(NodeUseIteratorOne) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node::Uses::iterator i(n0->uses().begin());
- CHECK_EQ(n1, *i);
- ++i;
- CHECK(n0->uses().end() == i);
+void CheckInputs(Node* node, Node** inputs, int input_count) {
+ CHECK_EQ(input_count, node->InputCount());
+ // Check InputAt().
+ for (int i = 0; i < static_cast<int>(input_count); i++) {
+ CHECK_EQ(inputs[i], node->InputAt(i));
+ }
+
+ // Check input iterator.
+ int index = 0;
+ for (Node* input : node->inputs()) {
+ CHECK_EQ(inputs[index], input);
+ index++;
+ }
+
+ // Check use lists of inputs.
+ for (int i = 0; i < static_cast<int>(input_count); i++) {
+ Node* input = inputs[i];
+ if (!input) continue; // skip null inputs
+ bool found = false;
+ // Check regular use list.
+ for (Node* use : input->uses()) {
+ if (use == node) {
+ found = true;
+ break;
+ }
+ }
+ CHECK(found);
+ int count = 0;
+ // Check use edge list.
+ for (auto edge : input->use_edges()) {
+ if (edge.from() == node && edge.to() == input && edge.index() == i) {
+ count++;
+ }
+ }
+ CHECK_EQ(1, count);
+ }
}
+} // namespace
-TEST(NodeUseIteratorReplaceNoUses) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
- Node* n3 = graph.NewNode(&dummy_operator, n2);
- n0->ReplaceUses(n1);
- CHECK(n0->uses().begin() == n0->uses().end());
- n0->ReplaceUses(n2);
- CHECK(n0->uses().begin() == n0->uses().end());
- USE(n3);
-}
+
+#define CHECK_INPUTS(node, ...) \
+ do { \
+ Node* __array[] = {__VA_ARGS__}; \
+ int __size = \
+ __array[0] != NONE ? static_cast<int>(arraysize(__array)) : 0; \
+ CheckInputs(node, __array, __size); \
+ } while (false)
TEST(NodeUseIteratorReplaceUses) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- Node* n3 = graph.NewNode(&dummy_operator);
- Node::Uses::iterator i1(n0->uses().begin());
- CHECK_EQ(n1, *i1);
- ++i1;
- CHECK_EQ(n2, *i1);
+ Zone zone;
+ Graph graph(&zone);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator1, n0);
+ Node* n2 = graph.NewNode(&dummy_operator1, n0);
+ Node* n3 = graph.NewNode(&dummy_operator0);
+
+ CHECK_USES(n0, n1, n2);
+
+ CHECK_INPUTS(n1, n0);
+ CHECK_INPUTS(n2, n0);
+
n0->ReplaceUses(n3);
- Node::Uses::iterator i2(n3->uses().begin());
- CHECK_EQ(n1, *i2);
- ++i2;
- CHECK_EQ(n2, *i2);
- Node::Inputs::iterator i3(n1->inputs().begin());
- CHECK_EQ(n3, *i3);
- ++i3;
- CHECK(n1->inputs().end() == i3);
- Node::Inputs::iterator i4(n2->inputs().begin());
- CHECK_EQ(n3, *i4);
- ++i4;
- CHECK(n2->inputs().end() == i4);
+
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n2, NONE);
+ CHECK_USES(n3, n1, n2);
+
+ CHECK_INPUTS(n1, n3);
+ CHECK_INPUTS(n2, n3);
}
TEST(NodeUseIteratorReplaceUsesSelf) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n3 = graph.NewNode(&dummy_operator);
+ Zone zone;
+ Graph graph(&zone);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator1, n0);
+
+ CHECK_USES(n0, n1);
+ CHECK_USES(n1, NONE);
n1->ReplaceInput(0, n1); // Create self-reference.
- Node::Uses::iterator i1(n1->uses().begin());
- CHECK_EQ(n1, *i1);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, n1);
- n1->ReplaceUses(n3);
+ Node* n2 = graph.NewNode(&dummy_operator0);
- CHECK(n1->uses().begin() == n1->uses().end());
+ n1->ReplaceUses(n2);
- Node::Uses::iterator i2(n3->uses().begin());
- CHECK_EQ(n1, *i2);
- ++i2;
- CHECK(n1->uses().end() == i2);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n2, n1);
}
TEST(ReplaceInput) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
- Node* n3 = graph.NewNode(&dummy_operator, n0, n1, n2);
- Node::Inputs::iterator i1(n3->inputs().begin());
- CHECK(n0 == *i1);
- CHECK_EQ(n0, n3->InputAt(0));
- ++i1;
- CHECK_EQ(n1, *i1);
- CHECK_EQ(n1, n3->InputAt(1));
- ++i1;
- CHECK_EQ(n2, *i1);
- CHECK_EQ(n2, n3->InputAt(2));
- ++i1;
- CHECK(i1 == n3->inputs().end());
+ Zone zone;
+ Graph graph(&zone);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator0);
+ Node* n3 = graph.NewNode(&dummy_operator3, n0, n1, n2);
+ Node* n4 = graph.NewNode(&dummy_operator0);
- Node::Uses::iterator i2(n1->uses().begin());
- CHECK_EQ(n3, *i2);
- ++i2;
- CHECK(i2 == n1->uses().end());
+ CHECK_USES(n0, n3);
+ CHECK_USES(n1, n3);
+ CHECK_USES(n2, n3);
+ CHECK_USES(n3, NONE);
+ CHECK_USES(n4, NONE);
- Node* n4 = graph.NewNode(&dummy_operator);
- Node::Uses::iterator i3(n4->uses().begin());
- CHECK(i3 == n4->uses().end());
+ CHECK_INPUTS(n3, n0, n1, n2);
n3->ReplaceInput(1, n4);
- Node::Uses::iterator i4(n1->uses().begin());
- CHECK(i4 == n1->uses().end());
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n4, n3);
- Node::Uses::iterator i5(n4->uses().begin());
- CHECK_EQ(n3, *i5);
- ++i5;
- CHECK(i5 == n4->uses().end());
-
- Node::Inputs::iterator i6(n3->inputs().begin());
- CHECK(n0 == *i6);
- CHECK_EQ(n0, n3->InputAt(0));
- ++i6;
- CHECK_EQ(n4, *i6);
- CHECK_EQ(n4, n3->InputAt(1));
- ++i6;
- CHECK_EQ(n2, *i6);
- CHECK_EQ(n2, n3->InputAt(2));
- ++i6;
- CHECK(i6 == n3->inputs().end());
+ CHECK_INPUTS(n3, n0, n4, n2);
}
TEST(OwnedBy) {
- GraphTester graph;
+ Zone zone;
+ Graph graph(&zone);
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator0);
CHECK(!n0->OwnedBy(n1));
CHECK(!n1->OwnedBy(n0));
- Node* n2 = graph.NewNode(&dummy_operator, n0);
+ Node* n2 = graph.NewNode(&dummy_operator1, n0);
CHECK(n0->OwnedBy(n2));
CHECK(!n2->OwnedBy(n0));
- Node* n3 = graph.NewNode(&dummy_operator, n0);
+ Node* n3 = graph.NewNode(&dummy_operator1, n0);
CHECK(!n0->OwnedBy(n2));
CHECK(!n0->OwnedBy(n3));
CHECK(!n2->OwnedBy(n0));
@@ -247,11 +238,11 @@
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator1, n0);
CHECK(n0->OwnedBy(n1));
CHECK(!n1->OwnedBy(n0));
- Node* n2 = graph.NewNode(&dummy_operator, n0);
+ Node* n2 = graph.NewNode(&dummy_operator1, n0);
CHECK(!n0->OwnedBy(n1));
CHECK(!n0->OwnedBy(n2));
CHECK(!n1->OwnedBy(n0));
@@ -259,7 +250,7 @@
CHECK(!n2->OwnedBy(n0));
CHECK(!n2->OwnedBy(n1));
- Node* n3 = graph.NewNode(&dummy_operator);
+ Node* n3 = graph.NewNode(&dummy_operator0);
n2->ReplaceInput(0, n3);
CHECK(n0->OwnedBy(n1));
@@ -275,276 +266,197 @@
TEST(Uses) {
- GraphTester graph;
+ Zone zone;
+ Graph graph(&zone);
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- CHECK_EQ(1, n0->UseCount());
- printf("A: %d vs %d\n", n0->UseAt(0)->id(), n1->id());
- CHECK(n0->UseAt(0) == n1);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- CHECK_EQ(2, n0->UseCount());
- printf("B: %d vs %d\n", n0->UseAt(1)->id(), n2->id());
- CHECK(n0->UseAt(1) == n2);
- Node* n3 = graph.NewNode(&dummy_operator, n0);
- CHECK_EQ(3, n0->UseCount());
- CHECK(n0->UseAt(2) == n3);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator1, n0);
+
+ CHECK_USES(n0, n1);
+ CHECK_USES(n1, NONE);
+
+ Node* n2 = graph.NewNode(&dummy_operator1, n0);
+
+ CHECK_USES(n0, n1, n2);
+ CHECK_USES(n2, NONE);
+
+ Node* n3 = graph.NewNode(&dummy_operator1, n0);
+
+ CHECK_USES(n0, n1, n2, n3);
+ CHECK_USES(n3, NONE);
}
TEST(Inputs) {
- GraphTester graph;
+ Zone zone;
+ Graph graph(&zone);
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- Node* n3 = graph.NewNode(&dummy_operator, n0, n1, n2);
- CHECK_EQ(3, n3->InputCount());
- CHECK(n3->InputAt(0) == n0);
- CHECK(n3->InputAt(1) == n1);
- CHECK(n3->InputAt(2) == n2);
- Node* n4 = graph.NewNode(&dummy_operator, n0, n1, n2);
- n3->AppendInput(graph.zone(), n4);
- CHECK_EQ(4, n3->InputCount());
- CHECK(n3->InputAt(0) == n0);
- CHECK(n3->InputAt(1) == n1);
- CHECK(n3->InputAt(2) == n2);
- CHECK(n3->InputAt(3) == n4);
- Node* n5 = graph.NewNode(&dummy_operator, n4);
- n3->AppendInput(graph.zone(), n4);
- CHECK_EQ(5, n3->InputCount());
- CHECK(n3->InputAt(0) == n0);
- CHECK(n3->InputAt(1) == n1);
- CHECK(n3->InputAt(2) == n2);
- CHECK(n3->InputAt(3) == n4);
- CHECK(n3->InputAt(4) == n4);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator1, n0);
+ Node* n2 = graph.NewNode(&dummy_operator1, n0);
+ Node* n3 = graph.NewNode(&dummy_operator3, n0, n1, n2);
- // Make sure uses have been hooked op correctly.
- Node::Uses uses(n4->uses());
- Node::Uses::iterator current = uses.begin();
- CHECK(current != uses.end());
- CHECK(*current == n3);
- ++current;
- CHECK(current != uses.end());
- CHECK(*current == n5);
- ++current;
- CHECK(current != uses.end());
- CHECK(*current == n3);
- ++current;
- CHECK(current == uses.end());
+ CHECK_INPUTS(n3, n0, n1, n2);
+
+ Node* n4 = graph.NewNode(&dummy_operator3, n0, n1, n2);
+ n3->AppendInput(graph.zone(), n4);
+
+ CHECK_INPUTS(n3, n0, n1, n2, n4);
+ CHECK_USES(n4, n3);
+
+ n3->AppendInput(graph.zone(), n4);
+
+ CHECK_INPUTS(n3, n0, n1, n2, n4, n4);
+ CHECK_USES(n4, n3, n3);
+
+ Node* n5 = graph.NewNode(&dummy_operator1, n4);
+
+ CHECK_USES(n4, n3, n3, n5);
}
TEST(RemoveInput) {
- GraphTester graph;
+ Zone zone;
+ Graph graph(&zone);
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator1, n0);
+ Node* n2 = graph.NewNode(&dummy_operator2, n0, n1);
+
+ CHECK_INPUTS(n0, NONE);
+ CHECK_INPUTS(n1, n0);
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n0, n1, n2);
n1->RemoveInput(0);
- CHECK_EQ(0, n1->InputCount());
- CHECK_EQ(1, n0->UseCount());
+ CHECK_INPUTS(n1, NONE);
+ CHECK_USES(n0, n2);
n2->RemoveInput(0);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
+ CHECK_INPUTS(n2, n1);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, n2);
n2->RemoveInput(0);
- CHECK_EQ(0, n2->InputCount());
+ CHECK_INPUTS(n2, NONE);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n2, NONE);
}
TEST(AppendInputsAndIterator) {
- GraphTester graph;
+ Zone zone;
+ Graph graph(&zone);
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator1, n0);
+ Node* n2 = graph.NewNode(&dummy_operator2, n0, n1);
- Node::InputEdges inputs(n2->input_edges());
- Node::InputEdges::iterator current = inputs.begin();
- CHECK(current != inputs.end());
- CHECK((*current).to() == n0);
- ++current;
- CHECK(current != inputs.end());
- CHECK((*current).to() == n1);
- ++current;
- CHECK(current == inputs.end());
+ CHECK_INPUTS(n0, NONE);
+ CHECK_INPUTS(n1, n0);
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n0, n1, n2);
- Node* n3 = graph.NewNode(&dummy_operator);
+ Node* n3 = graph.NewNode(&dummy_operator0);
+
n2->AppendInput(graph.zone(), n3);
- inputs = n2->input_edges();
- current = inputs.begin();
- CHECK(current != inputs.end());
- CHECK((*current).to() == n0);
- CHECK_EQ(0, (*current).index());
- ++current;
- CHECK(current != inputs.end());
- CHECK((*current).to() == n1);
- CHECK_EQ(1, (*current).index());
- ++current;
- CHECK(current != inputs.end());
- CHECK((*current).to() == n3);
- CHECK_EQ(2, (*current).index());
- ++current;
- CHECK(current == inputs.end());
+
+ CHECK_INPUTS(n2, n0, n1, n3);
+ CHECK_USES(n3, n2);
}
TEST(NullInputsSimple) {
- GraphTester graph;
+ Zone zone;
+ Graph graph(&zone);
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
- CHECK_EQ(2, n2->InputCount());
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator1, n0);
+ Node* n2 = graph.NewNode(&dummy_operator2, n0, n1);
- CHECK(n0 == n2->InputAt(0));
- CHECK(n1 == n2->InputAt(1));
- CHECK_EQ(2, n0->UseCount());
- n2->ReplaceInput(0, NULL);
- CHECK(NULL == n2->InputAt(0));
- CHECK(n1 == n2->InputAt(1));
- CHECK_EQ(1, n0->UseCount());
+ CHECK_INPUTS(n0, NONE);
+ CHECK_INPUTS(n1, n0);
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n0, n1, n2);
+
+ n2->ReplaceInput(0, nullptr);
+
+ CHECK_INPUTS(n2, NULL, n1);
+
+ CHECK_USES(n0, n1);
+
+ n2->ReplaceInput(1, nullptr);
+
+ CHECK_INPUTS(n2, NULL, NULL);
+
+ CHECK_USES(n1, NONE);
}
TEST(NullInputsAppended) {
- GraphTester graph;
+ Zone zone;
+ Graph graph(&zone);
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- Node* n3 = graph.NewNode(&dummy_operator, n0);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator1, n0);
+ Node* n2 = graph.NewNode(&dummy_operator1, n0);
+ Node* n3 = graph.NewNode(&dummy_operator1, n0);
n3->AppendInput(graph.zone(), n1);
n3->AppendInput(graph.zone(), n2);
- CHECK_EQ(3, n3->InputCount());
- CHECK(n0 == n3->InputAt(0));
- CHECK(n1 == n3->InputAt(1));
- CHECK(n2 == n3->InputAt(2));
- CHECK_EQ(1, n1->UseCount());
+ CHECK_INPUTS(n3, n0, n1, n2);
+ CHECK_USES(n0, n1, n2, n3);
+ CHECK_USES(n1, n3);
+ CHECK_USES(n2, n3);
+
n3->ReplaceInput(1, NULL);
- CHECK(n0 == n3->InputAt(0));
- CHECK(NULL == n3->InputAt(1));
- CHECK(n2 == n3->InputAt(2));
- CHECK_EQ(0, n1->UseCount());
+ CHECK_USES(n1, NONE);
+
+ CHECK_INPUTS(n3, n0, NULL, n2);
}
TEST(ReplaceUsesFromAppendedInputs) {
- GraphTester graph;
+ Zone zone;
+ Graph graph(&zone);
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- Node* n3 = graph.NewNode(&dummy_operator);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator1, n0);
+ Node* n2 = graph.NewNode(&dummy_operator1, n0);
+ Node* n3 = graph.NewNode(&dummy_operator0);
+
+ CHECK_INPUTS(n2, n0);
+
n2->AppendInput(graph.zone(), n1);
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n1, n2);
+
n2->AppendInput(graph.zone(), n0);
- CHECK_EQ(0, n3->UseCount());
- CHECK_EQ(3, n0->UseCount());
+ CHECK_INPUTS(n2, n0, n1, n0);
+ CHECK_USES(n1, n2);
+ CHECK_USES(n0, n2, n1, n2);
+
n0->ReplaceUses(n3);
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(3, n3->UseCount());
- Node::Uses uses(n3->uses());
- Node::Uses::iterator current = uses.begin();
- CHECK(current != uses.end());
- CHECK(*current == n1);
- ++current;
- CHECK(current != uses.end());
- CHECK(*current == n2);
- ++current;
- CHECK(current != uses.end());
- CHECK(*current == n2);
- ++current;
- CHECK(current == uses.end());
-}
-
-
-template <bool result>
-struct FixedPredicate {
- bool operator()(const Node* node) const { return result; }
-};
-
-
-TEST(ReplaceUsesIfWithFixedPredicate) {
- GraphTester graph;
-
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- Node* n3 = graph.NewNode(&dummy_operator);
-
- CHECK_EQ(0, n2->UseCount());
- n2->ReplaceUsesIf(FixedPredicate<true>(), n1);
- CHECK_EQ(0, n2->UseCount());
- n2->ReplaceUsesIf(FixedPredicate<false>(), n1);
- CHECK_EQ(0, n2->UseCount());
-
- CHECK_EQ(0, n3->UseCount());
- n3->ReplaceUsesIf(FixedPredicate<true>(), n1);
- CHECK_EQ(0, n3->UseCount());
- n3->ReplaceUsesIf(FixedPredicate<false>(), n1);
- CHECK_EQ(0, n3->UseCount());
-
- CHECK_EQ(2, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- n0->ReplaceUsesIf(FixedPredicate<false>(), n1);
- CHECK_EQ(2, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- n0->ReplaceUsesIf(FixedPredicate<true>(), n1);
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(2, n1->UseCount());
-
- n1->AppendInput(graph.zone(), n1);
- CHECK_EQ(3, n1->UseCount());
- n1->AppendInput(graph.zone(), n3);
- CHECK_EQ(1, n3->UseCount());
- n3->ReplaceUsesIf(FixedPredicate<true>(), n1);
- CHECK_EQ(4, n1->UseCount());
- CHECK_EQ(0, n3->UseCount());
- n1->ReplaceUsesIf(FixedPredicate<false>(), n3);
- CHECK_EQ(4, n1->UseCount());
- CHECK_EQ(0, n3->UseCount());
-}
-
-
-TEST(ReplaceUsesIfWithEqualTo) {
- GraphTester graph;
-
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
-
- CHECK_EQ(0, n2->UseCount());
- n2->ReplaceUsesIf(std::bind1st(std::equal_to<Node*>(), n1), n0);
- CHECK_EQ(0, n2->UseCount());
-
- CHECK_EQ(2, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- n1->ReplaceUsesIf(std::bind1st(std::equal_to<Node*>(), n0), n0);
- CHECK_EQ(2, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- n0->ReplaceUsesIf(std::bind2nd(std::equal_to<Node*>(), n2), n1);
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(2, n1->UseCount());
+ CHECK_USES(n0, NONE);
+ CHECK_INPUTS(n2, n3, n1, n3);
+ CHECK_USES(n3, n2, n1, n2);
}
TEST(ReplaceInputMultipleUses) {
- GraphTester graph;
+ Zone zone;
+ Graph graph(&zone);
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator1, n0);
n2->ReplaceInput(0, n1);
CHECK_EQ(0, n0->UseCount());
CHECK_EQ(1, n1->UseCount());
- Node* n3 = graph.NewNode(&dummy_operator, n0);
+ Node* n3 = graph.NewNode(&dummy_operator1, n0);
n3->ReplaceInput(0, n1);
CHECK_EQ(0, n0->UseCount());
CHECK_EQ(2, n1->UseCount());
@@ -552,94 +464,92 @@
TEST(TrimInputCountInline) {
- GraphTester graph;
+ Zone zone;
+ Graph graph(&zone);
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator1, n0);
n1->TrimInputCount(1);
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(n0, n1->InputAt(0));
- CHECK_EQ(1, n0->UseCount());
+ CHECK_INPUTS(n1, n0);
+ CHECK_USES(n0, n1);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator1, n0);
n1->TrimInputCount(0);
- CHECK_EQ(0, n1->InputCount());
- CHECK_EQ(0, n0->UseCount());
+ CHECK_INPUTS(n1, NONE);
+ CHECK_USES(n0, NONE);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator2, n0, n1);
n2->TrimInputCount(2);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n0, n2);
+ CHECK_USES(n1, n2);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator2, n0, n1);
n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0);
+ CHECK_USES(n0, n2);
+ CHECK_USES(n1, NONE);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator2, n0, n1);
n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, NONE);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, NONE);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n0);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator2, n0, n0);
n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0);
+ CHECK_USES(n0, n2);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n0);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator2, n0, n0);
n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, NONE);
+ CHECK_USES(n0, NONE);
}
}
TEST(TrimInputCountOutOfLine1) {
- GraphTester graph;
+ Zone zone;
+ Graph graph(&zone);
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator0);
n1->AppendInput(graph.zone(), n0);
+ CHECK_INPUTS(n1, n0);
+ CHECK_USES(n0, n1);
+
n1->TrimInputCount(1);
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(n0, n1->InputAt(0));
- CHECK_EQ(1, n0->UseCount());
+ CHECK_INPUTS(n1, n0);
+ CHECK_USES(n0, n1);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator0);
n1->AppendInput(graph.zone(), n0);
CHECK_EQ(1, n1->InputCount());
n1->TrimInputCount(0);
@@ -648,138 +558,131 @@
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator0);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
+ CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(2);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(n0, n2->InputAt(0));
- CHECK_EQ(n1, n2->InputAt(1));
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n0, n2);
+ CHECK_USES(n1, n2);
+ CHECK_USES(n2, NONE);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator0);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
+ CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(n0, n2->InputAt(0));
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0);
+ CHECK_USES(n0, n2);
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n2, NONE);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator0);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
+ CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, NONE);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n2, NONE);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator0);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n0);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(2, n0->UseCount());
+ CHECK_INPUTS(n2, n0, n0);
+ CHECK_USES(n0, n2, n2);
n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0);
+ CHECK_USES(n0, n2);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator0);
n2->AppendInput(graph.zone(), n0);
n2->AppendInput(graph.zone(), n0);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(2, n0->UseCount());
+ CHECK_INPUTS(n2, n0, n0);
+ CHECK_USES(n0, n2, n2);
n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, NONE);
+ CHECK_USES(n0, NONE);
}
}
TEST(TrimInputCountOutOfLine2) {
- GraphTester graph;
+ Zone zone;
+ Graph graph(&zone);
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator1, n0);
n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
+ CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(2);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(n0, n2->InputAt(0));
- CHECK_EQ(n1, n2->InputAt(1));
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n0, n2);
+ CHECK_USES(n1, n2);
+ CHECK_USES(n2, NONE);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator1, n0);
n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
+ CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(n0, n2->InputAt(0));
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0);
+ CHECK_USES(n0, n2);
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n2, NONE);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator1, n0);
n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
+ CHECK_INPUTS(n2, n0, n1);
n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, NONE);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, NONE);
+ CHECK_USES(n2, NONE);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator1, n0);
n2->AppendInput(graph.zone(), n0);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(2, n0->UseCount());
+ CHECK_INPUTS(n2, n0, n0);
+ CHECK_USES(n0, n2, n2);
n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
+ CHECK_INPUTS(n2, n0);
+ CHECK_USES(n0, n2);
+ CHECK_USES(n2, NONE);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n2 = graph.NewNode(&dummy_operator1, n0);
n2->AppendInput(graph.zone(), n0);
CHECK_EQ(2, n2->InputCount());
CHECK_EQ(2, n0->UseCount());
@@ -791,48 +694,96 @@
}
-TEST(RemoveAllInputs) {
- GraphTester graph;
+TEST(NullAllInputs) {
+ Zone zone;
+ Graph graph(&zone);
for (int i = 0; i < 2; i++) {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator1, n0);
Node* n2;
if (i == 0) {
- n2 = graph.NewNode(&dummy_operator, n0, n1);
+ n2 = graph.NewNode(&dummy_operator2, n0, n1);
+ CHECK_INPUTS(n2, n0, n1);
} else {
- n2 = graph.NewNode(&dummy_operator, n0);
+ n2 = graph.NewNode(&dummy_operator1, n0);
+ CHECK_INPUTS(n2, n0);
n2->AppendInput(graph.zone(), n1); // with out-of-line input.
+ CHECK_INPUTS(n2, n0, n1);
}
- n0->RemoveAllInputs();
- CHECK_EQ(0, n0->InputCount());
+ n0->NullAllInputs();
+ CHECK_INPUTS(n0, NONE);
- CHECK_EQ(2, n0->UseCount());
- n1->RemoveAllInputs();
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(NULL, n1->InputAt(0));
+ CHECK_USES(n0, n1, n2);
+ n1->NullAllInputs();
+ CHECK_INPUTS(n1, NULL);
+ CHECK_INPUTS(n2, n0, n1);
+ CHECK_USES(n0, n2);
- CHECK_EQ(1, n1->UseCount());
- n2->RemoveAllInputs();
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(NULL, n2->InputAt(0));
- CHECK_EQ(NULL, n2->InputAt(1));
+ n2->NullAllInputs();
+ CHECK_INPUTS(n1, NULL);
+ CHECK_INPUTS(n2, NULL, NULL);
+ CHECK_USES(n0, NONE);
}
{
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
+ Node* n0 = graph.NewNode(&dummy_operator0);
+ Node* n1 = graph.NewNode(&dummy_operator1, n0);
n1->ReplaceInput(0, n1); // self-reference.
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- n1->RemoveAllInputs();
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(NULL, n1->InputAt(0));
+ CHECK_INPUTS(n0, NONE);
+ CHECK_INPUTS(n1, n1);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, n1);
+ n1->NullAllInputs();
+
+ CHECK_INPUTS(n0, NONE);
+ CHECK_INPUTS(n1, NULL);
+ CHECK_USES(n0, NONE);
+ CHECK_USES(n1, NONE);
}
}
+
+
+TEST(AppendAndTrim) {
+ Zone zone;
+ Graph graph(&zone);
+
+ Node* nodes[] = {
+ graph.NewNode(&dummy_operator0), graph.NewNode(&dummy_operator0),
+ graph.NewNode(&dummy_operator0), graph.NewNode(&dummy_operator0),
+ graph.NewNode(&dummy_operator0)};
+
+ int max = static_cast<int>(arraysize(nodes));
+
+ Node* last = graph.NewNode(&dummy_operator0);
+
+ for (int i = 0; i < max; i++) {
+ last->AppendInput(graph.zone(), nodes[i]);
+ CheckInputs(last, nodes, i + 1);
+
+ for (int j = 0; j < max; j++) {
+ if (j <= i) CHECK_USES(nodes[j], last);
+ if (j > i) CHECK_USES(nodes[j], NONE);
+ }
+
+ CHECK_USES(last, NONE);
+ }
+
+ for (int i = max; i >= 0; i--) {
+ last->TrimInputCount(i);
+ CheckInputs(last, nodes, i);
+
+ for (int j = 0; j < i; j++) {
+ if (j < i) CHECK_USES(nodes[j], last);
+ if (j >= i) CHECK_USES(nodes[j], NONE);
+ }
+
+ CHECK_USES(last, NONE);
+ }
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-operator.cc b/test/cctest/compiler/test-operator.cc
index 39f660f..eecf46a 100644
--- a/test/cctest/compiler/test-operator.cc
+++ b/test/cctest/compiler/test-operator.cc
@@ -4,13 +4,12 @@
#include <sstream>
-#include "src/v8.h"
-
#include "src/compiler/operator.h"
#include "test/cctest/cctest.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
#define NONE Operator::kNoProperties
#define FOLD Operator::kFoldable
@@ -69,10 +68,10 @@
}
-static SmartArrayPointer<const char> OperatorToString(Operator* op) {
+static v8::base::SmartArrayPointer<const char> OperatorToString(Operator* op) {
std::ostringstream os;
os << *op;
- return SmartArrayPointer<const char>(StrDup(os.str().c_str()));
+ return v8::base::SmartArrayPointer<const char>(StrDup(os.str().c_str()));
}
@@ -80,14 +79,14 @@
Operator op1a(19, NONE, "Another1", 0, 0, 0, 0, 0, 0);
Operator op1b(19, FOLD, "Another2", 2, 0, 0, 2, 0, 0);
- CHECK_EQ("Another1", OperatorToString(&op1a).get());
- CHECK_EQ("Another2", OperatorToString(&op1b).get());
+ CHECK_EQ(0, strcmp("Another1", OperatorToString(&op1a).get()));
+ CHECK_EQ(0, strcmp("Another2", OperatorToString(&op1b).get()));
Operator op2a(20, NONE, "Flog1", 0, 0, 0, 0, 0, 0);
Operator op2b(20, FOLD, "Flog2", 1, 0, 0, 1, 0, 0);
- CHECK_EQ("Flog1", OperatorToString(&op2a).get());
- CHECK_EQ("Flog2", OperatorToString(&op2b).get());
+ CHECK_EQ(0, strcmp("Flog1", OperatorToString(&op2a).get()));
+ CHECK_EQ(0, strcmp("Flog2", OperatorToString(&op2b).get()));
}
@@ -148,16 +147,16 @@
TEST(TestOperator1int_Print) {
Operator1<int> op1(12, NONE, "Op1Test", 0, 0, 0, 1, 0, 0, 0);
- CHECK_EQ("Op1Test[0]", OperatorToString(&op1).get());
+ CHECK_EQ(0, strcmp("Op1Test[0]", OperatorToString(&op1).get()));
Operator1<int> op2(12, NONE, "Op1Test", 0, 0, 0, 1, 0, 0, 66666666);
- CHECK_EQ("Op1Test[66666666]", OperatorToString(&op2).get());
+ CHECK_EQ(0, strcmp("Op1Test[66666666]", OperatorToString(&op2).get()));
Operator1<int> op3(12, NONE, "FooBar", 0, 0, 0, 1, 0, 0, 2347);
- CHECK_EQ("FooBar[2347]", OperatorToString(&op3).get());
+ CHECK_EQ(0, strcmp("FooBar[2347]", OperatorToString(&op3).get()));
Operator1<int> op4(12, NONE, "BarFoo", 0, 0, 0, 1, 0, 0, -879);
- CHECK_EQ("BarFoo[-879]", OperatorToString(&op4).get());
+ CHECK_EQ(0, strcmp("BarFoo[-879]", OperatorToString(&op4).get()));
}
@@ -179,8 +178,8 @@
Operator1<double> op1a(23, NONE, "Canary", 0, 0, 0, 0, 0, 0, 0.5);
Operator1<double> op1b(23, FOLD, "Finch", 2, 0, 0, 2, 0, 0, -1.5);
- CHECK_EQ("Canary[0.5]", OperatorToString(&op1a).get());
- CHECK_EQ("Finch[-1.5]", OperatorToString(&op1b).get());
+ CHECK_EQ(0, strcmp("Canary[0.5]", OperatorToString(&op1a).get()));
+ CHECK_EQ(0, strcmp("Finch[-1.5]", OperatorToString(&op1b).get()));
}
@@ -281,3 +280,7 @@
CHECK_EQ(55, op.EffectOutputCount());
CHECK_EQ(66, op.ControlOutputCount());
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-osr.cc b/test/cctest/compiler/test-osr.cc
new file mode 100644
index 0000000..f0640c2
--- /dev/null
+++ b/test/cctest/compiler/test-osr.cc
@@ -0,0 +1,575 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/codegen.h"
+#include "src/compiler/all-nodes.h"
+#include "src/compiler/common-operator.h"
+#include "src/compiler/diamond.h"
+#include "src/compiler/graph.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/js-operator.h"
+#include "src/compiler/operator.h"
+#include "src/compiler/osr.h"
+#include "test/cctest/cctest.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// TODO(titzer): move this method to a common testing place.
+
+static int CheckInputs(Node* node, Node* i0 = NULL, Node* i1 = NULL,
+ Node* i2 = NULL, Node* i3 = NULL) {
+ int count = 4;
+ if (i3 == NULL) count = 3;
+ if (i2 == NULL) count = 2;
+ if (i1 == NULL) count = 1;
+ if (i0 == NULL) count = 0;
+ CHECK_EQ(count, node->InputCount());
+ if (i0 != NULL) CHECK_EQ(i0, node->InputAt(0));
+ if (i1 != NULL) CHECK_EQ(i1, node->InputAt(1));
+ if (i2 != NULL) CHECK_EQ(i2, node->InputAt(2));
+ if (i3 != NULL) CHECK_EQ(i3, node->InputAt(3));
+ return count;
+}
+
+
+static Operator kIntLt(IrOpcode::kInt32LessThan, Operator::kPure,
+ "Int32LessThan", 2, 0, 0, 1, 0, 0);
+static Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0,
+ 0, 1, 0, 0);
+
+
+static const int kMaxOsrValues = 10;
+
+class OsrDeconstructorTester : public HandleAndZoneScope {
+ public:
+ explicit OsrDeconstructorTester(int num_values)
+ : isolate(main_isolate()),
+ common(main_zone()),
+ graph(main_zone()),
+ jsgraph(main_isolate(), &graph, &common, nullptr, nullptr, nullptr),
+ start(graph.NewNode(common.Start(1))),
+ p0(graph.NewNode(common.Parameter(0), start)),
+ end(graph.NewNode(common.End(1), start)),
+ osr_normal_entry(graph.NewNode(common.OsrNormalEntry(), start, start)),
+ osr_loop_entry(graph.NewNode(common.OsrLoopEntry(), start, start)),
+ self(graph.NewNode(common.Int32Constant(0xaabbccdd))) {
+ CHECK(num_values <= kMaxOsrValues);
+ graph.SetStart(start);
+ for (int i = 0; i < num_values; i++) {
+ osr_values[i] = graph.NewNode(common.OsrValue(i), osr_loop_entry);
+ }
+ }
+
+ Isolate* isolate;
+ CommonOperatorBuilder common;
+ Graph graph;
+ JSGraph jsgraph;
+ Node* start;
+ Node* p0;
+ Node* end;
+ Node* osr_normal_entry;
+ Node* osr_loop_entry;
+ Node* self;
+ Node* osr_values[kMaxOsrValues];
+
+ Node* NewOsrPhi(Node* loop, Node* incoming, int osr_value, Node* back1 = NULL,
+ Node* back2 = NULL, Node* back3 = NULL) {
+ int count = 5;
+ if (back3 == NULL) count = 4;
+ if (back2 == NULL) count = 3;
+ if (back1 == NULL) count = 2;
+ CHECK_EQ(loop->InputCount(), count);
+ CHECK_EQ(osr_loop_entry, loop->InputAt(1));
+
+ Node* inputs[6];
+ inputs[0] = incoming;
+ inputs[1] = osr_values[osr_value];
+ if (count > 2) inputs[2] = back1;
+ if (count > 3) inputs[3] = back2;
+ if (count > 4) inputs[4] = back3;
+ inputs[count] = loop;
+ return graph.NewNode(common.Phi(MachineRepresentation::kTagged, count),
+ count + 1, inputs);
+ }
+
+ Node* NewLoop(bool is_osr, int num_backedges, Node* entry = nullptr) {
+ if (entry == nullptr) entry = osr_normal_entry;
+ Node* loop = graph.NewNode(common.Loop(1), entry);
+ if (is_osr) {
+ loop->AppendInput(graph.zone(), osr_loop_entry);
+ }
+ for (int i = 0; i < num_backedges; i++) {
+ loop->AppendInput(graph.zone(), loop);
+ }
+ NodeProperties::ChangeOp(loop, common.Loop(loop->InputCount()));
+ return loop;
+ }
+
+ Node* NewOsrLoop(int num_backedges, Node* entry = NULL) {
+ return NewLoop(true, num_backedges, entry);
+ }
+
+ void DeconstructOsr() {
+ OsrHelper helper(0, 0);
+ helper.Deconstruct(&jsgraph, &common, main_zone());
+ AllNodes nodes(main_zone(), &graph);
+ // Should be edited out.
+ CHECK(!nodes.IsLive(osr_normal_entry));
+ CHECK(!nodes.IsLive(osr_loop_entry));
+ // No dangling nodes should be left over.
+ for (Node* const node : nodes.live) {
+ for (Node* const use : node->uses()) {
+ CHECK(std::find(nodes.live.begin(), nodes.live.end(), use) !=
+ nodes.live.end());
+ }
+ }
+ }
+};
+
+
+TEST(Deconstruct_osr0) {
+ OsrDeconstructorTester T(0);
+
+ Node* loop = T.NewOsrLoop(1);
+
+ T.graph.SetEnd(loop);
+
+ T.DeconstructOsr();
+
+ CheckInputs(loop, T.start, loop);
+}
+
+
+TEST(Deconstruct_osr1) {
+ OsrDeconstructorTester T(1);
+
+ Node* loop = T.NewOsrLoop(1);
+ Node* osr_phi =
+ T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant());
+
+ Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, loop);
+ T.graph.SetEnd(ret);
+
+ T.DeconstructOsr();
+
+ CheckInputs(loop, T.start, loop);
+ CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop);
+ CheckInputs(ret, osr_phi, T.start, loop);
+}
+
+
+TEST(Deconstruct_osr_remove_prologue) {
+ OsrDeconstructorTester T(1);
+ Diamond d(&T.graph, &T.common, T.p0);
+ d.Chain(T.osr_normal_entry);
+
+ Node* loop = T.NewOsrLoop(1, d.merge);
+ Node* osr_phi =
+ T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant());
+
+ Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, loop);
+ T.graph.SetEnd(ret);
+
+ T.DeconstructOsr();
+
+ CheckInputs(loop, T.start, loop);
+ CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop);
+ CheckInputs(ret, osr_phi, T.start, loop);
+
+ // The control before the loop should have been removed.
+ AllNodes nodes(T.main_zone(), &T.graph);
+ CHECK(!nodes.IsLive(d.branch));
+ CHECK(!nodes.IsLive(d.if_true));
+ CHECK(!nodes.IsLive(d.if_false));
+ CHECK(!nodes.IsLive(d.merge));
+}
+
+
+TEST(Deconstruct_osr_with_body1) {
+ OsrDeconstructorTester T(1);
+
+ Node* loop = T.NewOsrLoop(1);
+
+ Node* branch = T.graph.NewNode(T.common.Branch(), T.p0, loop);
+ Node* if_true = T.graph.NewNode(T.common.IfTrue(), branch);
+ Node* if_false = T.graph.NewNode(T.common.IfFalse(), branch);
+ loop->ReplaceInput(2, if_true);
+
+ Node* osr_phi =
+ T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant());
+
+ Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, if_false);
+ T.graph.SetEnd(ret);
+
+ T.DeconstructOsr();
+
+ CheckInputs(loop, T.start, if_true);
+ CheckInputs(branch, T.p0, loop);
+ CheckInputs(if_true, branch);
+ CheckInputs(if_false, branch);
+ CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop);
+ CheckInputs(ret, osr_phi, T.start, if_false);
+}
+
+
+TEST(Deconstruct_osr_with_body2) {
+ OsrDeconstructorTester T(1);
+
+ Node* loop = T.NewOsrLoop(1);
+
+ // Two chained branches in the the body of the loop.
+ Node* branch1 = T.graph.NewNode(T.common.Branch(), T.p0, loop);
+ Node* if_true1 = T.graph.NewNode(T.common.IfTrue(), branch1);
+ Node* if_false1 = T.graph.NewNode(T.common.IfFalse(), branch1);
+
+ Node* branch2 = T.graph.NewNode(T.common.Branch(), T.p0, if_true1);
+ Node* if_true2 = T.graph.NewNode(T.common.IfTrue(), branch2);
+ Node* if_false2 = T.graph.NewNode(T.common.IfFalse(), branch2);
+ loop->ReplaceInput(2, if_true2);
+
+ Node* osr_phi =
+ T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant());
+
+ Node* merge = T.graph.NewNode(T.common.Merge(2), if_false1, if_false2);
+ Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, merge);
+ T.graph.SetEnd(ret);
+
+ T.DeconstructOsr();
+
+ CheckInputs(loop, T.start, if_true2);
+ CheckInputs(branch1, T.p0, loop);
+ CheckInputs(branch2, T.p0, if_true1);
+ CheckInputs(if_true1, branch1);
+ CheckInputs(if_false1, branch1);
+ CheckInputs(if_true2, branch2);
+ CheckInputs(if_false2, branch2);
+
+ CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop);
+ CheckInputs(ret, osr_phi, T.start, merge);
+ CheckInputs(merge, if_false1, if_false2);
+}
+
+
+TEST(Deconstruct_osr_with_body3) {
+ OsrDeconstructorTester T(1);
+
+ Node* loop = T.NewOsrLoop(2);
+
+ // Two branches that create two different backedges.
+ Node* branch1 = T.graph.NewNode(T.common.Branch(), T.p0, loop);
+ Node* if_true1 = T.graph.NewNode(T.common.IfTrue(), branch1);
+ Node* if_false1 = T.graph.NewNode(T.common.IfFalse(), branch1);
+
+ Node* branch2 = T.graph.NewNode(T.common.Branch(), T.p0, if_true1);
+ Node* if_true2 = T.graph.NewNode(T.common.IfTrue(), branch2);
+ Node* if_false2 = T.graph.NewNode(T.common.IfFalse(), branch2);
+ loop->ReplaceInput(2, if_false1);
+ loop->ReplaceInput(3, if_true2);
+
+ Node* osr_phi =
+ T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant(),
+ T.jsgraph.ZeroConstant());
+
+ Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, if_false2);
+ T.graph.SetEnd(ret);
+
+ T.DeconstructOsr();
+
+ CheckInputs(loop, T.start, if_false1, if_true2);
+ CheckInputs(branch1, T.p0, loop);
+ CheckInputs(branch2, T.p0, if_true1);
+ CheckInputs(if_true1, branch1);
+ CheckInputs(if_false1, branch1);
+ CheckInputs(if_true2, branch2);
+ CheckInputs(if_false2, branch2);
+
+ CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(),
+ T.jsgraph.ZeroConstant(), loop);
+ CheckInputs(ret, osr_phi, T.start, if_false2);
+}
+
+
+struct While {
+ OsrDeconstructorTester& t;
+ Node* branch;
+ Node* if_true;
+ Node* exit;
+ Node* loop;
+
+ While(OsrDeconstructorTester& R, Node* cond, bool is_osr, int backedges = 1)
+ : t(R) {
+ loop = t.NewLoop(is_osr, backedges);
+ branch = t.graph.NewNode(t.common.Branch(), cond, loop);
+ if_true = t.graph.NewNode(t.common.IfTrue(), branch);
+ exit = t.graph.NewNode(t.common.IfFalse(), branch);
+ loop->ReplaceInput(loop->InputCount() - 1, if_true);
+ }
+
+ void Nest(While& that) {
+ that.loop->ReplaceInput(that.loop->InputCount() - 1, exit);
+ this->loop->ReplaceInput(0, that.if_true);
+ }
+
+ Node* Phi(Node* i1, Node* i2, Node* i3) {
+ if (loop->InputCount() == 2) {
+ return t.graph.NewNode(t.common.Phi(MachineRepresentation::kTagged, 2),
+ i1, i2, loop);
+ } else {
+ return t.graph.NewNode(t.common.Phi(MachineRepresentation::kTagged, 3),
+ i1, i2, i3, loop);
+ }
+ }
+};
+
+
+static Node* FindSuccessor(Node* node, IrOpcode::Value opcode) {
+ for (Node* use : node->uses()) {
+ if (use->opcode() == opcode) return use;
+ }
+ UNREACHABLE(); // should have been found.
+ return nullptr;
+}
+
+
+TEST(Deconstruct_osr_nested1) {
+ OsrDeconstructorTester T(1);
+
+ While outer(T, T.p0, false);
+ While inner(T, T.p0, true);
+ inner.Nest(outer);
+
+ Node* outer_phi = outer.Phi(T.p0, T.p0, nullptr);
+ outer.branch->ReplaceInput(0, outer_phi);
+
+ Node* osr_phi = inner.Phi(T.jsgraph.TrueConstant(), T.osr_values[0],
+ T.jsgraph.FalseConstant());
+ inner.branch->ReplaceInput(0, osr_phi);
+ outer_phi->ReplaceInput(1, osr_phi);
+
+ Node* ret =
+ T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit);
+ Node* end = T.graph.NewNode(T.common.End(1), ret);
+ T.graph.SetEnd(end);
+
+ T.DeconstructOsr();
+
+ // Check structure of deconstructed graph.
+ // Check inner OSR loop is directly connected to start.
+ CheckInputs(inner.loop, T.start, inner.if_true);
+ CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.FalseConstant(), inner.loop);
+
+ // Check control transfer to copy of outer loop.
+ Node* new_outer_loop = FindSuccessor(inner.exit, IrOpcode::kLoop);
+ Node* new_outer_phi = FindSuccessor(new_outer_loop, IrOpcode::kPhi);
+ CHECK_NE(new_outer_loop, outer.loop);
+ CHECK_NE(new_outer_phi, outer_phi);
+
+ CheckInputs(new_outer_loop, inner.exit, new_outer_loop->InputAt(1));
+
+ // Check structure of outer loop.
+ Node* new_outer_branch = FindSuccessor(new_outer_loop, IrOpcode::kBranch);
+ CHECK_NE(new_outer_branch, outer.branch);
+ CheckInputs(new_outer_branch, new_outer_phi, new_outer_loop);
+ Node* new_outer_exit = FindSuccessor(new_outer_branch, IrOpcode::kIfFalse);
+ Node* new_outer_if_true = FindSuccessor(new_outer_branch, IrOpcode::kIfTrue);
+
+ // Check structure of return.
+ end = T.graph.end();
+ Node* new_ret = end->InputAt(0);
+ CHECK_EQ(IrOpcode::kReturn, new_ret->opcode());
+ CheckInputs(new_ret, new_outer_phi, T.start, new_outer_exit);
+
+ // Check structure of inner loop.
+ Node* new_inner_loop = FindSuccessor(new_outer_if_true, IrOpcode::kLoop);
+ Node* new_inner_phi = FindSuccessor(new_inner_loop, IrOpcode::kPhi);
+
+ CheckInputs(new_inner_phi, T.jsgraph.TrueConstant(),
+ T.jsgraph.FalseConstant(), new_inner_loop);
+ CheckInputs(new_outer_phi, osr_phi, new_inner_phi, new_outer_loop);
+}
+
+
+TEST(Deconstruct_osr_nested2) {
+ OsrDeconstructorTester T(1);
+
+ // Test multiple backedge outer loop.
+ While outer(T, T.p0, false, 2);
+ While inner(T, T.p0, true);
+ inner.Nest(outer);
+
+ Node* outer_phi = outer.Phi(T.p0, T.p0, T.p0);
+ outer.branch->ReplaceInput(0, outer_phi);
+
+ Node* osr_phi = inner.Phi(T.jsgraph.TrueConstant(), T.osr_values[0],
+ T.jsgraph.FalseConstant());
+ inner.branch->ReplaceInput(0, osr_phi);
+ outer_phi->ReplaceInput(1, osr_phi);
+ outer_phi->ReplaceInput(2, T.jsgraph.FalseConstant());
+
+ Node* x_branch = T.graph.NewNode(T.common.Branch(), osr_phi, inner.exit);
+ Node* x_true = T.graph.NewNode(T.common.IfTrue(), x_branch);
+ Node* x_false = T.graph.NewNode(T.common.IfFalse(), x_branch);
+
+ outer.loop->ReplaceInput(1, x_true);
+ outer.loop->ReplaceInput(2, x_false);
+
+ Node* ret =
+ T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit);
+ Node* end = T.graph.NewNode(T.common.End(1), ret);
+ T.graph.SetEnd(end);
+
+ T.DeconstructOsr();
+
+ // Check structure of deconstructed graph.
+ // Check inner OSR loop is directly connected to start.
+ CheckInputs(inner.loop, T.start, inner.if_true);
+ CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.FalseConstant(), inner.loop);
+
+ // Check control transfer to copy of outer loop.
+ Node* new_merge = FindSuccessor(x_true, IrOpcode::kMerge);
+ CHECK_EQ(new_merge, FindSuccessor(x_false, IrOpcode::kMerge));
+ CheckInputs(new_merge, x_true, x_false);
+
+ Node* new_outer_loop = FindSuccessor(new_merge, IrOpcode::kLoop);
+ Node* new_outer_phi = FindSuccessor(new_outer_loop, IrOpcode::kPhi);
+ CHECK_NE(new_outer_loop, outer.loop);
+ CHECK_NE(new_outer_phi, outer_phi);
+
+ Node* new_entry_phi = FindSuccessor(new_merge, IrOpcode::kPhi);
+ CheckInputs(new_entry_phi, osr_phi, T.jsgraph.FalseConstant(), new_merge);
+
+ CHECK_EQ(new_merge, new_outer_loop->InputAt(0));
+
+ // Check structure of outer loop.
+ Node* new_outer_branch = FindSuccessor(new_outer_loop, IrOpcode::kBranch);
+ CHECK_NE(new_outer_branch, outer.branch);
+ CheckInputs(new_outer_branch, new_outer_phi, new_outer_loop);
+ Node* new_outer_exit = FindSuccessor(new_outer_branch, IrOpcode::kIfFalse);
+ Node* new_outer_if_true = FindSuccessor(new_outer_branch, IrOpcode::kIfTrue);
+
+ // Check structure of return.
+ end = T.graph.end();
+ Node* new_ret = end->InputAt(0);
+ CHECK_EQ(IrOpcode::kReturn, new_ret->opcode());
+ CheckInputs(new_ret, new_outer_phi, T.start, new_outer_exit);
+
+ // Check structure of inner loop.
+ Node* new_inner_loop = FindSuccessor(new_outer_if_true, IrOpcode::kLoop);
+ Node* new_inner_phi = FindSuccessor(new_inner_loop, IrOpcode::kPhi);
+
+ CheckInputs(new_inner_phi, T.jsgraph.TrueConstant(),
+ T.jsgraph.FalseConstant(), new_inner_loop);
+ CheckInputs(new_outer_phi, new_entry_phi, new_inner_phi,
+ T.jsgraph.FalseConstant(), new_outer_loop);
+}
+
+
+Node* MakeCounter(JSGraph* jsgraph, Node* start, Node* loop) {
+ int count = loop->InputCount();
+ NodeVector tmp_inputs(jsgraph->graph()->zone());
+ for (int i = 0; i < count; i++) {
+ tmp_inputs.push_back(start);
+ }
+ tmp_inputs.push_back(loop);
+
+ Node* phi = jsgraph->graph()->NewNode(
+ jsgraph->common()->Phi(MachineRepresentation::kWord32, count), count + 1,
+ &tmp_inputs[0]);
+ Node* inc = jsgraph->graph()->NewNode(&kIntAdd, phi, jsgraph->OneConstant());
+
+ for (int i = 1; i < count; i++) {
+ phi->ReplaceInput(i, inc);
+ }
+ return phi;
+}
+
+
+TEST(Deconstruct_osr_nested3) {
+ OsrDeconstructorTester T(1);
+
+ // outermost loop.
+ While loop0(T, T.p0, false, 1);
+ Node* loop0_cntr = MakeCounter(&T.jsgraph, T.p0, loop0.loop);
+ loop0.branch->ReplaceInput(0, loop0_cntr);
+
+ // middle loop.
+ Node* loop1 = T.graph.NewNode(T.common.Loop(1), loop0.if_true);
+ Node* loop1_phi =
+ T.graph.NewNode(T.common.Phi(MachineRepresentation::kTagged, 2),
+ loop0_cntr, loop0_cntr, loop1);
+
+ // innermost (OSR) loop.
+ While loop2(T, T.p0, true, 1);
+ loop2.loop->ReplaceInput(0, loop1);
+
+ Node* loop2_cntr = MakeCounter(&T.jsgraph, loop1_phi, loop2.loop);
+ loop2_cntr->ReplaceInput(1, T.osr_values[0]);
+ Node* osr_phi = loop2_cntr;
+ Node* loop2_inc = loop2_cntr->InputAt(2);
+ loop2.branch->ReplaceInput(0, loop2_cntr);
+
+ loop1_phi->ReplaceInput(1, loop2_cntr);
+ loop0_cntr->ReplaceInput(1, loop2_cntr);
+
+ // Branch to either the outer or middle loop.
+ Node* branch = T.graph.NewNode(T.common.Branch(), loop2_cntr, loop2.exit);
+ Node* if_true = T.graph.NewNode(T.common.IfTrue(), branch);
+ Node* if_false = T.graph.NewNode(T.common.IfFalse(), branch);
+
+ loop0.loop->ReplaceInput(1, if_true);
+ loop1->AppendInput(T.graph.zone(), if_false);
+ NodeProperties::ChangeOp(loop1, T.common.Loop(2));
+
+ Node* ret =
+ T.graph.NewNode(T.common.Return(), loop0_cntr, T.start, loop0.exit);
+ Node* end = T.graph.NewNode(T.common.End(1), ret);
+ T.graph.SetEnd(end);
+
+ T.DeconstructOsr();
+
+ // Check structure of deconstructed graph.
+ // Check loop2 (OSR loop) is directly connected to start.
+ CheckInputs(loop2.loop, T.start, loop2.if_true);
+ CheckInputs(osr_phi, T.osr_values[0], loop2_inc, loop2.loop);
+ CheckInputs(loop2.branch, osr_phi, loop2.loop);
+ CheckInputs(loop2.if_true, loop2.branch);
+ CheckInputs(loop2.exit, loop2.branch);
+ CheckInputs(branch, osr_phi, loop2.exit);
+ CheckInputs(if_true, branch);
+ CheckInputs(if_false, branch);
+
+ // Check structure of new_loop1.
+ Node* new_loop1_loop = FindSuccessor(if_false, IrOpcode::kLoop);
+ // TODO(titzer): check the internal copy of loop2.
+ USE(new_loop1_loop);
+
+ // Check structure of new_loop0.
+ Node* new_loop0_loop_entry = FindSuccessor(if_true, IrOpcode::kMerge);
+ Node* new_loop0_loop = FindSuccessor(new_loop0_loop_entry, IrOpcode::kLoop);
+ // TODO(titzer): check the internal copies of loop1 and loop2.
+
+ Node* new_loop0_branch = FindSuccessor(new_loop0_loop, IrOpcode::kBranch);
+ Node* new_loop0_if_true = FindSuccessor(new_loop0_branch, IrOpcode::kIfTrue);
+ Node* new_loop0_exit = FindSuccessor(new_loop0_branch, IrOpcode::kIfFalse);
+
+ USE(new_loop0_if_true);
+
+ Node* new_ret = T.graph.end()->InputAt(0);
+ CHECK_EQ(IrOpcode::kReturn, new_ret->opcode());
+
+ Node* new_loop0_phi = new_ret->InputAt(0);
+ CHECK_EQ(IrOpcode::kPhi, new_loop0_phi->opcode());
+ CHECK_EQ(new_loop0_loop, NodeProperties::GetControlInput(new_loop0_phi));
+ CHECK_EQ(new_loop0_phi, FindSuccessor(new_loop0_loop, IrOpcode::kPhi));
+
+ // Check that the return returns the phi from the OSR loop and control
+ // depends on the copy of the outer loop0.
+ CheckInputs(new_ret, new_loop0_phi, T.graph.start(), new_loop0_exit);
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-pipeline.cc b/test/cctest/compiler/test-pipeline.cc
index 98b0bae..f4ffd02 100644
--- a/test/cctest/compiler/test-pipeline.cc
+++ b/test/cctest/compiler/test-pipeline.cc
@@ -2,35 +2,43 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-#include "test/cctest/cctest.h"
-
-#include "src/ast-numbering.h"
#include "src/compiler.h"
#include "src/compiler/pipeline.h"
#include "src/handles.h"
-#include "src/parser.h"
-#include "src/rewriter.h"
-#include "src/scopes.h"
+#include "src/parsing/parser.h"
+#include "test/cctest/cctest.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
-TEST(PipelineAdd) {
- InitializedHandleScope handles;
- const char* source = "(function(a,b) { return a + b; })";
- Handle<JSFunction> function = v8::Utils::OpenHandle(
- *v8::Handle<v8::Function>::Cast(CompileRun(source)));
- CompilationInfoWithZone info(function);
-
- CHECK(Compiler::ParseAndAnalyze(&info));
+static void RunPipeline(Zone* zone, const char* source) {
+ Handle<JSFunction> function = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
+ *v8::Local<v8::Function>::Cast(CompileRun(source))));
+ ParseInfo parse_info(zone, function);
+ CHECK(Compiler::ParseAndAnalyze(&parse_info));
+ CompilationInfo info(&parse_info);
+ info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
Pipeline pipeline(&info);
-#if V8_TURBOFAN_TARGET
Handle<Code> code = pipeline.GenerateCode();
- CHECK(Pipeline::SupportedTarget());
CHECK(!code.is_null());
-#else
- USE(pipeline);
-#endif
}
+
+
+TEST(PipelineTyped) {
+ HandleAndZoneScope handles;
+ FLAG_turbo_types = true;
+ RunPipeline(handles.main_zone(), "(function(a,b) { return a + b; })");
+}
+
+
+TEST(PipelineGeneric) {
+ HandleAndZoneScope handles;
+ FLAG_turbo_types = false;
+ RunPipeline(handles.main_zone(), "(function(a,b) { return a + b; })");
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-representation-change.cc b/test/cctest/compiler/test-representation-change.cc
index 2dc3029..7353e16 100644
--- a/test/cctest/compiler/test-representation-change.cc
+++ b/test/cctest/compiler/test-representation-change.cc
@@ -4,18 +4,15 @@
#include <limits>
-#include "src/v8.h"
#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/codegen-tester.h"
#include "test/cctest/compiler/graph-builder-tester.h"
#include "test/cctest/compiler/value-helper.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/representation-change.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-namespace v8 { // for friendiness.
+namespace v8 {
namespace internal {
namespace compiler {
@@ -25,8 +22,9 @@
explicit RepresentationChangerTester(int num_parameters = 0)
: GraphAndBuilders(main_zone()),
javascript_(main_zone()),
- jsgraph_(main_graph_, &main_common_, &javascript_, &main_machine_),
- changer_(&jsgraph_, &main_simplified_, main_isolate()) {
+ jsgraph_(main_isolate(), main_graph_, &main_common_, &javascript_,
+ &main_simplified_, &main_machine_),
+ changer_(&jsgraph_, main_isolate()) {
Node* s = graph()->NewNode(common()->Start(num_parameters));
graph()->SetStart(s);
}
@@ -57,67 +55,73 @@
void CheckFloat64Constant(Node* n, double expected) {
Float64Matcher m(n);
CHECK(m.HasValue());
- CHECK_EQ(expected, m.Value());
+ CheckDoubleEq(expected, m.Value());
}
void CheckFloat32Constant(Node* n, float expected) {
CHECK_EQ(IrOpcode::kFloat32Constant, n->opcode());
float fval = OpParameter<float>(n->op());
- CHECK_EQ(expected, fval);
+ CheckDoubleEq(expected, fval);
}
void CheckHeapConstant(Node* n, HeapObject* expected) {
- HeapObjectMatcher<HeapObject> m(n);
+ HeapObjectMatcher m(n);
CHECK(m.HasValue());
- CHECK_EQ(expected, *m.Value().handle());
+ CHECK_EQ(expected, *m.Value());
}
void CheckNumberConstant(Node* n, double expected) {
NumberMatcher m(n);
CHECK_EQ(IrOpcode::kNumberConstant, n->opcode());
CHECK(m.HasValue());
- CHECK_EQ(expected, m.Value());
+ CheckDoubleEq(expected, m.Value());
}
Node* Parameter(int index = 0) {
- return graph()->NewNode(common()->Parameter(index), graph()->start());
+ Node* n = graph()->NewNode(common()->Parameter(index), graph()->start());
+ NodeProperties::SetType(n, Type::Any());
+ return n;
}
- void CheckTypeError(MachineTypeUnion from, MachineTypeUnion to) {
+ void CheckTypeError(MachineRepresentation from, Type* from_type,
+ MachineRepresentation to) {
changer()->testing_type_errors_ = true;
changer()->type_error_ = false;
Node* n = Parameter(0);
- Node* c = changer()->GetRepresentationFor(n, from, to);
+ Node* c = changer()->GetRepresentationFor(n, from, from_type, to);
CHECK(changer()->type_error_);
CHECK_EQ(n, c);
}
- void CheckNop(MachineTypeUnion from, MachineTypeUnion to) {
+ void CheckNop(MachineRepresentation from, Type* from_type,
+ MachineRepresentation to) {
Node* n = Parameter(0);
- Node* c = changer()->GetRepresentationFor(n, from, to);
+ Node* c = changer()->GetRepresentationFor(n, from, from_type, to);
CHECK_EQ(n, c);
}
};
-}
-}
-} // namespace v8::internal::compiler
-static const MachineType all_reps[] = {kRepBit, kRepWord32, kRepWord64,
- kRepFloat32, kRepFloat64, kRepTagged};
+const MachineType kMachineTypes[] = {
+ MachineType::Float32(), MachineType::Float64(), MachineType::Int8(),
+ MachineType::Uint8(), MachineType::Int16(), MachineType::Uint16(),
+ MachineType::Int32(), MachineType::Uint32(), MachineType::Int64(),
+ MachineType::Uint64(), MachineType::AnyTagged()};
TEST(BoolToBit_constant) {
RepresentationChangerTester r;
Node* true_node = r.jsgraph()->TrueConstant();
- Node* true_bit =
- r.changer()->GetRepresentationFor(true_node, kRepTagged, kRepBit);
+ Node* true_bit = r.changer()->GetRepresentationFor(
+ true_node, MachineRepresentation::kTagged, Type::None(),
+ MachineRepresentation::kBit);
r.CheckInt32Constant(true_bit, 1);
Node* false_node = r.jsgraph()->FalseConstant();
- Node* false_bit =
- r.changer()->GetRepresentationFor(false_node, kRepTagged, kRepBit);
+ Node* false_bit = r.changer()->GetRepresentationFor(
+ false_node, MachineRepresentation::kTagged, Type::None(),
+ MachineRepresentation::kBit);
r.CheckInt32Constant(false_bit, 0);
}
@@ -127,7 +131,9 @@
for (int i = -5; i < 5; i++) {
Node* node = r.jsgraph()->Int32Constant(i);
- Node* val = r.changer()->GetRepresentationFor(node, kRepBit, kRepTagged);
+ Node* val = r.changer()->GetRepresentationFor(
+ node, MachineRepresentation::kBit, Type::Boolean(),
+ MachineRepresentation::kTagged);
r.CheckHeapConstant(val, i == 0 ? r.isolate()->heap()->false_value()
: r.isolate()->heap()->true_value());
}
@@ -140,7 +146,9 @@
{
FOR_FLOAT64_INPUTS(i) {
Node* n = r.jsgraph()->Float64Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64, kRepTagged);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kFloat64, Type::None(),
+ MachineRepresentation::kTagged);
r.CheckNumberConstant(c, *i);
}
}
@@ -148,7 +156,9 @@
{
FOR_FLOAT64_INPUTS(i) {
Node* n = r.jsgraph()->Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64, kRepTagged);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kFloat64, Type::None(),
+ MachineRepresentation::kTagged);
r.CheckNumberConstant(c, *i);
}
}
@@ -156,7 +166,9 @@
{
FOR_FLOAT32_INPUTS(i) {
Node* n = r.jsgraph()->Float32Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepFloat32, kRepTagged);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kFloat32, Type::None(),
+ MachineRepresentation::kTagged);
r.CheckNumberConstant(c, *i);
}
}
@@ -164,8 +176,9 @@
{
FOR_INT32_INPUTS(i) {
Node* n = r.jsgraph()->Int32Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeInt32,
- kRepTagged);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kWord32, Type::Signed32(),
+ MachineRepresentation::kTagged);
r.CheckNumberConstant(c, *i);
}
}
@@ -173,8 +186,9 @@
{
FOR_UINT32_INPUTS(i) {
Node* n = r.jsgraph()->Int32Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeUint32,
- kRepTagged);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kWord32, Type::Unsigned32(),
+ MachineRepresentation::kTagged);
r.CheckNumberConstant(c, *i);
}
}
@@ -187,7 +201,9 @@
{
FOR_FLOAT64_INPUTS(i) {
Node* n = r.jsgraph()->Float64Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64, kRepFloat64);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kFloat64, Type::None(),
+ MachineRepresentation::kFloat64);
CHECK_EQ(n, c);
}
}
@@ -195,7 +211,9 @@
{
FOR_FLOAT64_INPUTS(i) {
Node* n = r.jsgraph()->Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepTagged, kRepFloat64);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kTagged, Type::None(),
+ MachineRepresentation::kFloat64);
r.CheckFloat64Constant(c, *i);
}
}
@@ -203,7 +221,9 @@
{
FOR_FLOAT32_INPUTS(i) {
Node* n = r.jsgraph()->Float32Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepFloat32, kRepFloat64);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kFloat32, Type::None(),
+ MachineRepresentation::kFloat64);
r.CheckFloat64Constant(c, *i);
}
}
@@ -211,8 +231,9 @@
{
FOR_INT32_INPUTS(i) {
Node* n = r.jsgraph()->Int32Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeInt32,
- kRepFloat64);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kWord32, Type::Signed32(),
+ MachineRepresentation::kFloat64);
r.CheckFloat64Constant(c, *i);
}
}
@@ -220,8 +241,9 @@
{
FOR_UINT32_INPUTS(i) {
Node* n = r.jsgraph()->Int32Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeUint32,
- kRepFloat64);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kWord32, Type::Unsigned32(),
+ MachineRepresentation::kFloat64);
r.CheckFloat64Constant(c, *i);
}
}
@@ -242,7 +264,9 @@
{
FOR_FLOAT32_INPUTS(i) {
Node* n = r.jsgraph()->Float32Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepFloat32, kRepFloat32);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kFloat32, Type::None(),
+ MachineRepresentation::kFloat32);
CHECK_EQ(n, c);
}
}
@@ -250,7 +274,9 @@
{
FOR_FLOAT32_INPUTS(i) {
Node* n = r.jsgraph()->Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepTagged, kRepFloat32);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kTagged, Type::None(),
+ MachineRepresentation::kFloat32);
r.CheckFloat32Constant(c, *i);
}
}
@@ -258,7 +284,9 @@
{
FOR_FLOAT32_INPUTS(i) {
Node* n = r.jsgraph()->Float64Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64, kRepFloat32);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kFloat64, Type::None(),
+ MachineRepresentation::kFloat32);
r.CheckFloat32Constant(c, *i);
}
}
@@ -267,8 +295,9 @@
FOR_INT32_INPUTS(i) {
if (!IsFloat32Int32(*i)) continue;
Node* n = r.jsgraph()->Int32Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeInt32,
- kRepFloat32);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kWord32, Type::Signed32(),
+ MachineRepresentation::kFloat32);
r.CheckFloat32Constant(c, static_cast<float>(*i));
}
}
@@ -277,8 +306,9 @@
FOR_UINT32_INPUTS(i) {
if (!IsFloat32Uint32(*i)) continue;
Node* n = r.jsgraph()->Int32Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeUint32,
- kRepFloat32);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kWord32, Type::Unsigned32(),
+ MachineRepresentation::kFloat32);
r.CheckFloat32Constant(c, static_cast<float>(*i));
}
}
@@ -291,8 +321,9 @@
{
FOR_INT32_INPUTS(i) {
Node* n = r.jsgraph()->Int32Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeInt32,
- kRepWord32);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kWord32, Type::Signed32(),
+ MachineRepresentation::kWord32);
r.CheckInt32Constant(c, *i);
}
}
@@ -301,8 +332,9 @@
FOR_INT32_INPUTS(i) {
if (!IsFloat32Int32(*i)) continue;
Node* n = r.jsgraph()->Float32Constant(static_cast<float>(*i));
- Node* c = r.changer()->GetRepresentationFor(n, kRepFloat32 | kTypeInt32,
- kRepWord32);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kFloat32, Type::Signed32(),
+ MachineRepresentation::kWord32);
r.CheckInt32Constant(c, *i);
}
}
@@ -310,8 +342,9 @@
{
FOR_INT32_INPUTS(i) {
Node* n = r.jsgraph()->Float64Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64 | kTypeInt32,
- kRepWord32);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kFloat64, Type::Signed32(),
+ MachineRepresentation::kWord32);
r.CheckInt32Constant(c, *i);
}
}
@@ -319,8 +352,9 @@
{
FOR_INT32_INPUTS(i) {
Node* n = r.jsgraph()->Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepTagged | kTypeInt32,
- kRepWord32);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kTagged, Type::Signed32(),
+ MachineRepresentation::kWord32);
r.CheckInt32Constant(c, *i);
}
}
@@ -333,8 +367,9 @@
{
FOR_UINT32_INPUTS(i) {
Node* n = r.jsgraph()->Int32Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepWord32 | kTypeUint32,
- kRepWord32);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kWord32, Type::Unsigned32(),
+ MachineRepresentation::kWord32);
r.CheckUint32Constant(c, *i);
}
}
@@ -343,8 +378,9 @@
FOR_UINT32_INPUTS(i) {
if (!IsFloat32Uint32(*i)) continue;
Node* n = r.jsgraph()->Float32Constant(static_cast<float>(*i));
- Node* c = r.changer()->GetRepresentationFor(n, kRepFloat32 | kTypeUint32,
- kRepWord32);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kFloat32, Type::Unsigned32(),
+ MachineRepresentation::kWord32);
r.CheckUint32Constant(c, *i);
}
}
@@ -352,8 +388,9 @@
{
FOR_UINT32_INPUTS(i) {
Node* n = r.jsgraph()->Float64Constant(*i);
- Node* c = r.changer()->GetRepresentationFor(n, kRepFloat64 | kTypeUint32,
- kRepWord32);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kFloat64, Type::Unsigned32(),
+ MachineRepresentation::kWord32);
r.CheckUint32Constant(c, *i);
}
}
@@ -361,20 +398,21 @@
{
FOR_UINT32_INPUTS(i) {
Node* n = r.jsgraph()->Constant(static_cast<double>(*i));
- Node* c = r.changer()->GetRepresentationFor(n, kRepTagged | kTypeUint32,
- kRepWord32);
+ Node* c = r.changer()->GetRepresentationFor(
+ n, MachineRepresentation::kTagged, Type::Unsigned32(),
+ MachineRepresentation::kWord32);
r.CheckUint32Constant(c, *i);
}
}
}
-static void CheckChange(IrOpcode::Value expected, MachineTypeUnion from,
- MachineTypeUnion to) {
+static void CheckChange(IrOpcode::Value expected, MachineRepresentation from,
+ Type* from_type, MachineRepresentation to) {
RepresentationChangerTester r;
Node* n = r.Parameter();
- Node* c = r.changer()->GetRepresentationFor(n, from, to);
+ Node* c = r.changer()->GetRepresentationFor(n, from, from_type, to);
CHECK_NE(c, n);
CHECK_EQ(expected, c->opcode());
@@ -383,12 +421,13 @@
static void CheckTwoChanges(IrOpcode::Value expected2,
- IrOpcode::Value expected1, MachineTypeUnion from,
- MachineTypeUnion to) {
+ IrOpcode::Value expected1,
+ MachineRepresentation from, Type* from_type,
+ MachineRepresentation to) {
RepresentationChangerTester r;
Node* n = r.Parameter();
- Node* c1 = r.changer()->GetRepresentationFor(n, from, to);
+ Node* c1 = r.changer()->GetRepresentationFor(n, from, from_type, to);
CHECK_NE(c1, n);
CHECK_EQ(expected1, c1->opcode());
@@ -400,70 +439,92 @@
TEST(SingleChanges) {
- CheckChange(IrOpcode::kChangeBoolToBit, kRepTagged, kRepBit);
- CheckChange(IrOpcode::kChangeBitToBool, kRepBit, kRepTagged);
+ CheckChange(IrOpcode::kChangeBoolToBit, MachineRepresentation::kTagged,
+ Type::None(), MachineRepresentation::kBit);
+ CheckChange(IrOpcode::kChangeBitToBool, MachineRepresentation::kBit,
+ Type::None(), MachineRepresentation::kTagged);
- CheckChange(IrOpcode::kChangeInt32ToTagged, kRepWord32 | kTypeInt32,
- kRepTagged);
- CheckChange(IrOpcode::kChangeUint32ToTagged, kRepWord32 | kTypeUint32,
- kRepTagged);
- CheckChange(IrOpcode::kChangeFloat64ToTagged, kRepFloat64, kRepTagged);
+ CheckChange(IrOpcode::kChangeInt32ToTagged, MachineRepresentation::kWord32,
+ Type::Signed32(), MachineRepresentation::kTagged);
+ CheckChange(IrOpcode::kChangeUint32ToTagged, MachineRepresentation::kWord32,
+ Type::Unsigned32(), MachineRepresentation::kTagged);
+ CheckChange(IrOpcode::kChangeFloat64ToTagged, MachineRepresentation::kFloat64,
+ Type::None(), MachineRepresentation::kTagged);
- CheckChange(IrOpcode::kChangeTaggedToInt32, kRepTagged | kTypeInt32,
- kRepWord32);
- CheckChange(IrOpcode::kChangeTaggedToUint32, kRepTagged | kTypeUint32,
- kRepWord32);
- CheckChange(IrOpcode::kChangeTaggedToFloat64, kRepTagged, kRepFloat64);
+ CheckChange(IrOpcode::kChangeTaggedToInt32, MachineRepresentation::kTagged,
+ Type::Signed32(), MachineRepresentation::kWord32);
+ CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged,
+ Type::Unsigned32(), MachineRepresentation::kWord32);
+ CheckChange(IrOpcode::kChangeTaggedToFloat64, MachineRepresentation::kTagged,
+ Type::None(), MachineRepresentation::kFloat64);
// Int32,Uint32 <-> Float64 are actually machine conversions.
- CheckChange(IrOpcode::kChangeInt32ToFloat64, kRepWord32 | kTypeInt32,
- kRepFloat64);
- CheckChange(IrOpcode::kChangeUint32ToFloat64, kRepWord32 | kTypeUint32,
- kRepFloat64);
- CheckChange(IrOpcode::kChangeFloat64ToInt32, kRepFloat64 | kTypeInt32,
- kRepWord32);
- CheckChange(IrOpcode::kChangeFloat64ToUint32, kRepFloat64 | kTypeUint32,
- kRepWord32);
+ CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
+ Type::Signed32(), MachineRepresentation::kFloat64);
+ CheckChange(IrOpcode::kChangeUint32ToFloat64, MachineRepresentation::kWord32,
+ Type::Unsigned32(), MachineRepresentation::kFloat64);
+ CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64,
+ Type::Signed32(), MachineRepresentation::kWord32);
+ CheckChange(IrOpcode::kChangeFloat64ToUint32, MachineRepresentation::kFloat64,
+ Type::Unsigned32(), MachineRepresentation::kWord32);
- CheckChange(IrOpcode::kTruncateFloat64ToFloat32, kRepFloat64, kRepFloat32);
+ CheckChange(IrOpcode::kTruncateFloat64ToFloat32,
+ MachineRepresentation::kFloat64, Type::None(),
+ MachineRepresentation::kFloat32);
// Int32,Uint32 <-> Float32 require two changes.
CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64,
- IrOpcode::kTruncateFloat64ToFloat32, kRepWord32 | kTypeInt32,
- kRepFloat32);
+ IrOpcode::kTruncateFloat64ToFloat32,
+ MachineRepresentation::kWord32, Type::Signed32(),
+ MachineRepresentation::kFloat32);
CheckTwoChanges(IrOpcode::kChangeUint32ToFloat64,
- IrOpcode::kTruncateFloat64ToFloat32, kRepWord32 | kTypeUint32,
- kRepFloat32);
+ IrOpcode::kTruncateFloat64ToFloat32,
+ MachineRepresentation::kWord32, Type::Unsigned32(),
+ MachineRepresentation::kFloat32);
CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
- IrOpcode::kChangeFloat64ToInt32, kRepFloat32 | kTypeInt32,
- kRepWord32);
+ IrOpcode::kChangeFloat64ToInt32,
+ MachineRepresentation::kFloat32, Type::Signed32(),
+ MachineRepresentation::kWord32);
CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
- IrOpcode::kChangeFloat64ToUint32, kRepFloat32 | kTypeUint32,
- kRepWord32);
+ IrOpcode::kChangeFloat64ToUint32,
+ MachineRepresentation::kFloat32, Type::Unsigned32(),
+ MachineRepresentation::kWord32);
// Float32 <-> Tagged require two changes.
CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
- IrOpcode::kChangeFloat64ToTagged, kRepFloat32, kRepTagged);
+ IrOpcode::kChangeFloat64ToTagged,
+ MachineRepresentation::kFloat32, Type::None(),
+ MachineRepresentation::kTagged);
CheckTwoChanges(IrOpcode::kChangeTaggedToFloat64,
- IrOpcode::kTruncateFloat64ToFloat32, kRepTagged, kRepFloat32);
+ IrOpcode::kTruncateFloat64ToFloat32,
+ MachineRepresentation::kTagged, Type::None(),
+ MachineRepresentation::kFloat32);
}
TEST(SignednessInWord32) {
RepresentationChangerTester r;
- // TODO(titzer): assume that uses of a word32 without a sign mean kTypeInt32.
- CheckChange(IrOpcode::kChangeTaggedToInt32, kRepTagged,
- kRepWord32 | kTypeInt32);
- CheckChange(IrOpcode::kChangeTaggedToUint32, kRepTagged,
- kRepWord32 | kTypeUint32);
- CheckChange(IrOpcode::kChangeInt32ToFloat64, kRepWord32, kRepFloat64);
- CheckChange(IrOpcode::kChangeFloat64ToInt32, kRepFloat64, kRepWord32);
+ CheckChange(IrOpcode::kChangeTaggedToInt32, MachineRepresentation::kTagged,
+ Type::Signed32(), MachineRepresentation::kWord32);
+ CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged,
+ Type::Unsigned32(), MachineRepresentation::kWord32);
+ CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
+ Type::None(), MachineRepresentation::kFloat64);
+ CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64,
+ Type::Signed32(), MachineRepresentation::kWord32);
+ CheckChange(IrOpcode::kTruncateFloat64ToInt32,
+ MachineRepresentation::kFloat64, Type::Number(),
+ MachineRepresentation::kWord32);
CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64,
- IrOpcode::kTruncateFloat64ToFloat32, kRepWord32, kRepFloat32);
+ IrOpcode::kTruncateFloat64ToFloat32,
+ MachineRepresentation::kWord32, Type::None(),
+ MachineRepresentation::kFloat32);
CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
- IrOpcode::kChangeFloat64ToInt32, kRepFloat32, kRepWord32);
+ IrOpcode::kTruncateFloat64ToInt32,
+ MachineRepresentation::kFloat32, Type::Number(),
+ MachineRepresentation::kWord32);
}
@@ -471,77 +532,99 @@
RepresentationChangerTester r;
// X -> X is always a nop for any single representation X.
- for (size_t i = 0; i < arraysize(all_reps); i++) {
- r.CheckNop(all_reps[i], all_reps[i]);
+ for (size_t i = 0; i < arraysize(kMachineTypes); i++) {
+ r.CheckNop(kMachineTypes[i].representation(), Type::None(),
+ kMachineTypes[i].representation());
}
// 32-bit floats.
- r.CheckNop(kRepFloat32, kRepFloat32);
- r.CheckNop(kRepFloat32 | kTypeNumber, kRepFloat32);
- r.CheckNop(kRepFloat32, kRepFloat32 | kTypeNumber);
-
- // 32-bit or 64-bit words can be used as branch conditions (kRepBit).
- r.CheckNop(kRepWord32, kRepBit);
- r.CheckNop(kRepWord32, kRepBit | kTypeBool);
- r.CheckNop(kRepWord64, kRepBit);
- r.CheckNop(kRepWord64, kRepBit | kTypeBool);
+ r.CheckNop(MachineRepresentation::kFloat32, Type::None(),
+ MachineRepresentation::kFloat32);
+ r.CheckNop(MachineRepresentation::kFloat32, Type::Number(),
+ MachineRepresentation::kFloat32);
// 32-bit words can be used as smaller word sizes and vice versa, because
// loads from memory implicitly sign or zero extend the value to the
// full machine word size, and stores implicitly truncate.
- r.CheckNop(kRepWord32, kRepWord8);
- r.CheckNop(kRepWord32, kRepWord16);
- r.CheckNop(kRepWord32, kRepWord32);
- r.CheckNop(kRepWord8, kRepWord32);
- r.CheckNop(kRepWord16, kRepWord32);
+ r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
+ MachineRepresentation::kWord8);
+ r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
+ MachineRepresentation::kWord16);
+ r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
+ MachineRepresentation::kWord32);
+ r.CheckNop(MachineRepresentation::kWord8, Type::Signed32(),
+ MachineRepresentation::kWord32);
+ r.CheckNop(MachineRepresentation::kWord16, Type::Signed32(),
+ MachineRepresentation::kWord32);
// kRepBit (result of comparison) is implicitly a wordish thing.
- r.CheckNop(kRepBit, kRepWord8);
- r.CheckNop(kRepBit | kTypeBool, kRepWord8);
- r.CheckNop(kRepBit, kRepWord16);
- r.CheckNop(kRepBit | kTypeBool, kRepWord16);
- r.CheckNop(kRepBit, kRepWord32);
- r.CheckNop(kRepBit | kTypeBool, kRepWord32);
- r.CheckNop(kRepBit, kRepWord64);
- r.CheckNop(kRepBit | kTypeBool, kRepWord64);
+ r.CheckNop(MachineRepresentation::kBit, Type::None(),
+ MachineRepresentation::kWord8);
+ r.CheckNop(MachineRepresentation::kBit, Type::None(),
+ MachineRepresentation::kWord16);
+ r.CheckNop(MachineRepresentation::kBit, Type::None(),
+ MachineRepresentation::kWord32);
+ r.CheckNop(MachineRepresentation::kBit, Type::None(),
+ MachineRepresentation::kWord64);
+ r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
+ MachineRepresentation::kWord8);
+ r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
+ MachineRepresentation::kWord16);
+ r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
+ MachineRepresentation::kWord32);
+ r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
+ MachineRepresentation::kWord64);
}
TEST(TypeErrors) {
RepresentationChangerTester r;
- // Floats cannot be implicitly converted to/from comparison conditions.
- r.CheckTypeError(kRepFloat64, kRepBit);
- r.CheckTypeError(kRepFloat64, kRepBit | kTypeBool);
- r.CheckTypeError(kRepBit, kRepFloat64);
- r.CheckTypeError(kRepBit | kTypeBool, kRepFloat64);
+ // Wordish cannot be implicitly converted to/from comparison conditions.
+ r.CheckTypeError(MachineRepresentation::kWord8, Type::None(),
+ MachineRepresentation::kBit);
+ r.CheckTypeError(MachineRepresentation::kWord16, Type::None(),
+ MachineRepresentation::kBit);
+ r.CheckTypeError(MachineRepresentation::kWord32, Type::None(),
+ MachineRepresentation::kBit);
+ r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
+ MachineRepresentation::kBit);
// Floats cannot be implicitly converted to/from comparison conditions.
- r.CheckTypeError(kRepFloat32, kRepBit);
- r.CheckTypeError(kRepFloat32, kRepBit | kTypeBool);
- r.CheckTypeError(kRepBit, kRepFloat32);
- r.CheckTypeError(kRepBit | kTypeBool, kRepFloat32);
+ r.CheckTypeError(MachineRepresentation::kFloat64, Type::None(),
+ MachineRepresentation::kBit);
+ r.CheckTypeError(MachineRepresentation::kBit, Type::None(),
+ MachineRepresentation::kFloat64);
+ r.CheckTypeError(MachineRepresentation::kBit, Type::Boolean(),
+ MachineRepresentation::kFloat64);
+
+ // Floats cannot be implicitly converted to/from comparison conditions.
+ r.CheckTypeError(MachineRepresentation::kFloat32, Type::None(),
+ MachineRepresentation::kBit);
+ r.CheckTypeError(MachineRepresentation::kBit, Type::None(),
+ MachineRepresentation::kFloat32);
+ r.CheckTypeError(MachineRepresentation::kBit, Type::Boolean(),
+ MachineRepresentation::kFloat32);
// Word64 is internal and shouldn't be implicitly converted.
- r.CheckTypeError(kRepWord64, kRepTagged | kTypeBool);
- r.CheckTypeError(kRepWord64, kRepTagged);
- r.CheckTypeError(kRepWord64, kRepTagged | kTypeBool);
- r.CheckTypeError(kRepTagged, kRepWord64);
- r.CheckTypeError(kRepTagged | kTypeBool, kRepWord64);
+ r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
+ MachineRepresentation::kTagged);
+ r.CheckTypeError(MachineRepresentation::kTagged, Type::None(),
+ MachineRepresentation::kWord64);
+ r.CheckTypeError(MachineRepresentation::kTagged, Type::Boolean(),
+ MachineRepresentation::kWord64);
// Word64 / Word32 shouldn't be implicitly converted.
- r.CheckTypeError(kRepWord64, kRepWord32);
- r.CheckTypeError(kRepWord32, kRepWord64);
- r.CheckTypeError(kRepWord64, kRepWord32 | kTypeInt32);
- r.CheckTypeError(kRepWord32 | kTypeInt32, kRepWord64);
- r.CheckTypeError(kRepWord64, kRepWord32 | kTypeUint32);
- r.CheckTypeError(kRepWord32 | kTypeUint32, kRepWord64);
-
- for (size_t i = 0; i < arraysize(all_reps); i++) {
- for (size_t j = 0; j < arraysize(all_reps); j++) {
- if (i == j) continue;
- // Only a single from representation is allowed.
- r.CheckTypeError(all_reps[i] | all_reps[j], kRepTagged);
- }
- }
+ r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
+ MachineRepresentation::kWord32);
+ r.CheckTypeError(MachineRepresentation::kWord32, Type::None(),
+ MachineRepresentation::kWord64);
+ r.CheckTypeError(MachineRepresentation::kWord32, Type::Signed32(),
+ MachineRepresentation::kWord64);
+ r.CheckTypeError(MachineRepresentation::kWord32, Type::Unsigned32(),
+ MachineRepresentation::kWord64);
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-bytecode-graph-builder.cc b/test/cctest/compiler/test-run-bytecode-graph-builder.cc
new file mode 100644
index 0000000..88555b7
--- /dev/null
+++ b/test/cctest/compiler/test-run-bytecode-graph-builder.cc
@@ -0,0 +1,2339 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utility>
+
+#include "src/compiler/pipeline.h"
+#include "src/execution.h"
+#include "src/handles.h"
+#include "src/interpreter/bytecode-array-builder.h"
+#include "src/interpreter/interpreter.h"
+#include "src/parsing/parser.h"
+#include "test/cctest/cctest.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+
+static const char kFunctionName[] = "f";
+
+static const Token::Value kCompareOperators[] = {
+ Token::Value::EQ, Token::Value::NE, Token::Value::EQ_STRICT,
+ Token::Value::NE_STRICT, Token::Value::LT, Token::Value::LTE,
+ Token::Value::GT, Token::Value::GTE};
+
+static const int SMI_MAX = (1 << 30) - 1;
+static const int SMI_MIN = -(1 << 30);
+
+static MaybeHandle<Object> CallFunction(Isolate* isolate,
+ Handle<JSFunction> function) {
+ return Execution::Call(isolate, function,
+ isolate->factory()->undefined_value(), 0, nullptr);
+}
+
+
+template <class... A>
+static MaybeHandle<Object> CallFunction(Isolate* isolate,
+ Handle<JSFunction> function,
+ A... args) {
+ Handle<Object> argv[] = {args...};
+ return Execution::Call(isolate, function,
+ isolate->factory()->undefined_value(), sizeof...(args),
+ argv);
+}
+
+
+template <class... A>
+class BytecodeGraphCallable {
+ public:
+ BytecodeGraphCallable(Isolate* isolate, Handle<JSFunction> function)
+ : isolate_(isolate), function_(function) {}
+ virtual ~BytecodeGraphCallable() {}
+
+ MaybeHandle<Object> operator()(A... args) {
+ return CallFunction(isolate_, function_, args...);
+ }
+
+ private:
+ Isolate* isolate_;
+ Handle<JSFunction> function_;
+};
+
+
+class BytecodeGraphTester {
+ public:
+ BytecodeGraphTester(Isolate* isolate, Zone* zone, const char* script,
+ const char* filter = kFunctionName)
+ : isolate_(isolate), zone_(zone), script_(script) {
+ i::FLAG_ignition = true;
+ i::FLAG_always_opt = false;
+ i::FLAG_allow_natives_syntax = true;
+ i::FLAG_ignition_fallback_on_eval_and_catch = false;
+ // Set ignition filter flag via SetFlagsFromString to avoid double-free
+ // (or potential leak with StrDup() based on ownership confusion).
+ ScopedVector<char> ignition_filter(64);
+ SNPrintF(ignition_filter, "--ignition-filter=%s", filter);
+ FlagList::SetFlagsFromString(ignition_filter.start(),
+ ignition_filter.length());
+ // Ensure handler table is generated.
+ isolate->interpreter()->Initialize();
+ }
+ virtual ~BytecodeGraphTester() {}
+
+ template <class... A>
+ BytecodeGraphCallable<A...> GetCallable(
+ const char* functionName = kFunctionName) {
+ return BytecodeGraphCallable<A...>(isolate_, GetFunction(functionName));
+ }
+
+ Local<Message> CheckThrowsReturnMessage() {
+ TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_));
+ auto callable = GetCallable<>();
+ MaybeHandle<Object> no_result = callable();
+ CHECK(isolate_->has_pending_exception());
+ CHECK(try_catch.HasCaught());
+ CHECK(no_result.is_null());
+ isolate_->OptionalRescheduleException(true);
+ CHECK(!try_catch.Message().IsEmpty());
+ return try_catch.Message();
+ }
+
+ static Handle<Object> NewObject(const char* script) {
+ return v8::Utils::OpenHandle(*CompileRun(script));
+ }
+
+ private:
+ Isolate* isolate_;
+ Zone* zone_;
+ const char* script_;
+
+ Handle<JSFunction> GetFunction(const char* functionName) {
+ CompileRun(script_);
+ Local<Function> api_function = Local<Function>::Cast(
+ CcTest::global()
+ ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(functionName))
+ .ToLocalChecked());
+ Handle<JSFunction> function =
+ Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function));
+ CHECK(function->shared()->HasBytecodeArray());
+
+ ParseInfo parse_info(zone_, function);
+
+ CompilationInfo compilation_info(&parse_info);
+ compilation_info.SetOptimizing(BailoutId::None(), Handle<Code>());
+ compilation_info.MarkAsDeoptimizationEnabled();
+ // TODO(mythria): Remove this step once parse_info is not needed.
+ CHECK(Compiler::ParseAndAnalyze(&parse_info));
+ compiler::Pipeline pipeline(&compilation_info);
+ Handle<Code> code = pipeline.GenerateCode();
+ function->ReplaceCode(*code);
+
+ return function;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(BytecodeGraphTester);
+};
+
+
+#define SPACE()
+
+#define REPEAT_2(SEP, ...) __VA_ARGS__ SEP() __VA_ARGS__
+#define REPEAT_4(SEP, ...) \
+ REPEAT_2(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__)
+#define REPEAT_8(SEP, ...) \
+ REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_4(SEP, __VA_ARGS__)
+#define REPEAT_16(SEP, ...) \
+ REPEAT_8(SEP, __VA_ARGS__) SEP() REPEAT_8(SEP, __VA_ARGS__)
+#define REPEAT_32(SEP, ...) \
+ REPEAT_16(SEP, __VA_ARGS__) SEP() REPEAT_16(SEP, __VA_ARGS__)
+#define REPEAT_64(SEP, ...) \
+ REPEAT_32(SEP, __VA_ARGS__) SEP() REPEAT_32(SEP, __VA_ARGS__)
+#define REPEAT_128(SEP, ...) \
+ REPEAT_64(SEP, __VA_ARGS__) SEP() REPEAT_64(SEP, __VA_ARGS__)
+#define REPEAT_256(SEP, ...) \
+ REPEAT_128(SEP, __VA_ARGS__) SEP() REPEAT_128(SEP, __VA_ARGS__)
+
+#define REPEAT_127(SEP, ...) \
+ REPEAT_64(SEP, __VA_ARGS__) \
+ SEP() \
+ REPEAT_32(SEP, __VA_ARGS__) \
+ SEP() \
+ REPEAT_16(SEP, __VA_ARGS__) \
+ SEP() \
+ REPEAT_8(SEP, __VA_ARGS__) \
+ SEP() \
+ REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) SEP() __VA_ARGS__
+
+
+template <int N, typename T = Handle<Object>>
+struct ExpectedSnippet {
+ const char* code_snippet;
+ T return_value_and_parameters[N + 1];
+
+ inline T return_value() const { return return_value_and_parameters[0]; }
+
+ inline T parameter(int i) const {
+ CHECK_GE(i, 0);
+ CHECK_LT(i, N);
+ return return_value_and_parameters[1 + i];
+ }
+};
+
+
+TEST(BytecodeGraphBuilderReturnStatements) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"return;", {factory->undefined_value()}},
+ {"return null;", {factory->null_value()}},
+ {"return true;", {factory->true_value()}},
+ {"return false;", {factory->false_value()}},
+ {"return 0;", {factory->NewNumberFromInt(0)}},
+ {"return +1;", {factory->NewNumberFromInt(1)}},
+ {"return -1;", {factory->NewNumberFromInt(-1)}},
+ {"return +127;", {factory->NewNumberFromInt(127)}},
+ {"return -128;", {factory->NewNumberFromInt(-128)}},
+ {"return 0.001;", {factory->NewNumber(0.001)}},
+ {"return 3.7e-60;", {factory->NewNumber(3.7e-60)}},
+ {"return -3.7e60;", {factory->NewNumber(-3.7e60)}},
+ {"return '';", {factory->NewStringFromStaticChars("")}},
+ {"return 'catfood';", {factory->NewStringFromStaticChars("catfood")}},
+ {"return NaN;", {factory->nan_value()}}};
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderPrimitiveExpressions) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"return 1 + 1;", {factory->NewNumberFromInt(2)}},
+ {"return 20 - 30;", {factory->NewNumberFromInt(-10)}},
+ {"return 4 * 100;", {factory->NewNumberFromInt(400)}},
+ {"return 100 / 5;", {factory->NewNumberFromInt(20)}},
+ {"return 25 % 7;", {factory->NewNumberFromInt(4)}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderTwoParameterTests) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<2> snippets[] = {
+ // Integers
+ {"return p1 + p2;",
+ {factory->NewNumberFromInt(-70), factory->NewNumberFromInt(3),
+ factory->NewNumberFromInt(-73)}},
+ {"return p1 + p2 + 3;",
+ {factory->NewNumberFromInt(1139044), factory->NewNumberFromInt(300),
+ factory->NewNumberFromInt(1138741)}},
+ {"return p1 - p2;",
+ {factory->NewNumberFromInt(1100), factory->NewNumberFromInt(1000),
+ factory->NewNumberFromInt(-100)}},
+ {"return p1 * p2;",
+ {factory->NewNumberFromInt(-100000), factory->NewNumberFromInt(1000),
+ factory->NewNumberFromInt(-100)}},
+ {"return p1 / p2;",
+ {factory->NewNumberFromInt(-10), factory->NewNumberFromInt(1000),
+ factory->NewNumberFromInt(-100)}},
+ {"return p1 % p2;",
+ {factory->NewNumberFromInt(5), factory->NewNumberFromInt(373),
+ factory->NewNumberFromInt(16)}},
+ // Doubles
+ {"return p1 + p2;",
+ {factory->NewHeapNumber(9.999), factory->NewHeapNumber(3.333),
+ factory->NewHeapNumber(6.666)}},
+ {"return p1 - p2;",
+ {factory->NewHeapNumber(-3.333), factory->NewHeapNumber(3.333),
+ factory->NewHeapNumber(6.666)}},
+ {"return p1 * p2;",
+ {factory->NewHeapNumber(3.333 * 6.666), factory->NewHeapNumber(3.333),
+ factory->NewHeapNumber(6.666)}},
+ {"return p1 / p2;",
+ {factory->NewHeapNumber(2.25), factory->NewHeapNumber(9),
+ factory->NewHeapNumber(4)}},
+ // Strings
+ {"return p1 + p2;",
+ {factory->NewStringFromStaticChars("abcdef"),
+ factory->NewStringFromStaticChars("abc"),
+ factory->NewStringFromStaticChars("def")}}};
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s(p1, p2) { %s }\n%s(0, 0);", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0), snippets[i].parameter(1))
+ .ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderNamedLoad) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<1> snippets[] = {
+ {"return p1.val;",
+ {factory->NewNumberFromInt(10),
+ BytecodeGraphTester::NewObject("({val : 10})")}},
+ {"return p1[\"name\"];",
+ {factory->NewStringFromStaticChars("abc"),
+ BytecodeGraphTester::NewObject("({name : 'abc'})")}},
+ {"'use strict'; return p1.val;",
+ {factory->NewNumberFromInt(10),
+ BytecodeGraphTester::NewObject("({val : 10 })")}},
+ {"'use strict'; return p1[\"val\"];",
+ {factory->NewNumberFromInt(10),
+ BytecodeGraphTester::NewObject("({val : 10, name : 'abc'})")}},
+ {"var b;\n" REPEAT_127(SPACE, " b = p1.name; ") " return p1.name;\n",
+ {factory->NewStringFromStaticChars("abc"),
+ BytecodeGraphTester::NewObject("({name : 'abc'})")}},
+ {"'use strict'; var b;\n"
+ REPEAT_127(SPACE, " b = p1.name; ")
+ "return p1.name;\n",
+ {factory->NewStringFromStaticChars("abc"),
+ BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(2048);
+ SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderKeyedLoad) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<2> snippets[] = {
+ {"return p1[p2];",
+ {factory->NewNumberFromInt(10),
+ BytecodeGraphTester::NewObject("({val : 10})"),
+ factory->NewStringFromStaticChars("val")}},
+ {"return p1[100];",
+ {factory->NewStringFromStaticChars("abc"),
+ BytecodeGraphTester::NewObject("({100 : 'abc'})"),
+ factory->NewNumberFromInt(0)}},
+ {"var b = 100; return p1[b];",
+ {factory->NewStringFromStaticChars("abc"),
+ BytecodeGraphTester::NewObject("({100 : 'abc'})"),
+ factory->NewNumberFromInt(0)}},
+ {"'use strict'; return p1[p2];",
+ {factory->NewNumberFromInt(10),
+ BytecodeGraphTester::NewObject("({val : 10 })"),
+ factory->NewStringFromStaticChars("val")}},
+ {"'use strict'; return p1[100];",
+ {factory->NewNumberFromInt(10),
+ BytecodeGraphTester::NewObject("({100 : 10})"),
+ factory->NewNumberFromInt(0)}},
+ {"'use strict'; var b = p2; return p1[b];",
+ {factory->NewStringFromStaticChars("abc"),
+ BytecodeGraphTester::NewObject("({100 : 'abc'})"),
+ factory->NewNumberFromInt(100)}},
+ {"var b;\n" REPEAT_127(SPACE, " b = p1[p2]; ") " return p1[p2];\n",
+ {factory->NewStringFromStaticChars("abc"),
+ BytecodeGraphTester::NewObject("({100 : 'abc'})"),
+ factory->NewNumberFromInt(100)}},
+ {"'use strict'; var b;\n" REPEAT_127(SPACE,
+ " b = p1[p2]; ") "return p1[p2];\n",
+ {factory->NewStringFromStaticChars("abc"),
+ BytecodeGraphTester::NewObject("({ 100 : 'abc'})"),
+ factory->NewNumberFromInt(100)}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(2048);
+ SNPrintF(script, "function %s(p1, p2) { %s };\n%s(0);", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0), snippets[i].parameter(1))
+ .ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderNamedStore) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<1> snippets[] = {
+ {"return p1.val = 20;",
+ {factory->NewNumberFromInt(20),
+ BytecodeGraphTester::NewObject("({val : 10})")}},
+ {"p1.type = 'int'; return p1.type;",
+ {factory->NewStringFromStaticChars("int"),
+ BytecodeGraphTester::NewObject("({val : 10})")}},
+ {"p1.name = 'def'; return p1[\"name\"];",
+ {factory->NewStringFromStaticChars("def"),
+ BytecodeGraphTester::NewObject("({name : 'abc'})")}},
+ {"'use strict'; p1.val = 20; return p1.val;",
+ {factory->NewNumberFromInt(20),
+ BytecodeGraphTester::NewObject("({val : 10 })")}},
+ {"'use strict'; return p1.type = 'int';",
+ {factory->NewStringFromStaticChars("int"),
+ BytecodeGraphTester::NewObject("({val : 10})")}},
+ {"'use strict'; p1.val = 20; return p1[\"val\"];",
+ {factory->NewNumberFromInt(20),
+ BytecodeGraphTester::NewObject("({val : 10, name : 'abc'})")}},
+ {"var b = 'abc';\n" REPEAT_127(
+ SPACE, " p1.name = b; ") " p1.name = 'def'; return p1.name;\n",
+ {factory->NewStringFromStaticChars("def"),
+ BytecodeGraphTester::NewObject("({name : 'abc'})")}},
+ {"'use strict'; var b = 'def';\n" REPEAT_127(
+ SPACE, " p1.name = 'abc'; ") "p1.name = b; return p1.name;\n",
+ {factory->NewStringFromStaticChars("def"),
+ BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(3072);
+ SNPrintF(script, "function %s(p1) { %s };\n%s({});", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderKeyedStore) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<2> snippets[] = {
+ {"p1[p2] = 20; return p1[p2];",
+ {factory->NewNumberFromInt(20),
+ BytecodeGraphTester::NewObject("({val : 10})"),
+ factory->NewStringFromStaticChars("val")}},
+ {"return p1[100] = 'def';",
+ {factory->NewStringFromStaticChars("def"),
+ BytecodeGraphTester::NewObject("({100 : 'abc'})"),
+ factory->NewNumberFromInt(0)}},
+ {"var b = 100; p1[b] = 'def'; return p1[b];",
+ {factory->NewStringFromStaticChars("def"),
+ BytecodeGraphTester::NewObject("({100 : 'abc'})"),
+ factory->NewNumberFromInt(0)}},
+ {"'use strict'; p1[p2] = 20; return p1[p2];",
+ {factory->NewNumberFromInt(20),
+ BytecodeGraphTester::NewObject("({val : 10 })"),
+ factory->NewStringFromStaticChars("val")}},
+ {"'use strict'; return p1[100] = 20;",
+ {factory->NewNumberFromInt(20),
+ BytecodeGraphTester::NewObject("({100 : 10})"),
+ factory->NewNumberFromInt(0)}},
+ {"'use strict'; var b = p2; p1[b] = 'def'; return p1[b];",
+ {factory->NewStringFromStaticChars("def"),
+ BytecodeGraphTester::NewObject("({100 : 'abc'})"),
+ factory->NewNumberFromInt(100)}},
+ {"var b;\n" REPEAT_127(
+ SPACE, " b = p1[p2]; ") " p1[p2] = 'def'; return p1[p2];\n",
+ {factory->NewStringFromStaticChars("def"),
+ BytecodeGraphTester::NewObject("({100 : 'abc'})"),
+ factory->NewNumberFromInt(100)}},
+ {"'use strict'; var b;\n" REPEAT_127(
+ SPACE, " b = p1[p2]; ") " p1[p2] = 'def'; return p1[p2];\n",
+ {factory->NewStringFromStaticChars("def"),
+ BytecodeGraphTester::NewObject("({ 100 : 'abc'})"),
+ factory->NewNumberFromInt(100)}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(2048);
+ SNPrintF(script, "function %s(p1, p2) { %s };\n%s({});", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderPropertyCall) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<1> snippets[] = {
+ {"return p1.func();",
+ {factory->NewNumberFromInt(25),
+ BytecodeGraphTester::NewObject("({func() { return 25; }})")}},
+ {"return p1.func('abc');",
+ {factory->NewStringFromStaticChars("abc"),
+ BytecodeGraphTester::NewObject("({func(a) { return a; }})")}},
+ {"return p1.func(1, 2, 3, 4, 5, 6, 7, 8);",
+ {factory->NewNumberFromInt(36),
+ BytecodeGraphTester::NewObject(
+ "({func(a, b, c, d, e, f, g, h) {\n"
+ " return a + b + c + d + e + f + g + h;}})")}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(2048);
+ SNPrintF(script, "function %s(p1) { %s };\n%s({func() {}});", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderCallNew) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"function counter() { this.count = 20; }\n"
+ "function f() {\n"
+ " var c = new counter();\n"
+ " return c.count;\n"
+ "}; f()",
+ {factory->NewNumberFromInt(20)}},
+ {"function counter(arg0) { this.count = 17; this.x = arg0; }\n"
+ "function f() {\n"
+ " var c = new counter(6);\n"
+ " return c.count + c.x;\n"
+ "}; f()",
+ {factory->NewNumberFromInt(23)}},
+ {"function counter(arg0, arg1) {\n"
+ " this.count = 17; this.x = arg0; this.y = arg1;\n"
+ "}\n"
+ "function f() {\n"
+ " var c = new counter(3, 5);\n"
+ " return c.count + c.x + c.y;\n"
+ "}; f()",
+ {factory->NewNumberFromInt(25)}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderCreateClosure) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"function f() {\n"
+ " function counter() { this.count = 20; }\n"
+ " var c = new counter();\n"
+ " return c.count;\n"
+ "}; f()",
+ {factory->NewNumberFromInt(20)}},
+ {"function f() {\n"
+ " function counter(arg0) { this.count = 17; this.x = arg0; }\n"
+ " var c = new counter(6);\n"
+ " return c.count + c.x;\n"
+ "}; f()",
+ {factory->NewNumberFromInt(23)}},
+ {"function f() {\n"
+ " function counter(arg0, arg1) {\n"
+ " this.count = 17; this.x = arg0; this.y = arg1;\n"
+ " }\n"
+ " var c = new counter(3, 5);\n"
+ " return c.count + c.x + c.y;\n"
+ "}; f()",
+ {factory->NewNumberFromInt(25)}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderCallRuntime) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<1> snippets[] = {
+ {"function f(arg0) { return %MaxSmi(); }\nf()",
+ {factory->NewNumberFromInt(Smi::kMaxValue), factory->undefined_value()}},
+ {"function f(arg0) { return %IsArray(arg0) }\nf(undefined)",
+ {factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}},
+ {"function f(arg0) { return %Add(arg0, 2) }\nf(1)",
+ {factory->NewNumberFromInt(5), factory->NewNumberFromInt(3)}},
+ {"function f(arg0) { return %spread_arguments(arg0).length }\nf([])",
+ {factory->NewNumberFromInt(3),
+ BytecodeGraphTester::NewObject("[1, 2, 3]")}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderGlobals) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"var global = 321;\n function f() { return global; };\n f();",
+ {factory->NewNumberFromInt(321)}},
+ {"var global = 321;\n"
+ "function f() { global = 123; return global };\n f();",
+ {factory->NewNumberFromInt(123)}},
+ {"var global = function() { return 'abc'};\n"
+ "function f() { return global(); };\n f();",
+ {factory->NewStringFromStaticChars("abc")}},
+ {"var global = 456;\n"
+ "function f() { 'use strict'; return global; };\n f();",
+ {factory->NewNumberFromInt(456)}},
+ {"var global = 987;\n"
+ "function f() { 'use strict'; global = 789; return global };\n f();",
+ {factory->NewNumberFromInt(789)}},
+ {"var global = function() { return 'xyz'};\n"
+ "function f() { 'use strict'; return global(); };\n f();",
+ {factory->NewStringFromStaticChars("xyz")}},
+ {"var global = 'abc'; var global_obj = {val:123};\n"
+ "function f() {\n" REPEAT_127(
+ SPACE, " var b = global_obj.name;\n") "return global; };\n f();\n",
+ {factory->NewStringFromStaticChars("abc")}},
+ {"var global = 'abc'; var global_obj = {val:123};\n"
+ "function f() { 'use strict';\n" REPEAT_127(
+ SPACE, " var b = global_obj.name;\n") "global = 'xyz'; return "
+ "global };\n f();\n",
+ {factory->NewStringFromStaticChars("xyz")}},
+ {"function f() { return typeof(undeclared_var); }\n; f();\n",
+ {factory->NewStringFromStaticChars("undefined")}},
+ {"var defined_var = 10; function f() { return typeof(defined_var); }\n; "
+ "f();\n",
+ {factory->NewStringFromStaticChars("number")}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderToObject) {
+ // TODO(mythria): tests for ToObject. Needs ForIn.
+}
+
+
+TEST(BytecodeGraphBuilderToName) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"var a = 'val'; var obj = {[a] : 10}; return obj.val;",
+ {factory->NewNumberFromInt(10)}},
+ {"var a = 20; var obj = {[a] : 10}; return obj['20'];",
+ {factory->NewNumberFromInt(10)}},
+ {"var a = 20; var obj = {[a] : 10}; return obj[20];",
+ {factory->NewNumberFromInt(10)}},
+ {"var a = {val:23}; var obj = {[a] : 10}; return obj[a];",
+ {factory->NewNumberFromInt(10)}},
+ {"var a = {val:23}; var obj = {[a] : 10}; return obj['[object Object]'];",
+ {factory->NewNumberFromInt(10)}},
+ {"var a = {toString : function() { return 'x'}};\n"
+ "var obj = {[a] : 10};\n"
+ "return obj.x;",
+ {factory->NewNumberFromInt(10)}},
+ {"var a = {valueOf : function() { return 'x'}};\n"
+ "var obj = {[a] : 10};\n"
+ "return obj.x;",
+ {factory->undefined_value()}},
+ {"var a = {[Symbol.toPrimitive] : function() { return 'x'}};\n"
+ "var obj = {[a] : 10};\n"
+ "return obj.x;",
+ {factory->NewNumberFromInt(10)}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s({});", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderLogicalNot) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<1> snippets[] = {
+ {"return !p1;",
+ {factory->false_value(),
+ BytecodeGraphTester::NewObject("({val : 10})")}},
+ {"return !p1;", {factory->true_value(), factory->NewNumberFromInt(0)}},
+ {"return !p1;", {factory->true_value(), factory->undefined_value()}},
+ {"return !p1;", {factory->false_value(), factory->NewNumberFromInt(10)}},
+ {"return !p1;", {factory->false_value(), factory->true_value()}},
+ {"return !p1;",
+ {factory->false_value(), factory->NewStringFromStaticChars("abc")}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderTypeOf) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<1> snippets[] = {
+ {"return typeof p1;",
+ {factory->NewStringFromStaticChars("object"),
+ BytecodeGraphTester::NewObject("({val : 10})")}},
+ {"return typeof p1;",
+ {factory->NewStringFromStaticChars("undefined"),
+ factory->undefined_value()}},
+ {"return typeof p1;",
+ {factory->NewStringFromStaticChars("number"),
+ factory->NewNumberFromInt(10)}},
+ {"return typeof p1;",
+ {factory->NewStringFromStaticChars("boolean"), factory->true_value()}},
+ {"return typeof p1;",
+ {factory->NewStringFromStaticChars("string"),
+ factory->NewStringFromStaticChars("abc")}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderCountOperation) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<1> snippets[] = {
+ {"return ++p1;",
+ {factory->NewNumberFromInt(11), factory->NewNumberFromInt(10)}},
+ {"return p1++;",
+ {factory->NewNumberFromInt(10), factory->NewNumberFromInt(10)}},
+ {"return p1++ + 10;",
+ {factory->NewHeapNumber(15.23), factory->NewHeapNumber(5.23)}},
+ {"return 20 + ++p1;",
+ {factory->NewHeapNumber(27.23), factory->NewHeapNumber(6.23)}},
+ {"return --p1;",
+ {factory->NewHeapNumber(9.8), factory->NewHeapNumber(10.8)}},
+ {"return p1--;",
+ {factory->NewHeapNumber(10.8), factory->NewHeapNumber(10.8)}},
+ {"return p1-- + 10;",
+ {factory->NewNumberFromInt(20), factory->NewNumberFromInt(10)}},
+ {"return 20 + --p1;",
+ {factory->NewNumberFromInt(29), factory->NewNumberFromInt(10)}},
+ {"return p1.val--;",
+ {factory->NewNumberFromInt(10),
+ BytecodeGraphTester::NewObject("({val : 10})")}},
+ {"return ++p1['val'];",
+ {factory->NewNumberFromInt(11),
+ BytecodeGraphTester::NewObject("({val : 10})")}},
+ {"return ++p1[1];",
+ {factory->NewNumberFromInt(11),
+ BytecodeGraphTester::NewObject("({1 : 10})")}},
+ {" function inner() { return p1 } return --p1;",
+ {factory->NewNumberFromInt(9), factory->NewNumberFromInt(10)}},
+ {" function inner() { return p1 } return p1--;",
+ {factory->NewNumberFromInt(10), factory->NewNumberFromInt(10)}},
+ {"return ++p1;",
+ {factory->nan_value(), factory->NewStringFromStaticChars("String")}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderDelete) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<1> snippets[] = {
+ {"return delete p1.val;",
+ {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
+ {"delete p1.val; return p1.val;",
+ {factory->undefined_value(),
+ BytecodeGraphTester::NewObject("({val : 10})")}},
+ {"delete p1.name; return p1.val;",
+ {factory->NewNumberFromInt(10),
+ BytecodeGraphTester::NewObject("({val : 10, name:'abc'})")}},
+ {"'use strict'; return delete p1.val;",
+ {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
+ {"'use strict'; delete p1.val; return p1.val;",
+ {factory->undefined_value(),
+ BytecodeGraphTester::NewObject("({val : 10})")}},
+ {"'use strict'; delete p1.name; return p1.val;",
+ {factory->NewNumberFromInt(10),
+ BytecodeGraphTester::NewObject("({val : 10, name:'abc'})")}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderDeleteGlobal) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"var obj = {val : 10, type : 'int'};"
+ "function f() {return delete obj;};",
+ {factory->false_value()}},
+ {"function f() {return delete this;};", {factory->true_value()}},
+ {"var obj = {val : 10, type : 'int'};"
+ "function f() {return delete obj.val;};",
+ {factory->true_value()}},
+ {"var obj = {val : 10, type : 'int'};"
+ "function f() {'use strict'; return delete obj.val;};",
+ {factory->true_value()}},
+ {"var obj = {val : 10, type : 'int'};"
+ "function f() {delete obj.val; return obj.val;};",
+ {factory->undefined_value()}},
+ {"var obj = {val : 10, type : 'int'};"
+ "function f() {'use strict'; delete obj.val; return obj.val;};",
+ {factory->undefined_value()}},
+ {"var obj = {1 : 10, 2 : 20};"
+ "function f() { return delete obj[1]; };",
+ {factory->true_value()}},
+ {"var obj = {1 : 10, 2 : 20};"
+ "function f() { 'use strict'; return delete obj[1];};",
+ {factory->true_value()}},
+ {"obj = {1 : 10, 2 : 20};"
+ "function f() { delete obj[1]; return obj[2];};",
+ {factory->NewNumberFromInt(20)}},
+ {"function f() {"
+ " var obj = {1 : 10, 2 : 20};"
+ " function inner() { return obj[1]; };"
+ " return delete obj[1];"
+ "}",
+ {factory->true_value()}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "%s %s({});", snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderDeleteLookupSlot) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ // TODO(mythria): Add more tests when we have support for LdaLookupSlot.
+ const char* function_prologue = "var f;"
+ "var x = 1;"
+ "y = 10;"
+ "var obj = {val:10};"
+ "var z = 30;"
+ "function f1() {"
+ " var z = 20;"
+ " eval(\"function t() {";
+ const char* function_epilogue = " }; f = t; t();\");"
+ "}"
+ "f1();";
+
+ ExpectedSnippet<0> snippets[] = {
+ {"return delete y;", {factory->true_value()}},
+ {"return delete z;", {factory->false_value()}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
+ function_epilogue);
+
+ BytecodeGraphTester tester(isolate, zone, script.start(), "t");
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderLookupSlot) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ const char* function_prologue = "var f;"
+ "var x = 12;"
+ "y = 10;"
+ "var obj = {val:3.1414};"
+ "var z = 30;"
+ "function f1() {"
+ " var z = 20;"
+ " eval(\"function t() {";
+ const char* function_epilogue = " }; f = t; t();\");"
+ "}"
+ "f1();";
+
+ ExpectedSnippet<0> snippets[] = {
+ {"return x;", {factory->NewNumber(12)}},
+ {"return obj.val;", {factory->NewNumber(3.1414)}},
+ {"return typeof x;", {factory->NewStringFromStaticChars("number")}},
+ {"return typeof dummy;",
+ {factory->NewStringFromStaticChars("undefined")}},
+ {"x = 23; return x;", {factory->NewNumber(23)}},
+ {"'use strict'; obj.val = 23.456; return obj.val;",
+ {factory->NewNumber(23.456)}}};
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
+ function_epilogue);
+
+ BytecodeGraphTester tester(isolate, zone, script.start(), "t");
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderLookupSlotWide) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ const char* function_prologue =
+ "var f;"
+ "var x = 12;"
+ "y = 10;"
+ "var obj = {val:3.1414};"
+ "var z = 30;"
+ "function f1() {"
+ " var z = 20;"
+ " eval(\"function t() {";
+ const char* function_epilogue =
+ " }; f = t; t();\");"
+ "}"
+ "f1();";
+
+ ExpectedSnippet<0> snippets[] = {
+ {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return x;",
+ {factory->NewNumber(12)}},
+ {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return typeof x;",
+ {factory->NewStringFromStaticChars("number")}},
+ {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return x = 23;",
+ {factory->NewNumber(23)}},
+ {"'use strict';" REPEAT_256(SPACE, "y = 2.3;") "return obj.val = 23.456;",
+ {factory->NewNumber(23.456)}}};
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(3072);
+ SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
+ function_epilogue);
+
+ BytecodeGraphTester tester(isolate, zone, script.start(), "t");
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderCallLookupSlot) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"g = function(){ return 2 }; eval(''); return g();",
+ {handle(Smi::FromInt(2), isolate)}},
+ {"g = function(){ return 2 }; eval('g = function() {return 3}');\n"
+ "return g();",
+ {handle(Smi::FromInt(3), isolate)}},
+ {"g = { x: function(){ return this.y }, y: 20 };\n"
+ "eval('g = { x: g.x, y: 30 }');\n"
+ "return g.x();",
+ {handle(Smi::FromInt(30), isolate)}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderEval) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"return eval('1;');", {handle(Smi::FromInt(1), isolate)}},
+ {"return eval('100 * 20;');", {handle(Smi::FromInt(2000), isolate)}},
+ {"var x = 10; return eval('x + 20;');",
+ {handle(Smi::FromInt(30), isolate)}},
+ {"var x = 10; eval('x = 33;'); return x;",
+ {handle(Smi::FromInt(33), isolate)}},
+ {"'use strict'; var x = 20; var z = 0;\n"
+ "eval('var x = 33; z = x;'); return x + z;",
+ {handle(Smi::FromInt(53), isolate)}},
+ {"eval('var x = 33;'); eval('var y = x + 20'); return x + y;",
+ {handle(Smi::FromInt(86), isolate)}},
+ {"var x = 1; eval('for(i = 0; i < 10; i++) x = x + 1;'); return x",
+ {handle(Smi::FromInt(11), isolate)}},
+ {"var x = 10; eval('var x = 20;'); return x;",
+ {handle(Smi::FromInt(20), isolate)}},
+ {"var x = 1; eval('\"use strict\"; var x = 2;'); return x;",
+ {handle(Smi::FromInt(1), isolate)}},
+ {"'use strict'; var x = 1; eval('var x = 2;'); return x;",
+ {handle(Smi::FromInt(1), isolate)}},
+ {"var x = 10; eval('x + 20;'); return typeof x;",
+ {factory->NewStringFromStaticChars("number")}},
+ {"eval('var y = 10;'); return typeof unallocated;",
+ {factory->NewStringFromStaticChars("undefined")}},
+ {"'use strict'; eval('var y = 10;'); return typeof unallocated;",
+ {factory->NewStringFromStaticChars("undefined")}},
+ {"eval('var x = 10;'); return typeof x;",
+ {factory->NewStringFromStaticChars("number")}},
+ {"var x = {}; eval('var x = 10;'); return typeof x;",
+ {factory->NewStringFromStaticChars("number")}},
+ {"'use strict'; var x = {}; eval('var x = 10;'); return typeof x;",
+ {factory->NewStringFromStaticChars("object")}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderEvalParams) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+
+ ExpectedSnippet<1> snippets[] = {
+ {"var x = 10; return eval('x + p1;');",
+ {handle(Smi::FromInt(30), isolate), handle(Smi::FromInt(20), isolate)}},
+ {"var x = 10; eval('p1 = x;'); return p1;",
+ {handle(Smi::FromInt(10), isolate), handle(Smi::FromInt(20), isolate)}},
+ {"var a = 10;"
+ "function inner() { return eval('a + p1;');}"
+ "return inner();",
+ {handle(Smi::FromInt(30), isolate), handle(Smi::FromInt(20), isolate)}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s(p1) { %s }\n%s(0);", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderEvalGlobal) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"function add_global() { eval('function f() { z = 33; }; f()'); };"
+ "function f() { add_global(); return z; }; f();",
+ {handle(Smi::FromInt(33), isolate)}},
+ {"function add_global() {\n"
+ " eval('\"use strict\"; function f() { y = 33; };"
+ " try { f() } catch(e) {}');\n"
+ "}\n"
+ "function f() { add_global(); return typeof y; } f();",
+ {factory->NewStringFromStaticChars("undefined")}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+bool get_compare_result(Token::Value opcode, Handle<Object> lhs_value,
+ Handle<Object> rhs_value) {
+ switch (opcode) {
+ case Token::Value::EQ:
+ return Object::Equals(lhs_value, rhs_value).FromJust();
+ case Token::Value::NE:
+ return !Object::Equals(lhs_value, rhs_value).FromJust();
+ case Token::Value::EQ_STRICT:
+ return lhs_value->StrictEquals(*rhs_value);
+ case Token::Value::NE_STRICT:
+ return !lhs_value->StrictEquals(*rhs_value);
+ case Token::Value::LT:
+ return Object::LessThan(lhs_value, rhs_value).FromJust();
+ case Token::Value::LTE:
+ return Object::LessThanOrEqual(lhs_value, rhs_value).FromJust();
+ case Token::Value::GT:
+ return Object::GreaterThan(lhs_value, rhs_value).FromJust();
+ case Token::Value::GTE:
+ return Object::GreaterThanOrEqual(lhs_value, rhs_value).FromJust();
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+
+const char* get_code_snippet(Token::Value opcode) {
+ switch (opcode) {
+ case Token::Value::EQ:
+ return "return p1 == p2;";
+ case Token::Value::NE:
+ return "return p1 != p2;";
+ case Token::Value::EQ_STRICT:
+ return "return p1 === p2;";
+ case Token::Value::NE_STRICT:
+ return "return p1 !== p2;";
+ case Token::Value::LT:
+ return "return p1 < p2;";
+ case Token::Value::LTE:
+ return "return p1 <= p2;";
+ case Token::Value::GT:
+ return "return p1 > p2;";
+ case Token::Value::GTE:
+ return "return p1 >= p2;";
+ default:
+ UNREACHABLE();
+ return "";
+ }
+}
+
+
+TEST(BytecodeGraphBuilderCompare) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+ Handle<Object> lhs_values[] = {
+ factory->NewNumberFromInt(10), factory->NewHeapNumber(3.45),
+ factory->NewStringFromStaticChars("abc"),
+ factory->NewNumberFromInt(SMI_MAX), factory->NewNumberFromInt(SMI_MIN)};
+ Handle<Object> rhs_values[] = {factory->NewNumberFromInt(10),
+ factory->NewStringFromStaticChars("10"),
+ factory->NewNumberFromInt(20),
+ factory->NewStringFromStaticChars("abc"),
+ factory->NewHeapNumber(3.45),
+ factory->NewNumberFromInt(SMI_MAX),
+ factory->NewNumberFromInt(SMI_MIN)};
+
+ for (size_t i = 0; i < arraysize(kCompareOperators); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s(p1, p2) { %s }\n%s({}, {});", kFunctionName,
+ get_code_snippet(kCompareOperators[i]), kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
+ for (size_t j = 0; j < arraysize(lhs_values); j++) {
+ for (size_t k = 0; k < arraysize(rhs_values); k++) {
+ Handle<Object> return_value =
+ callable(lhs_values[j], rhs_values[k]).ToHandleChecked();
+ bool result = get_compare_result(kCompareOperators[i], lhs_values[j],
+ rhs_values[k]);
+ CHECK(return_value->SameValue(*factory->ToBoolean(result)));
+ }
+ }
+ }
+}
+
+
+TEST(BytecodeGraphBuilderTestIn) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<2> snippets[] = {
+ {"return p2 in p1;",
+ {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})"),
+ factory->NewStringFromStaticChars("val")}},
+ {"return p2 in p1;",
+ {factory->true_value(), BytecodeGraphTester::NewObject("[]"),
+ factory->NewStringFromStaticChars("length")}},
+ {"return p2 in p1;",
+ {factory->true_value(), BytecodeGraphTester::NewObject("[]"),
+ factory->NewStringFromStaticChars("toString")}},
+ {"return p2 in p1;",
+ {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})"),
+ factory->NewStringFromStaticChars("toString")}},
+ {"return p2 in p1;",
+ {factory->false_value(), BytecodeGraphTester::NewObject("({val : 10})"),
+ factory->NewStringFromStaticChars("abc")}},
+ {"return p2 in p1;",
+ {factory->false_value(), BytecodeGraphTester::NewObject("({val : 10})"),
+ factory->NewNumberFromInt(10)}},
+ {"return p2 in p1;",
+ {factory->true_value(), BytecodeGraphTester::NewObject("({10 : 'val'})"),
+ factory->NewNumberFromInt(10)}},
+ {"return p2 in p1;",
+ {factory->false_value(),
+ BytecodeGraphTester::NewObject("({10 : 'val'})"),
+ factory->NewNumberFromInt(1)}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s(p1, p2) { %s }\n%s({}, {});", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0), snippets[i].parameter(1))
+ .ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderTestInstanceOf) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<1> snippets[] = {
+ {"return p1 instanceof Object;",
+ {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
+ {"return p1 instanceof String;",
+ {factory->false_value(), factory->NewStringFromStaticChars("string")}},
+ {"var cons = function() {};"
+ "var obj = new cons();"
+ "return obj instanceof cons;",
+ {factory->true_value(), factory->undefined_value()}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderThrow) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+
+ // TODO(mythria): Add more tests when real try-catch and deoptimization
+ // information are supported.
+ ExpectedSnippet<0, const char*> snippets[] = {
+ {"throw undefined;", {"Uncaught undefined"}},
+ {"throw 1;", {"Uncaught 1"}},
+ {"throw 'Error';", {"Uncaught Error"}},
+ {"throw 'Error1'; throw 'Error2'", {"Uncaught Error1"}},
+ // TODO(mythria): Enable these tests when JumpIfTrue is supported.
+ // {"var a = true; if (a) { throw 'Error'; }", {"Error"}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
+ v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value());
+ CHECK(
+ message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
+ .FromJust());
+ }
+}
+
+
+TEST(BytecodeGraphBuilderContext) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"var x = 'outer';"
+ "function f() {"
+ " 'use strict';"
+ " {"
+ " let x = 'inner';"
+ " (function() {x});"
+ " }"
+ "return(x);"
+ "}"
+ "f();",
+ {factory->NewStringFromStaticChars("outer")}},
+ {"var x = 'outer';"
+ "function f() {"
+ " 'use strict';"
+ " {"
+ " let x = 'inner ';"
+ " var innerFunc = function() {return x};"
+ " }"
+ "return(innerFunc() + x);"
+ "}"
+ "f();",
+ {factory->NewStringFromStaticChars("inner outer")}},
+ {"var x = 'outer';"
+ "function f() {"
+ " 'use strict';"
+ " {"
+ " let x = 'inner ';"
+ " var innerFunc = function() {return x;};"
+ " {"
+ " let x = 'innermost ';"
+ " var innerMostFunc = function() {return x + innerFunc();};"
+ " }"
+ " x = 'inner_changed ';"
+ " }"
+ " return(innerMostFunc() + x);"
+ "}"
+ "f();",
+ {factory->NewStringFromStaticChars("innermost inner_changed outer")}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "%s", snippets[i].code_snippet);
+
+ BytecodeGraphTester tester(isolate, zone, script.start(), "f");
+ auto callable = tester.GetCallable<>("f");
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderLoadContext) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<1> snippets[] = {
+ {"function Outer() {"
+ " var outerVar = 2;"
+ " function Inner(innerArg) {"
+ " this.innerFunc = function () {"
+ " return outerVar * innerArg;"
+ " };"
+ " };"
+ " this.getInnerFunc = function GetInner() {"
+ " return new Inner(3).innerFunc;"
+ " }"
+ "}"
+ "var f = new Outer().getInnerFunc();"
+ "f();",
+ {factory->NewNumberFromInt(6), factory->undefined_value()}},
+ {"function Outer() {"
+ " var outerVar = 2;"
+ " function Inner(innerArg) {"
+ " this.innerFunc = function () {"
+ " outerVar = innerArg; return outerVar;"
+ " };"
+ " };"
+ " this.getInnerFunc = function GetInner() {"
+ " return new Inner(10).innerFunc;"
+ " }"
+ "}"
+ "var f = new Outer().getInnerFunc();"
+ "f();",
+ {factory->NewNumberFromInt(10), factory->undefined_value()}},
+ {"function testOuter(outerArg) {"
+ " this.testinnerFunc = function testInner(innerArg) {"
+ " return innerArg + outerArg;"
+ " }"
+ "}"
+ "var f = new testOuter(10).testinnerFunc;"
+ "f(0);",
+ {factory->NewNumberFromInt(14), factory->NewNumberFromInt(4)}},
+ {"function testOuter(outerArg) {"
+ " var outerVar = outerArg * 2;"
+ " this.testinnerFunc = function testInner(innerArg) {"
+ " outerVar = outerVar + innerArg; return outerVar;"
+ " }"
+ "}"
+ "var f = new testOuter(10).testinnerFunc;"
+ "f(0);",
+ {factory->NewNumberFromInt(24), factory->NewNumberFromInt(4)}}};
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "%s", snippets[i].code_snippet);
+
+ BytecodeGraphTester tester(isolate, zone, script.start(), "*");
+ auto callable = tester.GetCallable<Handle<Object>>("f");
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderCreateArgumentsNoParameters) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"function f() {return arguments[0];}", {factory->undefined_value()}},
+ {"function f(a) {return arguments[0];}", {factory->undefined_value()}},
+ {"function f() {'use strict'; return arguments[0];}",
+ {factory->undefined_value()}},
+ {"function f(a) {'use strict'; return arguments[0];}",
+ {factory->undefined_value()}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderCreateArguments) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<3> snippets[] = {
+ {"function f(a, b, c) {return arguments[0];}",
+ {factory->NewNumberFromInt(1), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+ {"function f(a, b, c) {return arguments[3];}",
+ {factory->undefined_value(), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+ {"function f(a, b, c) { b = c; return arguments[1];}",
+ {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+ {"function f(a, b, c) {'use strict'; return arguments[0];}",
+ {factory->NewNumberFromInt(1), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+ {"function f(a, b, c) {'use strict'; return arguments[3];}",
+ {factory->undefined_value(), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+ {"function f(a, b, c) {'use strict'; b = c; return arguments[1];}",
+ {factory->NewNumberFromInt(2), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+ {"function inline_func(a, b) { return arguments[0] }"
+ "function f(a, b, c) {return inline_func(b, c) + arguments[0];}",
+ {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(2), factory->NewNumberFromInt(30)}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable =
+ tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0), snippets[i].parameter(1),
+ snippets[i].parameter(2))
+ .ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderRegExpLiterals) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"return /abd/.exec('cccabbdd');", {factory->null_value()}},
+ {"return /ab+d/.exec('cccabbdd')[0];",
+ {factory->NewStringFromStaticChars("abbd")}},
+ {"var a = 3.1414;"
+ REPEAT_256(SPACE, "a = 3.1414;")
+ "return /ab+d/.exec('cccabbdd')[0];",
+ {factory->NewStringFromStaticChars("abbd")}},
+ {"return /ab+d/.exec('cccabbdd')[1];", {factory->undefined_value()}},
+ {"return /AbC/i.exec('ssaBC')[0];",
+ {factory->NewStringFromStaticChars("aBC")}},
+ {"return 'ssaBC'.match(/AbC/i)[0];",
+ {factory->NewStringFromStaticChars("aBC")}},
+ {"return 'ssaBCtAbC'.match(/(AbC)/gi)[1];",
+ {factory->NewStringFromStaticChars("AbC")}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(4096);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderArrayLiterals) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"return [][0];", {factory->undefined_value()}},
+ {"return [1, 3, 2][1];", {factory->NewNumberFromInt(3)}},
+ {"var a;" REPEAT_256(SPACE, "a = 9.87;") "return [1, 3, 2][1];",
+ {factory->NewNumberFromInt(3)}},
+ {"return ['a', 'b', 'c'][2];", {factory->NewStringFromStaticChars("c")}},
+ {"var a = 100; return [a, a++, a + 2, a + 3][2];",
+ {factory->NewNumberFromInt(103)}},
+ {"var a = 100; return [a, ++a, a + 2, a + 3][1];",
+ {factory->NewNumberFromInt(101)}},
+ {"var a = 9.2;"
+ REPEAT_256(SPACE, "a = 9.34;")
+ "return [a, ++a, a + 2, a + 3][2];",
+ {factory->NewHeapNumber(12.34)}},
+ {"return [[1, 2, 3], ['a', 'b', 'c']][1][0];",
+ {factory->NewStringFromStaticChars("a")}},
+ {"var t = 't'; return [[t, t + 'est'], [1 + t]][0][1];",
+ {factory->NewStringFromStaticChars("test")}},
+ {"var t = 't'; return [[t, t + 'est'], [1 + t]][1][0];",
+ {factory->NewStringFromStaticChars("1t")}}};
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(4096);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderObjectLiterals) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"return { }.name;", {factory->undefined_value()}},
+ {"return { name: 'string', val: 9.2 }.name;",
+ {factory->NewStringFromStaticChars("string")}},
+ {"var a;\n"
+ REPEAT_256(SPACE, "a = 1.23;\n")
+ "return { name: 'string', val: 9.2 }.name;",
+ {factory->NewStringFromStaticChars("string")}},
+ {"return { name: 'string', val: 9.2 }['name'];",
+ {factory->NewStringFromStaticChars("string")}},
+ {"var a = 15; return { name: 'string', val: a }.val;",
+ {factory->NewNumberFromInt(15)}},
+ {"var a;"
+ REPEAT_256(SPACE, "a = 1.23;")
+ "return { name: 'string', val: a }.val;",
+ {factory->NewHeapNumber(1.23)}},
+ {"var a = 15; var b = 'val'; return { name: 'string', val: a }[b];",
+ {factory->NewNumberFromInt(15)}},
+ {"var a = 5; return { val: a, val: a + 1 }.val;",
+ {factory->NewNumberFromInt(6)}},
+ {"return { func: function() { return 'test' } }.func();",
+ {factory->NewStringFromStaticChars("test")}},
+ {"return { func(a) { return a + 'st'; } }.func('te');",
+ {factory->NewStringFromStaticChars("test")}},
+ {"return { get a() { return 22; } }.a;", {factory->NewNumberFromInt(22)}},
+ {"var a = { get b() { return this.x + 't'; },\n"
+ " set b(val) { this.x = val + 's' } };\n"
+ "a.b = 'te';\n"
+ "return a.b;",
+ {factory->NewStringFromStaticChars("test")}},
+ {"var a = 123; return { 1: a }[1];", {factory->NewNumberFromInt(123)}},
+ {"return Object.getPrototypeOf({ __proto__: null });",
+ {factory->null_value()}},
+ {"var a = 'test'; return { [a]: 1 }.test;",
+ {factory->NewNumberFromInt(1)}},
+ {"var a = 'test'; return { b: a, [a]: a + 'ing' }['test']",
+ {factory->NewStringFromStaticChars("testing")}},
+ {"var a = 'proto_str';\n"
+ "var b = { [a]: 1, __proto__: { var : a } };\n"
+ "return Object.getPrototypeOf(b).var",
+ {factory->NewStringFromStaticChars("proto_str")}},
+ {"var n = 'name';\n"
+ "return { [n]: 'val', get a() { return 987 } }['a'];",
+ {factory->NewNumberFromInt(987)}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(4096);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderIf) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<1> snippets[] = {
+ {"if (p1 > 1) return 1;\n"
+ "return -1;",
+ {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
+ {"if (p1 > 1) return 1;\n"
+ "return -1;",
+ {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(1)}},
+ {"if (p1 > 1) { return 1; } else { return -1; }",
+ {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
+ {"if (p1 > 1) { return 1; } else { return -1; }",
+ {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(1)}},
+ {"if (p1 > 50) {\n"
+ " return 1;\n"
+ "} else if (p1 < 10) {\n"
+ " return 10;\n"
+ "} else {\n"
+ " return -10;\n"
+ "}",
+ {factory->NewNumberFromInt(1), factory->NewNumberFromInt(51)}},
+ {"if (p1 > 50) {\n"
+ " return 1;\n"
+ "} else if (p1 < 10) {\n"
+ " return 10;\n"
+ "} else {\n"
+ " return 100;\n"
+ "}",
+ {factory->NewNumberFromInt(10), factory->NewNumberFromInt(9)}},
+ {"if (p1 > 50) {\n"
+ " return 1;\n"
+ "} else if (p1 < 10) {\n"
+ " return 10;\n"
+ "} else {\n"
+ " return 100;\n"
+ "}",
+ {factory->NewNumberFromInt(100), factory->NewNumberFromInt(10)}},
+ {"if (p1 >= 0) {\n"
+ " if (p1 > 10) { return 2; } else { return 1; }\n"
+ "} else {\n"
+ " if (p1 < -10) { return -2; } else { return -1; }\n"
+ "}",
+ {factory->NewNumberFromInt(2), factory->NewNumberFromInt(100)}},
+ {"if (p1 >= 0) {\n"
+ " if (p1 > 10) { return 2; } else { return 1; }\n"
+ "} else {\n"
+ " if (p1 < -10) { return -2; } else { return -1; }\n"
+ "}",
+ {factory->NewNumberFromInt(1), factory->NewNumberFromInt(10)}},
+ {"if (p1 >= 0) {\n"
+ " if (p1 > 10) { return 2; } else { return 1; }\n"
+ "} else {\n"
+ " if (p1 < -10) { return -2; } else { return -1; }\n"
+ "}",
+ {factory->NewNumberFromInt(-2), factory->NewNumberFromInt(-11)}},
+ {"if (p1 >= 0) {\n"
+ " if (p1 > 10) { return 2; } else { return 1; }\n"
+ "} else {\n"
+ " if (p1 < -10) { return -2; } else { return -1; }\n"
+ "}",
+ {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(-10)}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(2048);
+ SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderConditionalOperator) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<1> snippets[] = {
+ {"return (p1 > 1) ? 1 : -1;",
+ {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
+ {"return (p1 > 1) ? 1 : -1;",
+ {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(0)}},
+ {"return (p1 > 50) ? 1 : ((p1 < 10) ? 10 : -10);",
+ {factory->NewNumberFromInt(10), factory->NewNumberFromInt(2)}},
+ {"return (p1 > 50) ? 1 : ((p1 < 10) ? 10 : -10);",
+ {factory->NewNumberFromInt(-10), factory->NewNumberFromInt(20)}},
+ };
+
+ size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
+ for (size_t i = 0; i < num_snippets; i++) {
+ ScopedVector<char> script(2048);
+ SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderSwitch) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ const char* switch_code =
+ "switch (p1) {\n"
+ " case 1: return 0;\n"
+ " case 2: return 1;\n"
+ " case 3:\n"
+ " case 4: return 2;\n"
+ " case 9: break;\n"
+ " default: return 3;\n"
+ "}\n"
+ "return 9;";
+
+ ExpectedSnippet<1> snippets[] = {
+ {switch_code,
+ {factory->NewNumberFromInt(0), factory->NewNumberFromInt(1)}},
+ {switch_code,
+ {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
+ {switch_code,
+ {factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+ {switch_code,
+ {factory->NewNumberFromInt(2), factory->NewNumberFromInt(4)}},
+ {switch_code,
+ {factory->NewNumberFromInt(9), factory->NewNumberFromInt(9)}},
+ {switch_code,
+ {factory->NewNumberFromInt(3), factory->NewNumberFromInt(5)}},
+ {switch_code,
+ {factory->NewNumberFromInt(3), factory->NewNumberFromInt(6)}},
+ };
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(2048);
+ SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderNestedSwitch) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ const char* switch_code =
+ "switch (p1) {\n"
+ " case 0: {"
+ " switch (p2) { case 0: return 0; case 1: return 1; case 2: break; }\n"
+ " return -1;"
+ " }\n"
+ " case 1: {"
+ " switch (p2) { case 0: return 2; case 1: return 3; }\n"
+ " }\n"
+ " case 2: break;"
+ " }\n"
+ "return -2;";
+
+ ExpectedSnippet<2> snippets[] = {
+ {switch_code,
+ {factory->NewNumberFromInt(0), factory->NewNumberFromInt(0),
+ factory->NewNumberFromInt(0)}},
+ {switch_code,
+ {factory->NewNumberFromInt(1), factory->NewNumberFromInt(0),
+ factory->NewNumberFromInt(1)}},
+ {switch_code,
+ {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(0),
+ factory->NewNumberFromInt(2)}},
+ {switch_code,
+ {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(0),
+ factory->NewNumberFromInt(3)}},
+ {switch_code,
+ {factory->NewNumberFromInt(2), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(0)}},
+ {switch_code,
+ {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(1)}},
+ {switch_code,
+ {factory->NewNumberFromInt(-2), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(2)}},
+ {switch_code,
+ {factory->NewNumberFromInt(-2), factory->NewNumberFromInt(2),
+ factory->NewNumberFromInt(0)}},
+ };
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(2048);
+ SNPrintF(script, "function %s(p1, p2) { %s };\n%s(0, 0);", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0), snippets[i].parameter(1))
+ .ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderBreakableBlocks) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"var x = 0;\n"
+ "my_heart: {\n"
+ " x = x + 1;\n"
+ " break my_heart;\n"
+ " x = x + 2;\n"
+ "}\n"
+ "return x;\n",
+ {factory->NewNumberFromInt(1)}},
+ {"var sum = 0;\n"
+ "outta_here: {\n"
+ " for (var x = 0; x < 10; ++x) {\n"
+ " for (var y = 0; y < 3; ++y) {\n"
+ " ++sum;\n"
+ " if (x + y == 12) { break outta_here; }\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "return sum;",
+ {factory->NewNumber(30)}},
+ };
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderWhile) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"var x = 1; while (x < 1) { x *= 100; } return x;",
+ {factory->NewNumberFromInt(1)}},
+ {"var x = 1, y = 0; while (x < 7) { y += x * x; x += 1; } return y;",
+ {factory->NewNumberFromInt(91)}},
+ {"var x = 1; while (true) { x += 1; if (x == 10) break; } return x;",
+ {factory->NewNumberFromInt(10)}},
+ {"var x = 1; while (false) { x += 1; } return x;",
+ {factory->NewNumberFromInt(1)}},
+ {"var x = 0;\n"
+ "while (true) {\n"
+ " while (x < 10) {\n"
+ " x = x * x + 1;\n"
+ " }"
+ " x += 1;\n"
+ " break;\n"
+ "}\n"
+ "return x;",
+ {factory->NewNumberFromInt(27)}},
+ {"var x = 1, y = 0;\n"
+ "while (x < 7) {\n"
+ " x += 1;\n"
+ " if (x == 2) continue;\n"
+ " if (x == 3) continue;\n"
+ " y += x * x;\n"
+ " if (x == 4) break;\n"
+ "}\n"
+ "return y;",
+ {factory->NewNumberFromInt(16)}}};
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderDo) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"var x = 1; do { x *= 100; } while (x < 100); return x;",
+ {factory->NewNumberFromInt(100)}},
+ {"var x = 1; do { x = x * x + 1; } while (x < 7) return x;",
+ {factory->NewNumberFromInt(26)}},
+ {"var x = 1; do { x += 1; } while (false); return x;",
+ {factory->NewNumberFromInt(2)}},
+ {"var x = 1, y = 0;\n"
+ "do {\n"
+ " x += 1;\n"
+ " if (x == 2) continue;\n"
+ " if (x == 3) continue;\n"
+ " y += x * x;\n"
+ " if (x == 4) break;\n"
+ "} while (x < 7);\n"
+ "return y;",
+ {factory->NewNumberFromInt(16)}}};
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderFor) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"for (var x = 0;; x = 2 * x + 1) { if (x > 10) return x; }",
+ {factory->NewNumberFromInt(15)}},
+ {"for (var x = 0; true; x = 2 * x + 1) { if (x > 100) return x; }",
+ {factory->NewNumberFromInt(127)}},
+ {"for (var x = 0; false; x = 2 * x + 1) { if (x > 100) return x; } "
+ "return 0;",
+ {factory->NewNumberFromInt(0)}},
+ {"for (var x = 0; x < 200; x = 2 * x + 1) { x = x; } return x;",
+ {factory->NewNumberFromInt(255)}},
+ {"for (var x = 0; x < 200; x = 2 * x + 1) {} return x;",
+ {factory->NewNumberFromInt(255)}},
+ {"var sum = 0;\n"
+ "for (var x = 0; x < 200; x += 1) {\n"
+ " if (x % 2) continue;\n"
+ " if (sum > 10) break;\n"
+ " sum += x;\n"
+ "}\n"
+ "return sum;",
+ {factory->NewNumberFromInt(12)}},
+ {"var sum = 0;\n"
+ "for (var w = 0; w < 2; w++) {\n"
+ " for (var x = 0; x < 200; x += 1) {\n"
+ " if (x % 2) continue;\n"
+ " if (x > 4) break;\n"
+ " sum += x + w;\n"
+ " }\n"
+ "}\n"
+ "return sum;",
+ {factory->NewNumberFromInt(15)}},
+ {"var sum = 0;\n"
+ "for (var w = 0; w < 2; w++) {\n"
+ " if (w == 1) break;\n"
+ " for (var x = 0; x < 200; x += 1) {\n"
+ " if (x % 2) continue;\n"
+ " if (x > 4) break;\n"
+ " sum += x + w;\n"
+ " }\n"
+ "}\n"
+ "return sum;",
+ {factory->NewNumberFromInt(6)}},
+ {"var sum = 0;\n"
+ "for (var w = 0; w < 3; w++) {\n"
+ " if (w == 1) continue;\n"
+ " for (var x = 0; x < 200; x += 1) {\n"
+ " if (x % 2) continue;\n"
+ " if (x > 4) break;\n"
+ " sum += x + w;\n"
+ " }\n"
+ "}\n"
+ "return sum;",
+ {factory->NewNumberFromInt(18)}},
+ {"var sum = 0;\n"
+ "for (var x = 1; x < 10; x += 2) {\n"
+ " for (var y = x; y < x + 2; y++) {\n"
+ " sum += y * y;\n"
+ " }\n"
+ "}\n"
+ "return sum;",
+ {factory->NewNumberFromInt(385)}},
+ };
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(BytecodeGraphBuilderForIn) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+ ExpectedSnippet<0> snippets[] = {
+ {"var sum = 0;\n"
+ "var empty = null;\n"
+ "for (var x in empty) { sum++; }\n"
+ "return sum;",
+ {factory->NewNumberFromInt(0)}},
+ {"var sum = 100;\n"
+ "var empty = 1;\n"
+ "for (var x in empty) { sum++; }\n"
+ "return sum;",
+ {factory->NewNumberFromInt(100)}},
+ {"for (var x in [ 10, 20, 30 ]) {}\n"
+ "return 2;",
+ {factory->NewNumberFromInt(2)}},
+ {"var last = 0;\n"
+ "for (var x in [ 10, 20, 30 ]) {\n"
+ " last = x;\n"
+ "}\n"
+ "return +last;",
+ {factory->NewNumberFromInt(2)}},
+ {"var first = -1;\n"
+ "for (var x in [ 10, 20, 30 ]) {\n"
+ " first = +x;\n"
+ " if (first > 0) break;\n"
+ "}\n"
+ "return first;",
+ {factory->NewNumberFromInt(1)}},
+ {"var first = -1;\n"
+ "for (var x in [ 10, 20, 30 ]) {\n"
+ " if (first >= 0) continue;\n"
+ " first = x;\n"
+ "}\n"
+ "return +first;",
+ {factory->NewNumberFromInt(0)}},
+ {"var sum = 0;\n"
+ "for (var x in [ 10, 20, 30 ]) {\n"
+ " for (var y in [ 11, 22, 33, 44, 55, 66, 77 ]) {\n"
+ " sum += 1;\n"
+ " }\n"
+ "}\n"
+ "return sum;",
+ {factory->NewNumberFromInt(21)}},
+ {"var sum = 0;\n"
+ "for (var x in [ 10, 20, 30 ]) {\n"
+ " for (var y in [ 11, 22, 33, 44, 55, 66, 77 ]) {\n"
+ " if (sum == 7) break;\n"
+ " if (sum == 6) continue;\n"
+ " sum += 1;\n"
+ " }\n"
+ "}\n"
+ "return sum;",
+ {factory->NewNumberFromInt(6)}},
+ };
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+
+TEST(JumpWithConstantsAndWideConstants) {
+ HandleAndZoneScope scope;
+ auto isolate = scope.main_isolate();
+ const int kStep = 19;
+ int start = 7;
+ for (int constants = start; constants < 256 + 3 * kStep; constants += kStep) {
+ std::stringstream filler_os;
+ // Generate a string that consumes constant pool entries and
+ // spread out branch distances in script below.
+ for (int i = 0; i < constants; i++) {
+ filler_os << "var x_ = 'x_" << i << "';\n";
+ }
+ std::string filler(filler_os.str());
+
+ std::stringstream script_os;
+ script_os << "function " << kFunctionName << "(a) {\n";
+ script_os << " " << filler;
+ script_os << " for (var i = a; i < 2; i++) {\n";
+ script_os << " " << filler;
+ script_os << " if (i == 0) { " << filler << "i = 10; continue; }\n";
+ script_os << " else if (i == a) { " << filler << "i = 12; break; }\n";
+ script_os << " else { " << filler << " }\n";
+ script_os << " }\n";
+ script_os << " return i;\n";
+ script_os << "}\n";
+ script_os << kFunctionName << "(0);\n";
+ std::string script(script_os.str());
+ auto factory = isolate->factory();
+ auto zone = scope.main_zone();
+ for (int a = 0; a < 3; a++) {
+ BytecodeGraphTester tester(isolate, zone, script.c_str());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_val =
+ callable(factory->NewNumberFromInt(a)).ToHandleChecked();
+ static const int results[] = {11, 12, 2};
+ CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]);
+ }
+ }
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-deopt.cc b/test/cctest/compiler/test-run-deopt.cc
index 14c024c..8b4c9dc 100644
--- a/test/cctest/compiler/test-run-deopt.cc
+++ b/test/cctest/compiler/test-run-deopt.cc
@@ -2,18 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
+#include "src/frames-inl.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/function-tester.h"
-using namespace v8;
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
-#if V8_TURBOFAN_TARGET
-
-static void IsOptimized(const FunctionCallbackInfo<v8::Value>& args) {
+static void IsOptimized(const v8::FunctionCallbackInfo<v8::Value>& args) {
JavaScriptFrameIterator it(CcTest::i_isolate());
JavaScriptFrame* frame = it.frame();
return args.GetReturnValue().Set(frame->is_optimized());
@@ -21,56 +18,104 @@
static void InstallIsOptimizedHelper(v8::Isolate* isolate) {
- Local<v8::Context> context = isolate->GetCurrentContext();
- Local<v8::FunctionTemplate> t = FunctionTemplate::New(isolate, IsOptimized);
- context->Global()->Set(v8_str("IsOptimized"), t->GetFunction());
+ v8::Local<v8::Context> context = isolate->GetCurrentContext();
+ v8::Local<v8::FunctionTemplate> t =
+ v8::FunctionTemplate::New(isolate, IsOptimized);
+ CHECK(context->Global()
+ ->Set(context, v8_str("IsOptimized"),
+ t->GetFunction(context).ToLocalChecked())
+ .FromJust());
}
-TEST(TurboSimpleDeopt) {
+TEST(DeoptSimple) {
FLAG_allow_natives_syntax = true;
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function f(a) {"
- "var b = 1;"
- "if (!IsOptimized()) return 0;"
- "%DeoptimizeFunction(f);"
- "if (IsOptimized()) return 0;"
- "return a + b; })");
+ " var b = 1;"
+ " if (!IsOptimized()) return 0;"
+ " %DeoptimizeFunction(f);"
+ " if (IsOptimized()) return 0;"
+ " return a + b;"
+ "})");
InstallIsOptimizedHelper(CcTest::isolate());
T.CheckCall(T.Val(2), T.Val(1));
}
-TEST(TurboSimpleDeoptInExpr) {
+TEST(DeoptSimpleInExpr) {
FLAG_allow_natives_syntax = true;
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function f(a) {"
- "var b = 1;"
- "var c = 2;"
- "if (!IsOptimized()) return 0;"
- "var d = b + (%DeoptimizeFunction(f), c);"
- "if (IsOptimized()) return 0;"
- "return d + a; })");
+ " var b = 1;"
+ " var c = 2;"
+ " if (!IsOptimized()) return 0;"
+ " var d = b + (%DeoptimizeFunction(f), c);"
+ " if (IsOptimized()) return 0;"
+ " return d + a;"
+ "})");
InstallIsOptimizedHelper(CcTest::isolate());
T.CheckCall(T.Val(6), T.Val(3));
}
-#endif
-TEST(TurboTrivialDeopt) {
+TEST(DeoptExceptionHandlerCatch) {
FLAG_allow_natives_syntax = true;
- FLAG_turbo_deoptimization = true;
+
+ FunctionTester T(
+ "(function f() {"
+ " var is_opt = IsOptimized;"
+ " try {"
+ " DeoptAndThrow(f);"
+ " } catch (e) {"
+ " return is_opt();"
+ " }"
+ "})");
+
+ CompileRun("function DeoptAndThrow(f) { %DeoptimizeFunction(f); throw 0; }");
+ InstallIsOptimizedHelper(CcTest::isolate());
+ T.CheckCall(T.false_value());
+}
+
+
+TEST(DeoptExceptionHandlerFinally) {
+ FLAG_allow_natives_syntax = true;
+ FLAG_turbo_try_finally = true;
+
+ FunctionTester T(
+ "(function f() {"
+ " var is_opt = IsOptimized;"
+ " try {"
+ " DeoptAndThrow(f);"
+ " } finally {"
+ " return is_opt();"
+ " }"
+ "})");
+
+ CompileRun("function DeoptAndThrow(f) { %DeoptimizeFunction(f); throw 0; }");
+ InstallIsOptimizedHelper(CcTest::isolate());
+#if 0 // TODO(4195,mstarzinger): Reproduces on MIPS64, re-enable once fixed.
+ T.CheckCall(T.false_value());
+#endif
+}
+
+
+TEST(DeoptTrivial) {
+ FLAG_allow_natives_syntax = true;
FunctionTester T(
"(function foo() {"
- "%DeoptimizeFunction(foo);"
- "return 1; })");
+ " %DeoptimizeFunction(foo);"
+ " return 1;"
+ "})");
T.CheckCall(T.Val(1));
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-inlining.cc b/test/cctest/compiler/test-run-inlining.cc
index 19b96ba..f332d74 100644
--- a/test/cctest/compiler/test-run-inlining.cc
+++ b/test/cctest/compiler/test-run-inlining.cc
@@ -2,49 +2,64 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
+#include "src/frames-inl.h"
#include "test/cctest/compiler/function-tester.h"
-#if V8_TURBOFAN_TARGET
+namespace v8 {
+namespace internal {
+namespace compiler {
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace {
-// Helper to determine inline count via JavaScriptFrame::GetInlineCount.
+// Helper to determine inline count via JavaScriptFrame::GetFunctions.
// Note that a count of 1 indicates that no inlining has occured.
-static void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
+void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
StackTraceFrameIterator it(CcTest::i_isolate());
int frames_seen = 0;
JavaScriptFrame* topmost = it.frame();
while (!it.done()) {
JavaScriptFrame* frame = it.frame();
+ List<JSFunction*> functions(2);
+ frame->GetFunctions(&functions);
PrintF("%d %s, inline count: %d\n", frames_seen,
frame->function()->shared()->DebugName()->ToCString().get(),
- frame->GetInlineCount());
+ functions.length());
frames_seen++;
it.Advance();
}
- CHECK_EQ(args[0]->ToInt32(args.GetIsolate())->Value(),
- topmost->GetInlineCount());
+ List<JSFunction*> functions(2);
+ topmost->GetFunctions(&functions);
+ CHECK_EQ(args[0]
+ ->ToInt32(args.GetIsolate()->GetCurrentContext())
+ .ToLocalChecked()
+ ->Value(),
+ functions.length());
}
-static void InstallAssertInlineCountHelper(v8::Isolate* isolate) {
+void InstallAssertInlineCountHelper(v8::Isolate* isolate) {
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Local<v8::FunctionTemplate> t =
v8::FunctionTemplate::New(isolate, AssertInlineCount);
- context->Global()->Set(v8_str("AssertInlineCount"), t->GetFunction());
+ CHECK(context->Global()
+ ->Set(context, v8_str("AssertInlineCount"),
+ t->GetFunction(context).ToLocalChecked())
+ .FromJust());
}
-static uint32_t kInlineFlags = CompilationInfo::kInliningEnabled |
- CompilationInfo::kContextSpecializing |
- CompilationInfo::kTypingEnabled;
+const uint32_t kRestrictedInliningFlags =
+ CompilationInfo::kFunctionContextSpecializing |
+ CompilationInfo::kTypingEnabled;
+
+const uint32_t kInlineFlags = CompilationInfo::kInliningEnabled |
+ CompilationInfo::kFunctionContextSpecializing |
+ CompilationInfo::kTypingEnabled;
+
+} // namespace
TEST(SimpleInlining) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function(){"
" function foo(s) { AssertInlineCount(2); return s; };"
@@ -59,7 +74,6 @@
TEST(SimpleInliningDeopt) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function(){"
" function foo(s) { %DeoptimizeFunction(bar); return s; };"
@@ -73,8 +87,21 @@
}
+TEST(SimpleInliningDeoptSelf) {
+ FunctionTester T(
+ "(function(){"
+ " function foo(s) { %_DeoptimizeNow(); return s; };"
+ " function bar(s, t) { return foo(s); };"
+ " return bar;"
+ "})();",
+ kInlineFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.Val(1), T.Val(1), T.Val(2));
+}
+
+
TEST(SimpleInliningContext) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" function foo(s) { AssertInlineCount(2); var x = 12; return s + x; };"
@@ -89,7 +116,6 @@
TEST(SimpleInliningContextDeopt) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" function foo(s) {"
@@ -107,7 +133,6 @@
TEST(CaptureContext) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"var f = (function () {"
" var x = 42;"
@@ -125,7 +150,6 @@
// TODO(sigurds) For now we do not inline any native functions. If we do at
// some point, change this test.
TEST(DontInlineEval) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"var x = 42;"
"(function () {"
@@ -140,12 +164,12 @@
TEST(InlineOmitArguments) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" var x = 42;"
" function bar(s, t, u, v) { AssertInlineCount(2); return x + s; };"
- " return (function (s,t) { return bar(s); });"
+ " function foo(s, t) { return bar(s); };"
+ " return foo;"
"})();",
kInlineFlags);
@@ -154,8 +178,23 @@
}
+TEST(InlineOmitArgumentsObject) {
+ FunctionTester T(
+ "(function () {"
+ " function bar(s, t, u, v) { AssertInlineCount(2); return arguments; };"
+ " function foo(s, t) { var args = bar(s);"
+ " return args.length == 1 &&"
+ " args[0] == 11; };"
+ " return foo;"
+ "})();",
+ kInlineFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.true_value(), T.Val(11), T.undefined());
+}
+
+
TEST(InlineOmitArgumentsDeopt) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" function foo(s,t,u,v) { AssertInlineCount(2);"
@@ -173,12 +212,11 @@
TEST(InlineSurplusArguments) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" var x = 42;"
" function foo(s) { AssertInlineCount(2); return x + s; };"
- " function bar(s,t) { return foo(s,t,13); };"
+ " function bar(s, t) { return foo(s, t, 13); };"
" return bar;"
"})();",
kInlineFlags);
@@ -188,8 +226,25 @@
}
+TEST(InlineSurplusArgumentsObject) {
+ FunctionTester T(
+ "(function () {"
+ " function foo(s) { AssertInlineCount(2); return arguments; };"
+ " function bar(s, t) { var args = foo(s, t, 13);"
+ " return args.length == 3 &&"
+ " args[0] == 11 &&"
+ " args[1] == 12 &&"
+ " args[2] == 13; };"
+ " return bar;"
+ "})();",
+ kInlineFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.true_value(), T.Val(11), T.Val(12));
+}
+
+
TEST(InlineSurplusArgumentsDeopt) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" function foo(s) { AssertInlineCount(2); %DeoptimizeFunction(bar);"
@@ -209,7 +264,6 @@
TEST(InlineTwice) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" var x = 42;"
@@ -224,7 +278,6 @@
TEST(InlineTwiceDependent) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" var x = 42;"
@@ -240,7 +293,6 @@
TEST(InlineTwiceDependentDiamond) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" var x = 41;"
@@ -257,7 +309,6 @@
TEST(InlineTwiceDependentDiamondDifferent) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" var x = 41;"
@@ -274,7 +325,6 @@
TEST(InlineLoopGuardedEmpty) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" function foo(s) { AssertInlineCount(2); if (s) while (s); return s; };"
@@ -289,7 +339,6 @@
TEST(InlineLoopGuardedOnce) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" function foo(s,t) { AssertInlineCount(2); if (t > 0) while (s > 0) {"
@@ -305,7 +354,6 @@
TEST(InlineLoopGuardedTwice) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" function foo(s,t) { AssertInlineCount(2); if (t > 0) while (s > 0) {"
@@ -320,8 +368,51 @@
}
+TEST(InlineLoopUnguardedEmpty) {
+ FunctionTester T(
+ "(function () {"
+ " function foo(s) { AssertInlineCount(2); while (s); return s; };"
+ " function bar(s, t) { return foo(s); };"
+ " return bar;"
+ "})();",
+ kInlineFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(4));
+}
+
+
+TEST(InlineLoopUnguardedOnce) {
+ FunctionTester T(
+ "(function () {"
+ " function foo(s) { AssertInlineCount(2); while (s) {"
+ " s = s - 1; }; return s; };"
+ " function bar(s, t) { return foo(s); };"
+ " return bar;"
+ "})();",
+ kInlineFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(4));
+}
+
+
+TEST(InlineLoopUnguardedTwice) {
+ FunctionTester T(
+ "(function () {"
+ " function foo(s) { AssertInlineCount(2); while (s > 0) {"
+ " s = s - 1; }; return s; };"
+ " function bar(s,t) { return foo(foo(s,t),t); };"
+ " return bar;"
+ "})();",
+ kInlineFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(4));
+}
+
+
TEST(InlineStrictIntoNonStrict) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" var x = Object.create({}, { y: { value:42, writable:false } });"
@@ -338,7 +429,6 @@
TEST(InlineNonStrictIntoStrict) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" var x = Object.create({}, { y: { value:42, writable:false } });"
@@ -354,7 +444,6 @@
TEST(InlineIntrinsicIsSmi) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" var x = 42;"
@@ -368,23 +457,7 @@
}
-TEST(InlineIntrinsicIsNonNegativeSmi) {
- FLAG_turbo_deoptimization = true;
- FunctionTester T(
- "(function () {"
- " var x = 42;"
- " function bar(s,t) { return %_IsNonNegativeSmi(x); };"
- " return bar;"
- "})();",
- kInlineFlags);
-
- InstallAssertInlineCountHelper(CcTest::isolate());
- T.CheckCall(T.true_value(), T.Val(12), T.Val(4));
-}
-
-
TEST(InlineIntrinsicIsArray) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" var x = [1,2,3];"
@@ -419,7 +492,6 @@
TEST(InlineWithArguments) {
- FLAG_turbo_deoptimization = true;
FunctionTester T(
"(function () {"
" function foo(s,t,u) { AssertInlineCount(2);"
@@ -437,4 +509,99 @@
T.CheckCall(T.true_value(), T.Val(12), T.Val(14));
}
-#endif // V8_TURBOFAN_TARGET
+
+TEST(InlineBuiltin) {
+ FunctionTester T(
+ "(function () {"
+ " function foo(s,t,u) { AssertInlineCount(2); return true; }"
+ " function bar() { return foo(); };"
+ " %SetForceInlineFlag(foo);"
+ " return bar;"
+ "})();",
+ kRestrictedInliningFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.true_value());
+}
+
+
+TEST(InlineNestedBuiltin) {
+ FunctionTester T(
+ "(function () {"
+ " function foo(s,t,u) { AssertInlineCount(3); return true; }"
+ " function baz(s,t,u) { return foo(s,t,u); }"
+ " function bar() { return baz(); };"
+ " %SetForceInlineFlag(foo);"
+ " %SetForceInlineFlag(baz);"
+ " return bar;"
+ "})();",
+ kRestrictedInliningFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.true_value());
+}
+
+
+TEST(StrongModeArity) {
+ FLAG_strong_mode = true;
+ FunctionTester T(
+ "(function () {"
+ " function foo(x, y) { 'use strong'; return x; }"
+ " function bar(x, y) { return foo(x); }"
+ " return bar;"
+ "})();",
+ kInlineFlags);
+ T.CheckThrows(T.undefined(), T.undefined());
+}
+
+
+TEST(StrongModeArityOuter) {
+ FLAG_strong_mode = true;
+ FunctionTester T(
+ "(function () {"
+ " 'use strong';"
+ " function foo(x, y) { return x; }"
+ " function bar(x, y) { return foo(x); }"
+ " return bar;"
+ "})();",
+ kInlineFlags);
+ T.CheckThrows(T.undefined(), T.undefined());
+}
+
+
+TEST(InlineSelfRecursive) {
+ FunctionTester T(
+ "(function () {"
+ " function foo(x) { "
+ " AssertInlineCount(1);"
+ " if (x == 1) return foo(12);"
+ " return x;"
+ " }"
+ " return foo;"
+ "})();",
+ kInlineFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.Val(12), T.Val(1));
+}
+
+
+TEST(InlineMutuallyRecursive) {
+ FunctionTester T(
+ "(function () {"
+ " function bar(x) { AssertInlineCount(2); return foo(x); }"
+ " function foo(x) { "
+ " if (x == 1) return bar(42);"
+ " return x;"
+ " }"
+ " return foo;"
+ "})();",
+ kInlineFlags);
+
+ InstallAssertInlineCountHelper(CcTest::isolate());
+ T.CheckCall(T.Val(42), T.Val(1));
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-intrinsics.cc b/test/cctest/compiler/test-run-intrinsics.cc
index 76cbb8f..b201711 100644
--- a/test/cctest/compiler/test-run-intrinsics.cc
+++ b/test/cctest/compiler/test-run-intrinsics.cc
@@ -2,123 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "test/cctest/compiler/function-tester.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
+
uint32_t flags = CompilationInfo::kInliningEnabled;
-TEST(IsSmi) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_IsSmi(a); })", flags);
- T.CheckTrue(T.Val(1));
- T.CheckFalse(T.Val(1.1));
- T.CheckFalse(T.Val(-0.0));
- T.CheckTrue(T.Val(-2));
- T.CheckFalse(T.Val(-2.3));
- T.CheckFalse(T.undefined());
-}
+TEST(Call) {
+ FunctionTester T("(function(a,b) { return %_Call(b, a, 1, 2, 3); })", flags);
+ CompileRun("function f(a,b,c) { return a + b + c + this.d; }");
-
-TEST(IsNonNegativeSmi) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_IsNonNegativeSmi(a); })", flags);
-
- T.CheckTrue(T.Val(1));
- T.CheckFalse(T.Val(1.1));
- T.CheckFalse(T.Val(-0.0));
- T.CheckFalse(T.Val(-2));
- T.CheckFalse(T.Val(-2.3));
- T.CheckFalse(T.undefined());
-}
-
-
-TEST(IsMinusZero) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_IsMinusZero(a); })", flags);
-
- T.CheckFalse(T.Val(1));
- T.CheckFalse(T.Val(1.1));
- T.CheckTrue(T.Val(-0.0));
- T.CheckFalse(T.Val(-2));
- T.CheckFalse(T.Val(-2.3));
- T.CheckFalse(T.undefined());
-}
-
-
-TEST(IsArray) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_IsArray(a); })", flags);
-
- T.CheckFalse(T.NewObject("(function() {})"));
- T.CheckTrue(T.NewObject("([1])"));
- T.CheckFalse(T.NewObject("({})"));
- T.CheckFalse(T.NewObject("(/x/)"));
- T.CheckFalse(T.undefined());
- T.CheckFalse(T.null());
- T.CheckFalse(T.Val("x"));
- T.CheckFalse(T.Val(1));
-}
-
-
-TEST(IsObject) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_IsObject(a); })", flags);
-
- T.CheckFalse(T.NewObject("(function() {})"));
- T.CheckTrue(T.NewObject("([1])"));
- T.CheckTrue(T.NewObject("({})"));
- T.CheckTrue(T.NewObject("(/x/)"));
- T.CheckFalse(T.undefined());
- T.CheckTrue(T.null());
- T.CheckFalse(T.Val("x"));
- T.CheckFalse(T.Val(1));
-}
-
-
-TEST(IsFunction) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_IsFunction(a); })", flags);
-
- T.CheckTrue(T.NewObject("(function() {})"));
- T.CheckFalse(T.NewObject("([1])"));
- T.CheckFalse(T.NewObject("({})"));
- T.CheckFalse(T.NewObject("(/x/)"));
- T.CheckFalse(T.undefined());
- T.CheckFalse(T.null());
- T.CheckFalse(T.Val("x"));
- T.CheckFalse(T.Val(1));
-}
-
-
-TEST(IsRegExp) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_IsRegExp(a); })", flags);
-
- T.CheckFalse(T.NewObject("(function() {})"));
- T.CheckFalse(T.NewObject("([1])"));
- T.CheckFalse(T.NewObject("({})"));
- T.CheckTrue(T.NewObject("(/x/)"));
- T.CheckFalse(T.undefined());
- T.CheckFalse(T.null());
- T.CheckFalse(T.Val("x"));
- T.CheckFalse(T.Val(1));
+ T.CheckCall(T.Val(129), T.NewObject("({d:123})"), T.NewObject("f"));
+ T.CheckCall(T.Val("6x"), T.NewObject("({d:'x'})"), T.NewObject("f"));
}
TEST(ClassOf) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
FunctionTester T("(function(a) { return %_ClassOf(a); })", flags);
T.CheckCall(T.Val("Function"), T.NewObject("(function() {})"));
@@ -132,9 +34,121 @@
}
+#define COUNTER_NAME "hurz"
+
+static int* LookupCounter(const char* name) {
+ static int counter = 1234;
+ return strcmp(name, COUNTER_NAME) == 0 ? &counter : nullptr;
+}
+
+
+TEST(IncrementStatsCounter) {
+ FLAG_native_code_counters = true;
+ reinterpret_cast<v8::Isolate*>(CcTest::InitIsolateOnce())
+ ->SetCounterFunction(LookupCounter);
+ FunctionTester T(
+ "(function() { %_IncrementStatsCounter('" COUNTER_NAME "'); })", flags);
+ StatsCounter counter(T.main_isolate(), COUNTER_NAME);
+ if (!counter.Enabled()) return;
+
+ int old_value = *counter.GetInternalPointer();
+ T.CheckCall(T.undefined());
+ CHECK_EQ(old_value + 1, *counter.GetInternalPointer());
+}
+
+#undef COUNTER_NAME
+
+
+TEST(IsArray) {
+ FunctionTester T("(function(a) { return %_IsArray(a); })", flags);
+
+ T.CheckFalse(T.NewObject("new Date()"));
+ T.CheckFalse(T.NewObject("(function() {})"));
+ T.CheckTrue(T.NewObject("([1])"));
+ T.CheckFalse(T.NewObject("({})"));
+ T.CheckFalse(T.NewObject("(/x/)"));
+ T.CheckFalse(T.undefined());
+ T.CheckFalse(T.null());
+ T.CheckFalse(T.Val("x"));
+ T.CheckFalse(T.Val(1));
+}
+
+
+TEST(IsDate) {
+ FunctionTester T("(function(a) { return %_IsDate(a); })", flags);
+
+ T.CheckTrue(T.NewObject("new Date()"));
+ T.CheckFalse(T.NewObject("(function() {})"));
+ T.CheckFalse(T.NewObject("([1])"));
+ T.CheckFalse(T.NewObject("({})"));
+ T.CheckFalse(T.NewObject("(/x/)"));
+ T.CheckFalse(T.undefined());
+ T.CheckFalse(T.null());
+ T.CheckFalse(T.Val("x"));
+ T.CheckFalse(T.Val(1));
+}
+
+
+TEST(IsFunction) {
+ FunctionTester T("(function(a) { return %_IsFunction(a); })", flags);
+
+ T.CheckFalse(T.NewObject("new Date()"));
+ T.CheckTrue(T.NewObject("(function() {})"));
+ T.CheckFalse(T.NewObject("([1])"));
+ T.CheckFalse(T.NewObject("({})"));
+ T.CheckFalse(T.NewObject("(/x/)"));
+ T.CheckFalse(T.undefined());
+ T.CheckFalse(T.null());
+ T.CheckFalse(T.Val("x"));
+ T.CheckFalse(T.Val(1));
+}
+
+
+TEST(IsMinusZero) {
+ FunctionTester T("(function(a) { return %_IsMinusZero(a); })", flags);
+
+ T.CheckFalse(T.Val(1));
+ T.CheckFalse(T.Val(1.1));
+ T.CheckTrue(T.Val(-0.0));
+ T.CheckFalse(T.Val(-2));
+ T.CheckFalse(T.Val(-2.3));
+ T.CheckFalse(T.undefined());
+}
+
+
+TEST(IsRegExp) {
+ FunctionTester T("(function(a) { return %_IsRegExp(a); })", flags);
+
+ T.CheckFalse(T.NewObject("new Date()"));
+ T.CheckFalse(T.NewObject("(function() {})"));
+ T.CheckFalse(T.NewObject("([1])"));
+ T.CheckFalse(T.NewObject("({})"));
+ T.CheckTrue(T.NewObject("(/x/)"));
+ T.CheckFalse(T.undefined());
+ T.CheckFalse(T.null());
+ T.CheckFalse(T.Val("x"));
+ T.CheckFalse(T.Val(1));
+}
+
+
+TEST(IsSmi) {
+ FunctionTester T("(function(a) { return %_IsSmi(a); })", flags);
+
+ T.CheckFalse(T.NewObject("new Date()"));
+ T.CheckFalse(T.NewObject("(function() {})"));
+ T.CheckFalse(T.NewObject("([1])"));
+ T.CheckFalse(T.NewObject("({})"));
+ T.CheckFalse(T.NewObject("(/x/)"));
+ T.CheckFalse(T.undefined());
+ T.CheckTrue(T.Val(1));
+ T.CheckFalse(T.Val(1.1));
+ T.CheckFalse(T.Val(-0.0));
+ T.CheckTrue(T.Val(-2));
+ T.CheckFalse(T.Val(-2.3));
+}
+
+
TEST(ObjectEquals) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
FunctionTester T("(function(a,b) { return %_ObjectEquals(a,b); })", flags);
CompileRun("var o = {}");
@@ -147,21 +161,38 @@
}
-TEST(ValueOf) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_ValueOf(a); })", flags);
+TEST(OneByteSeqStringGetChar) {
+ FunctionTester T("(function(a,b) { return %_OneByteSeqStringGetChar(a,b); })",
+ flags);
- T.CheckCall(T.Val("a"), T.Val("a"));
- T.CheckCall(T.Val("b"), T.NewObject("(new String('b'))"));
- T.CheckCall(T.Val(123), T.Val(123));
- T.CheckCall(T.Val(456), T.NewObject("(new Number(456))"));
+ Handle<SeqOneByteString> string =
+ T.main_isolate()->factory()->NewRawOneByteString(3).ToHandleChecked();
+ string->SeqOneByteStringSet(0, 'b');
+ string->SeqOneByteStringSet(1, 'a');
+ string->SeqOneByteStringSet(2, 'r');
+ T.CheckCall(T.Val('b'), string, T.Val(0.0));
+ T.CheckCall(T.Val('a'), string, T.Val(1));
+ T.CheckCall(T.Val('r'), string, T.Val(2));
+}
+
+
+TEST(OneByteSeqStringSetChar) {
+ FunctionTester T("(function(a,b) { %_OneByteSeqStringSetChar(a,88,b); })",
+ flags);
+
+ Handle<SeqOneByteString> string =
+ T.main_isolate()->factory()->NewRawOneByteString(3).ToHandleChecked();
+ string->SeqOneByteStringSet(0, 'b');
+ string->SeqOneByteStringSet(1, 'a');
+ string->SeqOneByteStringSet(2, 'r');
+ T.Call(T.Val(1), string);
+ CHECK_EQ('b', string->SeqOneByteStringGet(0));
+ CHECK_EQ('X', string->SeqOneByteStringGet(1));
+ CHECK_EQ('r', string->SeqOneByteStringGet(2));
}
TEST(SetValueOf) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
FunctionTester T("(function(a,b) { return %_SetValueOf(a,b); })", flags);
T.CheckCall(T.Val("a"), T.NewObject("(new String)"), T.Val("a"));
@@ -170,20 +201,16 @@
}
-TEST(StringCharFromCode) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a) { return %_StringCharFromCode(a); })", flags);
+TEST(StringAdd) {
+ FunctionTester T("(function(a,b) { return %_StringAdd(a,b); })", flags);
- T.CheckCall(T.Val("a"), T.Val(97));
- T.CheckCall(T.Val("\xE2\x9D\x8A"), T.Val(0x274A));
- T.CheckCall(T.Val(""), T.undefined());
+ T.CheckCall(T.Val("aaabbb"), T.Val("aaa"), T.Val("bbb"));
+ T.CheckCall(T.Val("aaa"), T.Val("aaa"), T.Val(""));
+ T.CheckCall(T.Val("bbb"), T.Val(""), T.Val("bbb"));
}
TEST(StringCharAt) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
FunctionTester T("(function(a,b) { return %_StringCharAt(a,b); })", flags);
T.CheckCall(T.Val("e"), T.Val("huge fan!"), T.Val(3));
@@ -193,8 +220,6 @@
TEST(StringCharCodeAt) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
FunctionTester T("(function(a,b) { return %_StringCharCodeAt(a,b); })",
flags);
@@ -204,31 +229,16 @@
}
-TEST(StringAdd) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a,b) { return %_StringAdd(a,b); })", flags);
+TEST(StringCharFromCode) {
+ FunctionTester T("(function(a) { return %_StringCharFromCode(a); })", flags);
- T.CheckCall(T.Val("aaabbb"), T.Val("aaa"), T.Val("bbb"));
- T.CheckCall(T.Val("aaa"), T.Val("aaa"), T.Val(""));
- T.CheckCall(T.Val("bbb"), T.Val(""), T.Val("bbb"));
-}
-
-
-TEST(StringSubString) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a,b) { return %_SubString(a,b,b+3); })", flags);
-
- T.CheckCall(T.Val("aaa"), T.Val("aaabbb"), T.Val(0.0));
- T.CheckCall(T.Val("abb"), T.Val("aaabbb"), T.Val(2));
- T.CheckCall(T.Val("aaa"), T.Val("aaa"), T.Val(0.0));
+ T.CheckCall(T.Val("a"), T.Val(97));
+ T.CheckCall(T.Val("\xE2\x9D\x8A"), T.Val(0x274A));
+ T.CheckCall(T.Val(""), T.undefined());
}
TEST(StringCompare) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
FunctionTester T("(function(a,b) { return %_StringCompare(a,b); })", flags);
T.CheckCall(T.Val(-1), T.Val("aaa"), T.Val("bbb"));
@@ -237,13 +247,55 @@
}
-TEST(CallFunction) {
- FLAG_turbo_inlining_intrinsics = true;
- FLAG_turbo_deoptimization = true;
- FunctionTester T("(function(a,b) { return %_CallFunction(a, 1, 2, 3, b); })",
- flags);
- CompileRun("function f(a,b,c) { return a + b + c + this.d; }");
+TEST(SubString) {
+ FunctionTester T("(function(a,b) { return %_SubString(a,b,b+3); })", flags);
- T.CheckCall(T.Val(129), T.NewObject("({d:123})"), T.NewObject("f"));
- T.CheckCall(T.Val("6x"), T.NewObject("({d:'x'})"), T.NewObject("f"));
+ T.CheckCall(T.Val("aaa"), T.Val("aaabbb"), T.Val(0.0));
+ T.CheckCall(T.Val("abb"), T.Val("aaabbb"), T.Val(2));
+ T.CheckCall(T.Val("aaa"), T.Val("aaa"), T.Val(0.0));
}
+
+
+TEST(TwoByteSeqStringGetChar) {
+ FunctionTester T("(function(a,b) { return %_TwoByteSeqStringGetChar(a,b); })",
+ flags);
+
+ Handle<SeqTwoByteString> string =
+ T.main_isolate()->factory()->NewRawTwoByteString(3).ToHandleChecked();
+ string->SeqTwoByteStringSet(0, 'b');
+ string->SeqTwoByteStringSet(1, 'a');
+ string->SeqTwoByteStringSet(2, 'r');
+ T.CheckCall(T.Val('b'), string, T.Val(0.0));
+ T.CheckCall(T.Val('a'), string, T.Val(1));
+ T.CheckCall(T.Val('r'), string, T.Val(2));
+}
+
+
+TEST(TwoByteSeqStringSetChar) {
+ FunctionTester T("(function(a,b) { %_TwoByteSeqStringSetChar(a,88,b); })",
+ flags);
+
+ Handle<SeqTwoByteString> string =
+ T.main_isolate()->factory()->NewRawTwoByteString(3).ToHandleChecked();
+ string->SeqTwoByteStringSet(0, 'b');
+ string->SeqTwoByteStringSet(1, 'a');
+ string->SeqTwoByteStringSet(2, 'r');
+ T.Call(T.Val(1), string);
+ CHECK_EQ('b', string->SeqTwoByteStringGet(0));
+ CHECK_EQ('X', string->SeqTwoByteStringGet(1));
+ CHECK_EQ('r', string->SeqTwoByteStringGet(2));
+}
+
+
+TEST(ValueOf) {
+ FunctionTester T("(function(a) { return %_ValueOf(a); })", flags);
+
+ T.CheckCall(T.Val("a"), T.Val("a"));
+ T.CheckCall(T.Val("b"), T.NewObject("(new String('b'))"));
+ T.CheckCall(T.Val(123), T.Val(123));
+ T.CheckCall(T.Val(456), T.NewObject("(new Number(456))"));
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-jsbranches.cc b/test/cctest/compiler/test-run-jsbranches.cc
index 7a4a0b3..613528d 100644
--- a/test/cctest/compiler/test-run-jsbranches.cc
+++ b/test/cctest/compiler/test-run-jsbranches.cc
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "test/cctest/compiler/function-tester.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
TEST(Conditional) {
FunctionTester T("(function(a) { return a ? 23 : 42; })");
@@ -168,6 +167,33 @@
}
+TEST(ForOfContinueStatement) {
+ const char* src =
+ "(function(a,b) {"
+ " var r = '-';"
+ " for (var x of a) {"
+ " r += x + '-';"
+ " if (b) continue;"
+ " r += 'X-';"
+ " }"
+ " return r;"
+ "})";
+ FunctionTester T(src);
+
+ CompileRun(
+ "function wrap(v) {"
+ " var iterable = {};"
+ " function next() { return { done:!v.length, value:v.shift() }; };"
+ " iterable[Symbol.iterator] = function() { return { next:next }; };"
+ " return iterable;"
+ "}");
+
+ T.CheckCall(T.Val("-"), T.NewObject("wrap([])"), T.true_value());
+ T.CheckCall(T.Val("-1-2-"), T.NewObject("wrap([1,2])"), T.true_value());
+ T.CheckCall(T.Val("-1-X-2-X-"), T.NewObject("wrap([1,2])"), T.false_value());
+}
+
+
TEST(SwitchStatement) {
const char* src =
"(function(a,b) {"
@@ -355,3 +381,7 @@
T.CheckCall(T.Val(8126.1), T.Val(0.0), T.Val(8126.1));
T.CheckCall(T.Val(1123.1), T.Val(0.0), T.Val(1123.1));
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-jscalls.cc b/test/cctest/compiler/test-run-jscalls.cc
index dec7194..474453d 100644
--- a/test/cctest/compiler/test-run-jscalls.cc
+++ b/test/cctest/compiler/test-run-jscalls.cc
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "test/cctest/compiler/function-tester.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
TEST(SimpleCall) {
FunctionTester T("(function(foo,a) { return foo(a); })");
@@ -132,46 +131,18 @@
// TODO(titzer): factor these out into test-runtime-calls.cc
-TEST(RuntimeCallCPP1) {
- FLAG_allow_natives_syntax = true;
- FunctionTester T("(function(a) { return %ToBool(a); })");
-
- T.CheckCall(T.true_value(), T.Val(23), T.undefined());
- T.CheckCall(T.true_value(), T.Val(4.2), T.undefined());
- T.CheckCall(T.true_value(), T.Val("str"), T.undefined());
- T.CheckCall(T.true_value(), T.true_value(), T.undefined());
- T.CheckCall(T.false_value(), T.false_value(), T.undefined());
- T.CheckCall(T.false_value(), T.undefined(), T.undefined());
- T.CheckCall(T.false_value(), T.Val(0.0), T.undefined());
-}
-
-
TEST(RuntimeCallCPP2) {
FLAG_allow_natives_syntax = true;
- FunctionTester T("(function(a,b) { return %NumberAdd(a, b); })");
+ FunctionTester T("(function(a,b) { return %NumberImul(a, b); })");
- T.CheckCall(T.Val(65), T.Val(42), T.Val(23));
- T.CheckCall(T.Val(19), T.Val(42), T.Val(-23));
- T.CheckCall(T.Val(6.5), T.Val(4.2), T.Val(2.3));
-}
-
-
-TEST(RuntimeCallJS) {
- FLAG_allow_natives_syntax = true;
- FunctionTester T("(function(a) { return %ToString(a); })");
-
- T.CheckCall(T.Val("23"), T.Val(23), T.undefined());
- T.CheckCall(T.Val("4.2"), T.Val(4.2), T.undefined());
- T.CheckCall(T.Val("str"), T.Val("str"), T.undefined());
- T.CheckCall(T.Val("true"), T.true_value(), T.undefined());
- T.CheckCall(T.Val("false"), T.false_value(), T.undefined());
- T.CheckCall(T.Val("undefined"), T.undefined(), T.undefined());
+ T.CheckCall(T.Val(2730), T.Val(42), T.Val(65));
+ T.CheckCall(T.Val(798), T.Val(42), T.Val(19));
}
TEST(RuntimeCallInline) {
FLAG_allow_natives_syntax = true;
- FunctionTester T("(function(a) { return %_IsObject(a); })");
+ FunctionTester T("(function(a) { return %_IsJSReceiver(a); })");
T.CheckCall(T.false_value(), T.Val(23), T.undefined());
T.CheckCall(T.false_value(), T.Val(4.2), T.undefined());
@@ -184,26 +155,6 @@
}
-TEST(RuntimeCallBooleanize) {
- // TODO(turbofan): %Booleanize will disappear, don't hesitate to remove this
- // test case, two-argument case is covered by the above test already.
- FLAG_allow_natives_syntax = true;
- FunctionTester T("(function(a,b) { return %Booleanize(a, b); })");
-
- T.CheckCall(T.true_value(), T.Val(-1), T.Val(Token::LT));
- T.CheckCall(T.false_value(), T.Val(-1), T.Val(Token::EQ));
- T.CheckCall(T.false_value(), T.Val(-1), T.Val(Token::GT));
-
- T.CheckCall(T.false_value(), T.Val(0.0), T.Val(Token::LT));
- T.CheckCall(T.true_value(), T.Val(0.0), T.Val(Token::EQ));
- T.CheckCall(T.false_value(), T.Val(0.0), T.Val(Token::GT));
-
- T.CheckCall(T.false_value(), T.Val(1), T.Val(Token::LT));
- T.CheckCall(T.false_value(), T.Val(1), T.Val(Token::EQ));
- T.CheckCall(T.true_value(), T.Val(1), T.Val(Token::GT));
-}
-
-
TEST(EvalCall) {
FunctionTester T("(function(a,b) { return eval(a); })");
Handle<JSObject> g(T.function->context()->global_object()->global_proxy());
@@ -262,7 +213,10 @@
i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value);
i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun);
jsfun->set_code(T.function->code());
- context->Global()->Set(v8_str("foo"), v8::Utils::ToLocal(jsfun));
+ jsfun->set_shared(T.function->shared());
+ CHECK(context->Global()
+ ->Set(context, v8_str("foo"), v8::Utils::CallableToLocal(jsfun))
+ .FromJust());
CompileRun("var x = 24;");
ExpectInt32("foo();", 24);
}
@@ -283,7 +237,14 @@
i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value);
i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun);
jsfun->set_code(T.function->code());
- context->Global()->Set(v8_str("foo"), v8::Utils::ToLocal(jsfun));
+ jsfun->set_shared(T.function->shared());
+ CHECK(context->Global()
+ ->Set(context, v8_str("foo"), v8::Utils::CallableToLocal(jsfun))
+ .FromJust());
CompileRun("var x = 24;");
ExpectObject("foo()", context->Global());
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-jsexceptions.cc b/test/cctest/compiler/test-run-jsexceptions.cc
index 0712ab6..37b2a2d 100644
--- a/test/cctest/compiler/test-run-jsexceptions.cc
+++ b/test/cctest/compiler/test-run-jsexceptions.cc
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "test/cctest/compiler/function-tester.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
TEST(Throw) {
FunctionTester T("(function(a,b) { if (a) { throw b; } else { return b; }})");
@@ -17,7 +16,7 @@
}
-TEST(ThrowSourcePosition) {
+TEST(ThrowMessagePosition) {
static const char* src =
"(function(a, b) { \n"
" if (a == 1) throw 1; \n"
@@ -26,20 +25,258 @@
" throw 4; \n"
"}) ";
FunctionTester T(src);
- v8::Handle<v8::Message> message;
+ v8::Local<v8::Message> message;
+ v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
message = T.CheckThrowsReturnMessage(T.Val(1), T.undefined());
- CHECK(!message.IsEmpty());
- CHECK_EQ(2, message->GetLineNumber());
+ CHECK_EQ(2, message->GetLineNumber(context).FromMaybe(-1));
CHECK_EQ(40, message->GetStartPosition());
message = T.CheckThrowsReturnMessage(T.Val(2), T.undefined());
- CHECK(!message.IsEmpty());
- CHECK_EQ(3, message->GetLineNumber());
+ CHECK_EQ(3, message->GetLineNumber(context).FromMaybe(-1));
CHECK_EQ(67, message->GetStartPosition());
message = T.CheckThrowsReturnMessage(T.Val(3), T.undefined());
- CHECK(!message.IsEmpty());
- CHECK_EQ(4, message->GetLineNumber());
+ CHECK_EQ(4, message->GetLineNumber(context).FromMaybe(-1));
CHECK_EQ(95, message->GetStartPosition());
}
+
+
+TEST(ThrowMessageDirectly) {
+ static const char* src =
+ "(function(a, b) {"
+ " if (a) { throw b; } else { throw new Error(b); }"
+ "})";
+ FunctionTester T(src);
+ v8::Local<v8::Message> message;
+ v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
+ v8::Maybe<bool> t = v8::Just(true);
+
+ message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?"));
+ CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Error: Wat?")));
+
+ message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!"));
+ CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Kaboom!")));
+}
+
+
+TEST(ThrowMessageIndirectly) {
+ i::FLAG_turbo_try_finally = true;
+ static const char* src =
+ "(function(a, b) {"
+ " try {"
+ " if (a) { throw b; } else { throw new Error(b); }"
+ " } finally {"
+ " try { throw 'clobber'; } catch (e) { 'unclobber'; }"
+ " }"
+ "})";
+ FunctionTester T(src);
+ v8::Local<v8::Message> message;
+ v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
+ v8::Maybe<bool> t = v8::Just(true);
+
+ message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?"));
+ CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Error: Wat?")));
+
+ message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!"));
+ CHECK(t == message->Get()->Equals(context, v8_str("Uncaught Kaboom!")));
+}
+
+
+TEST(Catch) {
+ const char* src =
+ "(function(a,b) {"
+ " var r = '-';"
+ " try {"
+ " r += 'A-';"
+ " throw 'B-';"
+ " } catch (e) {"
+ " r += e;"
+ " }"
+ " return r;"
+ "})";
+ FunctionTester T(src);
+
+ T.CheckCall(T.Val("-A-B-"));
+}
+
+
+TEST(CatchNested) {
+ const char* src =
+ "(function(a,b) {"
+ " var r = '-';"
+ " try {"
+ " r += 'A-';"
+ " throw 'C-';"
+ " } catch (e) {"
+ " try {"
+ " throw 'B-';"
+ " } catch (e) {"
+ " r += e;"
+ " }"
+ " r += e;"
+ " }"
+ " return r;"
+ "})";
+ FunctionTester T(src);
+
+ T.CheckCall(T.Val("-A-B-C-"));
+}
+
+
+TEST(CatchBreak) {
+ const char* src =
+ "(function(a,b) {"
+ " var r = '-';"
+ " L: try {"
+ " r += 'A-';"
+ " if (a) break L;"
+ " r += 'B-';"
+ " throw 'C-';"
+ " } catch (e) {"
+ " if (b) break L;"
+ " r += e;"
+ " }"
+ " r += 'D-';"
+ " return r;"
+ "})";
+ FunctionTester T(src);
+
+ T.CheckCall(T.Val("-A-D-"), T.true_value(), T.false_value());
+ T.CheckCall(T.Val("-A-B-D-"), T.false_value(), T.true_value());
+ T.CheckCall(T.Val("-A-B-C-D-"), T.false_value(), T.false_value());
+}
+
+
+TEST(CatchCall) {
+ const char* src =
+ "(function(fun) {"
+ " var r = '-';"
+ " try {"
+ " r += 'A-';"
+ " return r + 'B-' + fun();"
+ " } catch (e) {"
+ " r += e;"
+ " }"
+ " return r;"
+ "})";
+ FunctionTester T(src);
+
+ CompileRun("function thrower() { throw 'T-'; }");
+ T.CheckCall(T.Val("-A-T-"), T.NewFunction("thrower"));
+ CompileRun("function returner() { return 'R-'; }");
+ T.CheckCall(T.Val("-A-B-R-"), T.NewFunction("returner"));
+}
+
+
+TEST(Finally) {
+ i::FLAG_turbo_try_finally = true;
+ const char* src =
+ "(function(a,b) {"
+ " var r = '-';"
+ " try {"
+ " r += 'A-';"
+ " } finally {"
+ " r += 'B-';"
+ " }"
+ " return r;"
+ "})";
+ FunctionTester T(src);
+
+ T.CheckCall(T.Val("-A-B-"));
+}
+
+
+TEST(FinallyBreak) {
+ i::FLAG_turbo_try_finally = true;
+ const char* src =
+ "(function(a,b) {"
+ " var r = '-';"
+ " L: try {"
+ " r += 'A-';"
+ " if (a) return r;"
+ " r += 'B-';"
+ " if (b) break L;"
+ " r += 'C-';"
+ " } finally {"
+ " r += 'D-';"
+ " }"
+ " return r;"
+ "})";
+ FunctionTester T(src);
+
+ T.CheckCall(T.Val("-A-"), T.true_value(), T.false_value());
+ T.CheckCall(T.Val("-A-B-D-"), T.false_value(), T.true_value());
+ T.CheckCall(T.Val("-A-B-C-D-"), T.false_value(), T.false_value());
+}
+
+
+TEST(DeoptTry) {
+ const char* src =
+ "(function f(a) {"
+ " try {"
+ " %DeoptimizeFunction(f);"
+ " throw a;"
+ " } catch (e) {"
+ " return e + 1;"
+ " }"
+ "})";
+ FunctionTester T(src);
+
+ T.CheckCall(T.Val(2), T.Val(1));
+}
+
+
+TEST(DeoptCatch) {
+ const char* src =
+ "(function f(a) {"
+ " try {"
+ " throw a;"
+ " } catch (e) {"
+ " %DeoptimizeFunction(f);"
+ " return e + 1;"
+ " }"
+ "})";
+ FunctionTester T(src);
+
+ T.CheckCall(T.Val(2), T.Val(1));
+}
+
+
+TEST(DeoptFinallyReturn) {
+ i::FLAG_turbo_try_finally = true;
+ const char* src =
+ "(function f(a) {"
+ " try {"
+ " throw a;"
+ " } finally {"
+ " %DeoptimizeFunction(f);"
+ " return a + 1;"
+ " }"
+ "})";
+ FunctionTester T(src);
+
+ T.CheckCall(T.Val(2), T.Val(1));
+}
+
+
+TEST(DeoptFinallyReThrow) {
+ i::FLAG_turbo_try_finally = true;
+ const char* src =
+ "(function f(a) {"
+ " try {"
+ " throw a;"
+ " } finally {"
+ " %DeoptimizeFunction(f);"
+ " }"
+ "})";
+ FunctionTester T(src);
+
+#if 0 // TODO(mstarzinger): Enable once we can.
+ T.CheckThrows(T.NewObject("new Error"), T.Val(1));
+#endif
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-jsobjects.cc b/test/cctest/compiler/test-run-jsobjects.cc
new file mode 100644
index 0000000..4bf10ca
--- /dev/null
+++ b/test/cctest/compiler/test-run-jsobjects.cc
@@ -0,0 +1,51 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "test/cctest/compiler/function-tester.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+TEST(ArgumentsMapped) {
+ FunctionTester T("(function(a) { return arguments; })");
+
+ Handle<Object> arguments;
+ T.Call(T.Val(19), T.Val(23), T.Val(42), T.Val(65)).ToHandle(&arguments);
+ CHECK(arguments->IsJSObject() && !arguments->IsJSArray());
+ CHECK(JSObject::cast(*arguments)->HasSloppyArgumentsElements());
+ Handle<String> l = T.isolate->factory()->length_string();
+ Handle<Object> length = JSObject::GetProperty(arguments, l).ToHandleChecked();
+ CHECK_EQ(4, length->Number());
+}
+
+
+TEST(ArgumentsUnmapped) {
+ FunctionTester T("(function(a) { 'use strict'; return arguments; })");
+
+ Handle<Object> arguments;
+ T.Call(T.Val(19), T.Val(23), T.Val(42), T.Val(65)).ToHandle(&arguments);
+ CHECK(arguments->IsJSObject() && !arguments->IsJSArray());
+ CHECK(!JSObject::cast(*arguments)->HasSloppyArgumentsElements());
+ Handle<String> l = T.isolate->factory()->length_string();
+ Handle<Object> length = JSObject::GetProperty(arguments, l).ToHandleChecked();
+ CHECK_EQ(4, length->Number());
+}
+
+
+TEST(ArgumentsRest) {
+ FunctionTester T("(function(a, ...args) { return args; })");
+
+ Handle<Object> arguments;
+ T.Call(T.Val(19), T.Val(23), T.Val(42), T.Val(65)).ToHandle(&arguments);
+ CHECK(arguments->IsJSObject() && arguments->IsJSArray());
+ CHECK(!JSObject::cast(*arguments)->HasSloppyArgumentsElements());
+ Handle<String> l = T.isolate->factory()->length_string();
+ Handle<Object> length = JSObject::GetProperty(arguments, l).ToHandleChecked();
+ CHECK_EQ(3, length->Number());
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-jsops.cc b/test/cctest/compiler/test-run-jsops.cc
index eb39760..9a2c467 100644
--- a/test/cctest/compiler/test-run-jsops.cc
+++ b/test/cctest/compiler/test-run-jsops.cc
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "test/cctest/compiler/function-tester.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
TEST(BinopAdd) {
FunctionTester T("(function(a,b) { return a + b; })");
@@ -212,7 +211,7 @@
}
-TEST(BinopLessThanEqual) {
+TEST(BinopLessThanOrEqual) {
FunctionTester T("(function(a,b) { return a <= b; })");
T.CheckTrue(7, 8);
@@ -396,6 +395,7 @@
TEST(GlobalStoreSloppy) {
+ FLAG_legacy_const = true;
FunctionTester T("(function(a,b) { g = a + b; return g; })");
T.CheckCall(T.Val(33), T.Val(22), T.Val(11));
@@ -451,7 +451,6 @@
TEST(BlockLoadStore) {
- FLAG_harmony_scoping = true;
FunctionTester T("(function(a) { 'use strict'; { let x = a+a; return x; }})");
T.CheckCall(T.Val(46), T.Val(23));
@@ -460,7 +459,6 @@
TEST(BlockLoadStoreNested) {
- FLAG_harmony_scoping = true;
const char* src =
"(function(a,b) {"
"'use strict';"
@@ -522,3 +520,26 @@
T.CheckTrue(T.Val("abc"));
T.CheckFalse(T.Val("xyz"));
}
+
+
+TEST(ClassLiteral) {
+ FLAG_harmony_sloppy = true;
+ const char* src =
+ "(function(a,b) {"
+ " class C {"
+ " x() { return a; }"
+ " static y() { return b; }"
+ " get z() { return 0; }"
+ " constructor() {}"
+ " }"
+ " return new C().x() + C.y();"
+ "})";
+ FunctionTester T(src);
+
+ T.CheckCall(T.Val(65), T.Val(23), T.Val(42));
+ T.CheckCall(T.Val("ab"), T.Val("a"), T.Val("b"));
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-machops.cc b/test/cctest/compiler/test-run-machops.cc
index 974d4ce..11a3582 100644
--- a/test/cctest/compiler/test-run-machops.cc
+++ b/test/cctest/compiler/test-run-machops.cc
@@ -1,28 +1,25 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+// Copyright 2014 the V8 project authors. All rights reserved. Use of this
+// source code is governed by a BSD-style license that can be found in the
+// LICENSE file.
#include <cmath>
#include <functional>
#include <limits>
#include "src/base/bits.h"
+#include "src/base/utils/random-number-generator.h"
#include "src/codegen.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
+#include "test/cctest/compiler/graph-builder-tester.h"
#include "test/cctest/compiler/value-helper.h"
-#if V8_TURBOFAN_TARGET
-
using namespace v8::base;
-#define CHECK_UINT32_EQ(x, y) \
- CHECK_EQ(static_cast<int32_t>(x), static_cast<int32_t>(y))
+namespace v8 {
+namespace internal {
+namespace compiler {
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-typedef RawMachineAssembler::Label MLabel;
TEST(RunInt32Add) {
RawMachineAssemblerTester<int32_t> m;
@@ -32,6 +29,278 @@
}
+TEST(RunWord32Ctz) {
+ BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
+ if (!m.machine()->Word32Ctz().IsSupported()) {
+ // We can only test the operator if it exists on the testing platform.
+ return;
+ }
+ m.Return(m.AddNode(m.machine()->Word32Ctz().op(), m.Parameter(0)));
+
+ CHECK_EQ(32, m.Call(uint32_t(0x00000000)));
+ CHECK_EQ(31, m.Call(uint32_t(0x80000000)));
+ CHECK_EQ(30, m.Call(uint32_t(0x40000000)));
+ CHECK_EQ(29, m.Call(uint32_t(0x20000000)));
+ CHECK_EQ(28, m.Call(uint32_t(0x10000000)));
+ CHECK_EQ(27, m.Call(uint32_t(0xa8000000)));
+ CHECK_EQ(26, m.Call(uint32_t(0xf4000000)));
+ CHECK_EQ(25, m.Call(uint32_t(0x62000000)));
+ CHECK_EQ(24, m.Call(uint32_t(0x91000000)));
+ CHECK_EQ(23, m.Call(uint32_t(0xcd800000)));
+ CHECK_EQ(22, m.Call(uint32_t(0x09400000)));
+ CHECK_EQ(21, m.Call(uint32_t(0xaf200000)));
+ CHECK_EQ(20, m.Call(uint32_t(0xac100000)));
+ CHECK_EQ(19, m.Call(uint32_t(0xe0b80000)));
+ CHECK_EQ(18, m.Call(uint32_t(0x9ce40000)));
+ CHECK_EQ(17, m.Call(uint32_t(0xc7920000)));
+ CHECK_EQ(16, m.Call(uint32_t(0xb8f10000)));
+ CHECK_EQ(15, m.Call(uint32_t(0x3b9f8000)));
+ CHECK_EQ(14, m.Call(uint32_t(0xdb4c4000)));
+ CHECK_EQ(13, m.Call(uint32_t(0xe9a32000)));
+ CHECK_EQ(12, m.Call(uint32_t(0xfca61000)));
+ CHECK_EQ(11, m.Call(uint32_t(0x6c8a7800)));
+ CHECK_EQ(10, m.Call(uint32_t(0x8ce5a400)));
+ CHECK_EQ(9, m.Call(uint32_t(0xcb7d0200)));
+ CHECK_EQ(8, m.Call(uint32_t(0xcb4dc100)));
+ CHECK_EQ(7, m.Call(uint32_t(0xdfbec580)));
+ CHECK_EQ(6, m.Call(uint32_t(0x27a9db40)));
+ CHECK_EQ(5, m.Call(uint32_t(0xde3bcb20)));
+ CHECK_EQ(4, m.Call(uint32_t(0xd7e8a610)));
+ CHECK_EQ(3, m.Call(uint32_t(0x9afdbc88)));
+ CHECK_EQ(2, m.Call(uint32_t(0x9afdbc84)));
+ CHECK_EQ(1, m.Call(uint32_t(0x9afdbc82)));
+ CHECK_EQ(0, m.Call(uint32_t(0x9afdbc81)));
+}
+
+
+TEST(RunWord32Clz) {
+ BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
+ m.Return(m.Word32Clz(m.Parameter(0)));
+
+ CHECK_EQ(0, m.Call(uint32_t(0x80001000)));
+ CHECK_EQ(1, m.Call(uint32_t(0x40000500)));
+ CHECK_EQ(2, m.Call(uint32_t(0x20000300)));
+ CHECK_EQ(3, m.Call(uint32_t(0x10000003)));
+ CHECK_EQ(4, m.Call(uint32_t(0x08050000)));
+ CHECK_EQ(5, m.Call(uint32_t(0x04006000)));
+ CHECK_EQ(6, m.Call(uint32_t(0x02000000)));
+ CHECK_EQ(7, m.Call(uint32_t(0x010000a0)));
+ CHECK_EQ(8, m.Call(uint32_t(0x00800c00)));
+ CHECK_EQ(9, m.Call(uint32_t(0x00400000)));
+ CHECK_EQ(10, m.Call(uint32_t(0x0020000d)));
+ CHECK_EQ(11, m.Call(uint32_t(0x00100f00)));
+ CHECK_EQ(12, m.Call(uint32_t(0x00080000)));
+ CHECK_EQ(13, m.Call(uint32_t(0x00041000)));
+ CHECK_EQ(14, m.Call(uint32_t(0x00020020)));
+ CHECK_EQ(15, m.Call(uint32_t(0x00010300)));
+ CHECK_EQ(16, m.Call(uint32_t(0x00008040)));
+ CHECK_EQ(17, m.Call(uint32_t(0x00004005)));
+ CHECK_EQ(18, m.Call(uint32_t(0x00002050)));
+ CHECK_EQ(19, m.Call(uint32_t(0x00001700)));
+ CHECK_EQ(20, m.Call(uint32_t(0x00000870)));
+ CHECK_EQ(21, m.Call(uint32_t(0x00000405)));
+ CHECK_EQ(22, m.Call(uint32_t(0x00000203)));
+ CHECK_EQ(23, m.Call(uint32_t(0x00000101)));
+ CHECK_EQ(24, m.Call(uint32_t(0x00000089)));
+ CHECK_EQ(25, m.Call(uint32_t(0x00000041)));
+ CHECK_EQ(26, m.Call(uint32_t(0x00000022)));
+ CHECK_EQ(27, m.Call(uint32_t(0x00000013)));
+ CHECK_EQ(28, m.Call(uint32_t(0x00000008)));
+ CHECK_EQ(29, m.Call(uint32_t(0x00000004)));
+ CHECK_EQ(30, m.Call(uint32_t(0x00000002)));
+ CHECK_EQ(31, m.Call(uint32_t(0x00000001)));
+ CHECK_EQ(32, m.Call(uint32_t(0x00000000)));
+}
+
+
+TEST(RunWord32Popcnt) {
+ BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
+ if (!m.machine()->Word32Popcnt().IsSupported()) {
+ // We can only test the operator if it exists on the testing platform.
+ return;
+ }
+ m.Return(m.AddNode(m.machine()->Word32Popcnt().op(), m.Parameter(0)));
+
+ CHECK_EQ(0, m.Call(uint32_t(0x00000000)));
+ CHECK_EQ(1, m.Call(uint32_t(0x00000001)));
+ CHECK_EQ(1, m.Call(uint32_t(0x80000000)));
+ CHECK_EQ(32, m.Call(uint32_t(0xffffffff)));
+ CHECK_EQ(6, m.Call(uint32_t(0x000dc100)));
+ CHECK_EQ(9, m.Call(uint32_t(0xe00dc100)));
+ CHECK_EQ(11, m.Call(uint32_t(0xe00dc103)));
+ CHECK_EQ(9, m.Call(uint32_t(0x000dc107)));
+}
+
+
+#if V8_TARGET_ARCH_64_BIT
+TEST(RunWord64Clz) {
+ BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint64());
+ m.Return(m.Word64Clz(m.Parameter(0)));
+
+ CHECK_EQ(0, m.Call(uint64_t(0x8000100000000000)));
+ CHECK_EQ(1, m.Call(uint64_t(0x4000050000000000)));
+ CHECK_EQ(2, m.Call(uint64_t(0x2000030000000000)));
+ CHECK_EQ(3, m.Call(uint64_t(0x1000000300000000)));
+ CHECK_EQ(4, m.Call(uint64_t(0x0805000000000000)));
+ CHECK_EQ(5, m.Call(uint64_t(0x0400600000000000)));
+ CHECK_EQ(6, m.Call(uint64_t(0x0200000000000000)));
+ CHECK_EQ(7, m.Call(uint64_t(0x010000a000000000)));
+ CHECK_EQ(8, m.Call(uint64_t(0x00800c0000000000)));
+ CHECK_EQ(9, m.Call(uint64_t(0x0040000000000000)));
+ CHECK_EQ(10, m.Call(uint64_t(0x0020000d00000000)));
+ CHECK_EQ(11, m.Call(uint64_t(0x00100f0000000000)));
+ CHECK_EQ(12, m.Call(uint64_t(0x0008000000000000)));
+ CHECK_EQ(13, m.Call(uint64_t(0x0004100000000000)));
+ CHECK_EQ(14, m.Call(uint64_t(0x0002002000000000)));
+ CHECK_EQ(15, m.Call(uint64_t(0x0001030000000000)));
+ CHECK_EQ(16, m.Call(uint64_t(0x0000804000000000)));
+ CHECK_EQ(17, m.Call(uint64_t(0x0000400500000000)));
+ CHECK_EQ(18, m.Call(uint64_t(0x0000205000000000)));
+ CHECK_EQ(19, m.Call(uint64_t(0x0000170000000000)));
+ CHECK_EQ(20, m.Call(uint64_t(0x0000087000000000)));
+ CHECK_EQ(21, m.Call(uint64_t(0x0000040500000000)));
+ CHECK_EQ(22, m.Call(uint64_t(0x0000020300000000)));
+ CHECK_EQ(23, m.Call(uint64_t(0x0000010100000000)));
+ CHECK_EQ(24, m.Call(uint64_t(0x0000008900000000)));
+ CHECK_EQ(25, m.Call(uint64_t(0x0000004100000000)));
+ CHECK_EQ(26, m.Call(uint64_t(0x0000002200000000)));
+ CHECK_EQ(27, m.Call(uint64_t(0x0000001300000000)));
+ CHECK_EQ(28, m.Call(uint64_t(0x0000000800000000)));
+ CHECK_EQ(29, m.Call(uint64_t(0x0000000400000000)));
+ CHECK_EQ(30, m.Call(uint64_t(0x0000000200000000)));
+ CHECK_EQ(31, m.Call(uint64_t(0x0000000100000000)));
+ CHECK_EQ(32, m.Call(uint64_t(0x0000000080001000)));
+ CHECK_EQ(33, m.Call(uint64_t(0x0000000040000500)));
+ CHECK_EQ(34, m.Call(uint64_t(0x0000000020000300)));
+ CHECK_EQ(35, m.Call(uint64_t(0x0000000010000003)));
+ CHECK_EQ(36, m.Call(uint64_t(0x0000000008050000)));
+ CHECK_EQ(37, m.Call(uint64_t(0x0000000004006000)));
+ CHECK_EQ(38, m.Call(uint64_t(0x0000000002000000)));
+ CHECK_EQ(39, m.Call(uint64_t(0x00000000010000a0)));
+ CHECK_EQ(40, m.Call(uint64_t(0x0000000000800c00)));
+ CHECK_EQ(41, m.Call(uint64_t(0x0000000000400000)));
+ CHECK_EQ(42, m.Call(uint64_t(0x000000000020000d)));
+ CHECK_EQ(43, m.Call(uint64_t(0x0000000000100f00)));
+ CHECK_EQ(44, m.Call(uint64_t(0x0000000000080000)));
+ CHECK_EQ(45, m.Call(uint64_t(0x0000000000041000)));
+ CHECK_EQ(46, m.Call(uint64_t(0x0000000000020020)));
+ CHECK_EQ(47, m.Call(uint64_t(0x0000000000010300)));
+ CHECK_EQ(48, m.Call(uint64_t(0x0000000000008040)));
+ CHECK_EQ(49, m.Call(uint64_t(0x0000000000004005)));
+ CHECK_EQ(50, m.Call(uint64_t(0x0000000000002050)));
+ CHECK_EQ(51, m.Call(uint64_t(0x0000000000001700)));
+ CHECK_EQ(52, m.Call(uint64_t(0x0000000000000870)));
+ CHECK_EQ(53, m.Call(uint64_t(0x0000000000000405)));
+ CHECK_EQ(54, m.Call(uint64_t(0x0000000000000203)));
+ CHECK_EQ(55, m.Call(uint64_t(0x0000000000000101)));
+ CHECK_EQ(56, m.Call(uint64_t(0x0000000000000089)));
+ CHECK_EQ(57, m.Call(uint64_t(0x0000000000000041)));
+ CHECK_EQ(58, m.Call(uint64_t(0x0000000000000022)));
+ CHECK_EQ(59, m.Call(uint64_t(0x0000000000000013)));
+ CHECK_EQ(60, m.Call(uint64_t(0x0000000000000008)));
+ CHECK_EQ(61, m.Call(uint64_t(0x0000000000000004)));
+ CHECK_EQ(62, m.Call(uint64_t(0x0000000000000002)));
+ CHECK_EQ(63, m.Call(uint64_t(0x0000000000000001)));
+ CHECK_EQ(64, m.Call(uint64_t(0x0000000000000000)));
+}
+
+
+TEST(RunWord64Ctz) {
+ RawMachineAssemblerTester<int32_t> m(MachineType::Uint64());
+ if (!m.machine()->Word64Ctz().IsSupported()) {
+ return;
+ }
+
+ m.Return(m.AddNode(m.machine()->Word64Ctz().op(), m.Parameter(0)));
+
+ CHECK_EQ(64, m.Call(uint64_t(0x0000000000000000)));
+ CHECK_EQ(63, m.Call(uint64_t(0x8000000000000000)));
+ CHECK_EQ(62, m.Call(uint64_t(0x4000000000000000)));
+ CHECK_EQ(61, m.Call(uint64_t(0x2000000000000000)));
+ CHECK_EQ(60, m.Call(uint64_t(0x1000000000000000)));
+ CHECK_EQ(59, m.Call(uint64_t(0xa800000000000000)));
+ CHECK_EQ(58, m.Call(uint64_t(0xf400000000000000)));
+ CHECK_EQ(57, m.Call(uint64_t(0x6200000000000000)));
+ CHECK_EQ(56, m.Call(uint64_t(0x9100000000000000)));
+ CHECK_EQ(55, m.Call(uint64_t(0xcd80000000000000)));
+ CHECK_EQ(54, m.Call(uint64_t(0x0940000000000000)));
+ CHECK_EQ(53, m.Call(uint64_t(0xaf20000000000000)));
+ CHECK_EQ(52, m.Call(uint64_t(0xac10000000000000)));
+ CHECK_EQ(51, m.Call(uint64_t(0xe0b8000000000000)));
+ CHECK_EQ(50, m.Call(uint64_t(0x9ce4000000000000)));
+ CHECK_EQ(49, m.Call(uint64_t(0xc792000000000000)));
+ CHECK_EQ(48, m.Call(uint64_t(0xb8f1000000000000)));
+ CHECK_EQ(47, m.Call(uint64_t(0x3b9f800000000000)));
+ CHECK_EQ(46, m.Call(uint64_t(0xdb4c400000000000)));
+ CHECK_EQ(45, m.Call(uint64_t(0xe9a3200000000000)));
+ CHECK_EQ(44, m.Call(uint64_t(0xfca6100000000000)));
+ CHECK_EQ(43, m.Call(uint64_t(0x6c8a780000000000)));
+ CHECK_EQ(42, m.Call(uint64_t(0x8ce5a40000000000)));
+ CHECK_EQ(41, m.Call(uint64_t(0xcb7d020000000000)));
+ CHECK_EQ(40, m.Call(uint64_t(0xcb4dc10000000000)));
+ CHECK_EQ(39, m.Call(uint64_t(0xdfbec58000000000)));
+ CHECK_EQ(38, m.Call(uint64_t(0x27a9db4000000000)));
+ CHECK_EQ(37, m.Call(uint64_t(0xde3bcb2000000000)));
+ CHECK_EQ(36, m.Call(uint64_t(0xd7e8a61000000000)));
+ CHECK_EQ(35, m.Call(uint64_t(0x9afdbc8800000000)));
+ CHECK_EQ(34, m.Call(uint64_t(0x9afdbc8400000000)));
+ CHECK_EQ(33, m.Call(uint64_t(0x9afdbc8200000000)));
+ CHECK_EQ(32, m.Call(uint64_t(0x9afdbc8100000000)));
+ CHECK_EQ(31, m.Call(uint64_t(0x0000000080000000)));
+ CHECK_EQ(30, m.Call(uint64_t(0x0000000040000000)));
+ CHECK_EQ(29, m.Call(uint64_t(0x0000000020000000)));
+ CHECK_EQ(28, m.Call(uint64_t(0x0000000010000000)));
+ CHECK_EQ(27, m.Call(uint64_t(0x00000000a8000000)));
+ CHECK_EQ(26, m.Call(uint64_t(0x00000000f4000000)));
+ CHECK_EQ(25, m.Call(uint64_t(0x0000000062000000)));
+ CHECK_EQ(24, m.Call(uint64_t(0x0000000091000000)));
+ CHECK_EQ(23, m.Call(uint64_t(0x00000000cd800000)));
+ CHECK_EQ(22, m.Call(uint64_t(0x0000000009400000)));
+ CHECK_EQ(21, m.Call(uint64_t(0x00000000af200000)));
+ CHECK_EQ(20, m.Call(uint64_t(0x00000000ac100000)));
+ CHECK_EQ(19, m.Call(uint64_t(0x00000000e0b80000)));
+ CHECK_EQ(18, m.Call(uint64_t(0x000000009ce40000)));
+ CHECK_EQ(17, m.Call(uint64_t(0x00000000c7920000)));
+ CHECK_EQ(16, m.Call(uint64_t(0x00000000b8f10000)));
+ CHECK_EQ(15, m.Call(uint64_t(0x000000003b9f8000)));
+ CHECK_EQ(14, m.Call(uint64_t(0x00000000db4c4000)));
+ CHECK_EQ(13, m.Call(uint64_t(0x00000000e9a32000)));
+ CHECK_EQ(12, m.Call(uint64_t(0x00000000fca61000)));
+ CHECK_EQ(11, m.Call(uint64_t(0x000000006c8a7800)));
+ CHECK_EQ(10, m.Call(uint64_t(0x000000008ce5a400)));
+ CHECK_EQ(9, m.Call(uint64_t(0x00000000cb7d0200)));
+ CHECK_EQ(8, m.Call(uint64_t(0x00000000cb4dc100)));
+ CHECK_EQ(7, m.Call(uint64_t(0x00000000dfbec580)));
+ CHECK_EQ(6, m.Call(uint64_t(0x0000000027a9db40)));
+ CHECK_EQ(5, m.Call(uint64_t(0x00000000de3bcb20)));
+ CHECK_EQ(4, m.Call(uint64_t(0x00000000d7e8a610)));
+ CHECK_EQ(3, m.Call(uint64_t(0x000000009afdbc88)));
+ CHECK_EQ(2, m.Call(uint64_t(0x000000009afdbc84)));
+ CHECK_EQ(1, m.Call(uint64_t(0x000000009afdbc82)));
+ CHECK_EQ(0, m.Call(uint64_t(0x000000009afdbc81)));
+}
+
+
+TEST(RunWord64Popcnt) {
+ BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint64());
+ if (!m.machine()->Word64Popcnt().IsSupported()) {
+ return;
+ }
+
+ m.Return(m.AddNode(m.machine()->Word64Popcnt().op(), m.Parameter(0)));
+
+ CHECK_EQ(0, m.Call(uint64_t(0x0000000000000000)));
+ CHECK_EQ(1, m.Call(uint64_t(0x0000000000000001)));
+ CHECK_EQ(1, m.Call(uint64_t(0x8000000000000000)));
+ CHECK_EQ(64, m.Call(uint64_t(0xffffffffffffffff)));
+ CHECK_EQ(12, m.Call(uint64_t(0x000dc100000dc100)));
+ CHECK_EQ(18, m.Call(uint64_t(0xe00dc100e00dc100)));
+ CHECK_EQ(22, m.Call(uint64_t(0xe00dc103e00dc103)));
+ CHECK_EQ(18, m.Call(uint64_t(0x000dc107000dc107)));
+}
+#endif // V8_TARGET_ARCH_64_BIT
+
+
static Node* Int32Input(RawMachineAssemblerTester<int32_t>* m, int index) {
switch (index) {
case 0:
@@ -49,7 +318,7 @@
case 6:
return m->Int32Constant(0x01234567);
case 7:
- return m->Load(kMachInt32, m->PointerConstant(NULL));
+ return m->Load(MachineType::Int32(), m->PointerConstant(NULL));
default:
return NULL;
}
@@ -74,10 +343,11 @@
for (size_t i = 0; i < arraysize(kOps); ++i) {
for (int j = 0; j < 8; j++) {
for (int k = 0; k < 8; k++) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+ MachineType::Int32());
Node* a = Int32Input(&m, j);
Node* b = Int32Input(&m, k);
- m.Return(m.NewNode(kOps[i], a, b));
+ m.Return(m.AddNode(kOps[i], a, b));
m.GenerateCode();
}
}
@@ -85,11 +355,260 @@
}
+TEST(CodeGenNop) {
+ RawMachineAssemblerTester<void> m;
+ m.Return(m.Int32Constant(0));
+ m.GenerateCode();
+}
+
+
+#if V8_TARGET_ARCH_64_BIT
+static Node* Int64Input(RawMachineAssemblerTester<int64_t>* m, int index) {
+ switch (index) {
+ case 0:
+ return m->Parameter(0);
+ case 1:
+ return m->Parameter(1);
+ case 2:
+ return m->Int64Constant(0);
+ case 3:
+ return m->Int64Constant(1);
+ case 4:
+ return m->Int64Constant(-1);
+ case 5:
+ return m->Int64Constant(0xff);
+ case 6:
+ return m->Int64Constant(0x0123456789abcdefLL);
+ case 7:
+ return m->Load(MachineType::Int64(), m->PointerConstant(NULL));
+ default:
+ return NULL;
+ }
+}
+
+
+TEST(CodeGenInt64Binop) {
+ RawMachineAssemblerTester<void> m;
+
+ const Operator* kOps[] = {
+ m.machine()->Word64And(), m.machine()->Word64Or(),
+ m.machine()->Word64Xor(), m.machine()->Word64Shl(),
+ m.machine()->Word64Shr(), m.machine()->Word64Sar(),
+ m.machine()->Word64Equal(), m.machine()->Int64Add(),
+ m.machine()->Int64Sub(), m.machine()->Int64Mul(), m.machine()->Int64Div(),
+ m.machine()->Uint64Div(), m.machine()->Int64Mod(),
+ m.machine()->Uint64Mod(), m.machine()->Int64LessThan(),
+ m.machine()->Int64LessThanOrEqual(), m.machine()->Uint64LessThan(),
+ m.machine()->Uint64LessThanOrEqual()};
+
+ for (size_t i = 0; i < arraysize(kOps); ++i) {
+ for (int j = 0; j < 8; j++) {
+ for (int k = 0; k < 8; k++) {
+ RawMachineAssemblerTester<int64_t> m(MachineType::Int64(),
+ MachineType::Int64());
+ Node* a = Int64Input(&m, j);
+ Node* b = Int64Input(&m, k);
+ m.Return(m.AddNode(kOps[i], a, b));
+ m.GenerateCode();
+ }
+ }
+ }
+}
+
+
+TEST(RunInt64AddWithOverflowP) {
+ int64_t actual_val = -1;
+ RawMachineAssemblerTester<int32_t> m;
+ Int64BinopTester bt(&m);
+ Node* add = m.Int64AddWithOverflow(bt.param0, bt.param1);
+ Node* val = m.Projection(0, add);
+ Node* ovf = m.Projection(1, add);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
+ bt.AddReturn(ovf);
+ FOR_INT64_INPUTS(i) {
+ FOR_INT64_INPUTS(j) {
+ int64_t expected_val;
+ int expected_ovf = bits::SignedAddOverflow64(*i, *j, &expected_val);
+ CHECK_EQ(expected_ovf, bt.call(*i, *j));
+ CHECK_EQ(expected_val, actual_val);
+ }
+ }
+}
+
+
+TEST(RunInt64AddWithOverflowImm) {
+ int64_t actual_val = -1, expected_val = 0;
+ FOR_INT64_INPUTS(i) {
+ {
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int64());
+ Node* add = m.Int64AddWithOverflow(m.Int64Constant(*i), m.Parameter(0));
+ Node* val = m.Projection(0, add);
+ Node* ovf = m.Projection(1, add);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
+ m.Return(ovf);
+ FOR_INT64_INPUTS(j) {
+ int expected_ovf = bits::SignedAddOverflow64(*i, *j, &expected_val);
+ CHECK_EQ(expected_ovf, m.Call(*j));
+ CHECK_EQ(expected_val, actual_val);
+ }
+ }
+ {
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int64());
+ Node* add = m.Int64AddWithOverflow(m.Parameter(0), m.Int64Constant(*i));
+ Node* val = m.Projection(0, add);
+ Node* ovf = m.Projection(1, add);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
+ m.Return(ovf);
+ FOR_INT64_INPUTS(j) {
+ int expected_ovf = bits::SignedAddOverflow64(*i, *j, &expected_val);
+ CHECK_EQ(expected_ovf, m.Call(*j));
+ CHECK_EQ(expected_val, actual_val);
+ }
+ }
+ FOR_INT64_INPUTS(j) {
+ RawMachineAssemblerTester<int32_t> m;
+ Node* add =
+ m.Int64AddWithOverflow(m.Int64Constant(*i), m.Int64Constant(*j));
+ Node* val = m.Projection(0, add);
+ Node* ovf = m.Projection(1, add);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
+ m.Return(ovf);
+ int expected_ovf = bits::SignedAddOverflow64(*i, *j, &expected_val);
+ CHECK_EQ(expected_ovf, m.Call());
+ CHECK_EQ(expected_val, actual_val);
+ }
+ }
+}
+
+
+TEST(RunInt64AddWithOverflowInBranchP) {
+ int constant = 911777;
+ RawMachineLabel blocka, blockb;
+ RawMachineAssemblerTester<int32_t> m;
+ Int64BinopTester bt(&m);
+ Node* add = m.Int64AddWithOverflow(bt.param0, bt.param1);
+ Node* ovf = m.Projection(1, add);
+ m.Branch(ovf, &blocka, &blockb);
+ m.Bind(&blocka);
+ bt.AddReturn(m.Int64Constant(constant));
+ m.Bind(&blockb);
+ Node* val = m.Projection(0, add);
+ Node* truncated = m.TruncateInt64ToInt32(val);
+ bt.AddReturn(truncated);
+ FOR_INT64_INPUTS(i) {
+ FOR_INT64_INPUTS(j) {
+ int32_t expected = constant;
+ int64_t result;
+ if (!bits::SignedAddOverflow64(*i, *j, &result)) {
+ expected = static_cast<int32_t>(result);
+ }
+ CHECK_EQ(expected, bt.call(*i, *j));
+ }
+ }
+}
+
+
+TEST(RunInt64SubWithOverflowP) {
+ int64_t actual_val = -1;
+ RawMachineAssemblerTester<int32_t> m;
+ Int64BinopTester bt(&m);
+ Node* add = m.Int64SubWithOverflow(bt.param0, bt.param1);
+ Node* val = m.Projection(0, add);
+ Node* ovf = m.Projection(1, add);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
+ bt.AddReturn(ovf);
+ FOR_INT64_INPUTS(i) {
+ FOR_INT64_INPUTS(j) {
+ int64_t expected_val;
+ int expected_ovf = bits::SignedSubOverflow64(*i, *j, &expected_val);
+ CHECK_EQ(expected_ovf, bt.call(*i, *j));
+ CHECK_EQ(expected_val, actual_val);
+ }
+ }
+}
+
+
+TEST(RunInt64SubWithOverflowImm) {
+ int64_t actual_val = -1, expected_val = 0;
+ FOR_INT64_INPUTS(i) {
+ {
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int64());
+ Node* add = m.Int64SubWithOverflow(m.Int64Constant(*i), m.Parameter(0));
+ Node* val = m.Projection(0, add);
+ Node* ovf = m.Projection(1, add);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
+ m.Return(ovf);
+ FOR_INT64_INPUTS(j) {
+ int expected_ovf = bits::SignedSubOverflow64(*i, *j, &expected_val);
+ CHECK_EQ(expected_ovf, m.Call(*j));
+ CHECK_EQ(expected_val, actual_val);
+ }
+ }
+ {
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int64());
+ Node* add = m.Int64SubWithOverflow(m.Parameter(0), m.Int64Constant(*i));
+ Node* val = m.Projection(0, add);
+ Node* ovf = m.Projection(1, add);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
+ m.Return(ovf);
+ FOR_INT64_INPUTS(j) {
+ int expected_ovf = bits::SignedSubOverflow64(*j, *i, &expected_val);
+ CHECK_EQ(expected_ovf, m.Call(*j));
+ CHECK_EQ(expected_val, actual_val);
+ }
+ }
+ FOR_INT64_INPUTS(j) {
+ RawMachineAssemblerTester<int32_t> m;
+ Node* add =
+ m.Int64SubWithOverflow(m.Int64Constant(*i), m.Int64Constant(*j));
+ Node* val = m.Projection(0, add);
+ Node* ovf = m.Projection(1, add);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord64, val);
+ m.Return(ovf);
+ int expected_ovf = bits::SignedSubOverflow64(*i, *j, &expected_val);
+ CHECK_EQ(expected_ovf, m.Call());
+ CHECK_EQ(expected_val, actual_val);
+ }
+ }
+}
+
+
+TEST(RunInt64SubWithOverflowInBranchP) {
+ int constant = 911999;
+ RawMachineLabel blocka, blockb;
+ RawMachineAssemblerTester<int32_t> m;
+ Int64BinopTester bt(&m);
+ Node* sub = m.Int64SubWithOverflow(bt.param0, bt.param1);
+ Node* ovf = m.Projection(1, sub);
+ m.Branch(ovf, &blocka, &blockb);
+ m.Bind(&blocka);
+ bt.AddReturn(m.Int64Constant(constant));
+ m.Bind(&blockb);
+ Node* val = m.Projection(0, sub);
+ Node* truncated = m.TruncateInt64ToInt32(val);
+ bt.AddReturn(truncated);
+ FOR_INT64_INPUTS(i) {
+ FOR_INT64_INPUTS(j) {
+ int32_t expected = constant;
+ int64_t result;
+ if (!bits::SignedSubOverflow64(*i, *j, &result)) {
+ expected = static_cast<int32_t>(result);
+ }
+ CHECK_EQ(expected, static_cast<int32_t>(bt.call(*i, *j)));
+ }
+ }
+}
+
+
+// TODO(titzer): add tests that run 64-bit integer operations.
+#endif // V8_TARGET_ARCH_64_BIT
+
+
TEST(RunGoto) {
RawMachineAssemblerTester<int32_t> m;
int constant = 99999;
- MLabel next;
+ RawMachineLabel next;
m.Goto(&next);
m.Bind(&next);
m.Return(m.Int32Constant(constant));
@@ -102,7 +621,7 @@
RawMachineAssemblerTester<int32_t> m;
int constant = 9999977;
- MLabel labels[10];
+ RawMachineLabel labels[10];
for (size_t i = 0; i < arraysize(labels); i++) {
m.Goto(&labels[i]);
m.Bind(&labels[i]);
@@ -117,7 +636,7 @@
RawMachineAssemblerTester<int32_t> m;
int constant = 999777;
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
m.Branch(m.Int32Constant(0), &blocka, &blockb);
m.Bind(&blocka);
m.Return(m.Int32Constant(0 - constant));
@@ -133,7 +652,7 @@
int constant = 995666;
- MLabel blocka, blockb, end;
+ RawMachineLabel blocka, blockb, end;
m.Branch(m.Int32Constant(0), &blocka, &blockb);
m.Bind(&blocka);
m.Goto(&end);
@@ -150,7 +669,7 @@
RawMachineAssemblerTester<int32_t> m;
int constant = 999555;
- MLabel header, body, exit;
+ RawMachineLabel header, body, exit;
m.Goto(&header);
m.Bind(&header);
m.Branch(m.Int32Constant(0), &body, &exit);
@@ -165,62 +684,65 @@
template <typename R>
static void BuildDiamondPhi(RawMachineAssemblerTester<R>* m, Node* cond_node,
- MachineType type, Node* true_node,
+ MachineRepresentation rep, Node* true_node,
Node* false_node) {
- MLabel blocka, blockb;
- MLabel* end = m->Exit();
+ RawMachineLabel blocka, blockb, end;
m->Branch(cond_node, &blocka, &blockb);
m->Bind(&blocka);
- m->Goto(end);
+ m->Goto(&end);
m->Bind(&blockb);
- m->Goto(end);
+ m->Goto(&end);
- m->Bind(end);
- Node* phi = m->Phi(type, true_node, false_node);
+ m->Bind(&end);
+ Node* phi = m->Phi(rep, true_node, false_node);
m->Return(phi);
}
TEST(RunDiamondPhiConst) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
int false_val = 0xFF666;
int true_val = 0x00DDD;
Node* true_node = m.Int32Constant(true_val);
Node* false_node = m.Int32Constant(false_val);
- BuildDiamondPhi(&m, m.Parameter(0), kMachInt32, true_node, false_node);
+ BuildDiamondPhi(&m, m.Parameter(0), MachineRepresentation::kWord32, true_node,
+ false_node);
CHECK_EQ(false_val, m.Call(0));
CHECK_EQ(true_val, m.Call(1));
}
TEST(RunDiamondPhiNumber) {
- RawMachineAssemblerTester<Object*> m(kMachInt32);
+ RawMachineAssemblerTester<Object*> m(MachineType::Int32());
double false_val = -11.1;
double true_val = 200.1;
Node* true_node = m.NumberConstant(true_val);
Node* false_node = m.NumberConstant(false_val);
- BuildDiamondPhi(&m, m.Parameter(0), kMachAnyTagged, true_node, false_node);
+ BuildDiamondPhi(&m, m.Parameter(0), MachineRepresentation::kTagged, true_node,
+ false_node);
m.CheckNumber(false_val, m.Call(0));
m.CheckNumber(true_val, m.Call(1));
}
TEST(RunDiamondPhiString) {
- RawMachineAssemblerTester<Object*> m(kMachInt32);
+ RawMachineAssemblerTester<Object*> m(MachineType::Int32());
const char* false_val = "false";
const char* true_val = "true";
Node* true_node = m.StringConstant(true_val);
Node* false_node = m.StringConstant(false_val);
- BuildDiamondPhi(&m, m.Parameter(0), kMachAnyTagged, true_node, false_node);
+ BuildDiamondPhi(&m, m.Parameter(0), MachineRepresentation::kTagged, true_node,
+ false_node);
m.CheckString(false_val, m.Call(0));
m.CheckString(true_val, m.Call(1));
}
TEST(RunDiamondPhiParam) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32, kMachInt32);
- BuildDiamondPhi(&m, m.Parameter(0), kMachInt32, m.Parameter(1),
- m.Parameter(2));
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
+ BuildDiamondPhi(&m, m.Parameter(0), MachineRepresentation::kWord32,
+ m.Parameter(1), m.Parameter(2));
int32_t c1 = 0x260cb75a;
int32_t c2 = 0xcd3e9c8b;
int result = m.Call(0, c1, c2);
@@ -240,16 +762,15 @@
Node* false_node = m.Int32Constant(false_val);
// x = false_val; while(false) { x = true_val; } return x;
- MLabel body, header;
- MLabel* end = m.Exit();
+ RawMachineLabel body, header, end;
m.Goto(&header);
m.Bind(&header);
- Node* phi = m.Phi(kMachInt32, false_node, true_node);
- m.Branch(cond_node, &body, end);
+ Node* phi = m.Phi(MachineRepresentation::kWord32, false_node, true_node);
+ m.Branch(cond_node, &body, &end);
m.Bind(&body);
m.Goto(&header);
- m.Bind(end);
+ m.Bind(&end);
m.Return(phi);
CHECK_EQ(false_val, m.Call());
@@ -257,22 +778,24 @@
TEST(RunLoopPhiParam) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
- MLabel blocka, blockb;
- MLabel* end = m.Exit();
+ RawMachineLabel blocka, blockb, end;
m.Goto(&blocka);
m.Bind(&blocka);
- Node* phi = m.Phi(kMachInt32, m.Parameter(1), m.Parameter(2));
- Node* cond = m.Phi(kMachInt32, m.Parameter(0), m.Int32Constant(0));
- m.Branch(cond, &blockb, end);
+ Node* phi =
+ m.Phi(MachineRepresentation::kWord32, m.Parameter(1), m.Parameter(2));
+ Node* cond =
+ m.Phi(MachineRepresentation::kWord32, m.Parameter(0), m.Int32Constant(0));
+ m.Branch(cond, &blockb, &end);
m.Bind(&blockb);
m.Goto(&blocka);
- m.Bind(end);
+ m.Bind(&end);
m.Return(phi);
int32_t c1 = 0xa81903b4;
@@ -290,22 +813,21 @@
int false_val = 0x10777;
// x = false_val; while(false) { x++; } return x;
- MLabel header, body;
- MLabel* end = m.Exit();
+ RawMachineLabel header, body, end;
Node* false_node = m.Int32Constant(false_val);
m.Goto(&header);
m.Bind(&header);
- Node* phi = m.Phi(kMachInt32, false_node, false_node);
- m.Branch(m.Int32Constant(0), &body, end);
+ Node* phi = m.Phi(MachineRepresentation::kWord32, false_node, false_node);
+ m.Branch(m.Int32Constant(0), &body, &end);
m.Bind(&body);
Node* add = m.Int32Add(phi, m.Int32Constant(1));
phi->ReplaceInput(1, add);
m.Goto(&header);
- m.Bind(end);
+ m.Bind(&end);
m.Return(phi);
CHECK_EQ(false_val, m.Call());
@@ -317,21 +839,20 @@
Int32BinopTester bt(&m);
// x = 0; while(x ^ param) { x++; } return x;
- MLabel header, body;
- MLabel* end = m.Exit();
+ RawMachineLabel header, body, end;
Node* zero = m.Int32Constant(0);
m.Goto(&header);
m.Bind(&header);
- Node* phi = m.Phi(kMachInt32, zero, zero);
- m.Branch(m.WordXor(phi, bt.param0), &body, end);
+ Node* phi = m.Phi(MachineRepresentation::kWord32, zero, zero);
+ m.Branch(m.WordXor(phi, bt.param0), &body, &end);
m.Bind(&body);
phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1)));
m.Goto(&header);
- m.Bind(end);
+ m.Bind(&end);
bt.AddReturn(phi);
CHECK_EQ(11, bt.call(11, 0));
@@ -345,21 +866,20 @@
Int32BinopTester bt(&m);
// x = 0; while(x < param) { x++; } return x;
- MLabel header, body;
- MLabel* end = m.Exit();
+ RawMachineLabel header, body, end;
Node* zero = m.Int32Constant(0);
m.Goto(&header);
m.Bind(&header);
- Node* phi = m.Phi(kMachInt32, zero, zero);
- m.Branch(m.Int32LessThan(phi, bt.param0), &body, end);
+ Node* phi = m.Phi(MachineRepresentation::kWord32, zero, zero);
+ m.Branch(m.Int32LessThan(phi, bt.param0), &body, &end);
m.Bind(&body);
phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1)));
m.Goto(&header);
- m.Bind(end);
+ m.Bind(&end);
bt.AddReturn(phi);
CHECK_EQ(11, bt.call(11, 0));
@@ -374,21 +894,20 @@
Int32BinopTester bt(&m);
// x = 0; while(x < param) { x++; } return x;
- MLabel header, body;
- MLabel* end = m.Exit();
+ RawMachineLabel header, body, end;
Node* zero = m.Int32Constant(0);
m.Goto(&header);
m.Bind(&header);
- Node* phi = m.Phi(kMachInt32, zero, zero);
- m.Branch(m.Uint32LessThan(phi, bt.param0), &body, end);
+ Node* phi = m.Phi(MachineRepresentation::kWord32, zero, zero);
+ m.Branch(m.Uint32LessThan(phi, bt.param0), &body, &end);
m.Bind(&body);
phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1)));
m.Goto(&header);
- m.Bind(end);
+ m.Bind(&end);
bt.AddReturn(phi);
CHECK_EQ(11, bt.call(11, 0));
@@ -403,20 +922,20 @@
Int32BinopTester bt(&m);
// x = param; while(x) { x--; } return x;
- MLabel header, body;
- MLabel* end = m.Exit();
+ RawMachineLabel header, body, end;
m.Goto(&header);
m.Bind(&header);
- Node* phi = m.Phi(kMachInt32, bt.param0, m.Int32Constant(0));
- m.Branch(phi, &body, end);
+ Node* phi =
+ m.Phi(MachineRepresentation::kWord32, bt.param0, m.Int32Constant(0));
+ m.Branch(phi, &body, &end);
m.Bind(&body);
phi->ReplaceInput(1, m.Int32Sub(phi, m.Int32Constant(1)));
m.Goto(&header);
- m.Bind(end);
+ m.Bind(&end);
bt.AddReturn(phi);
CHECK_EQ(0, bt.call(11, 0));
@@ -425,37 +944,172 @@
}
+TEST(RunLoopIncrementFloat32) {
+ RawMachineAssemblerTester<int32_t> m;
+
+ // x = -3.0f; while(x < 10f) { x = x + 0.5f; } return (int) (double) x;
+ RawMachineLabel header, body, end;
+ Node* minus_3 = m.Float32Constant(-3.0f);
+ Node* ten = m.Float32Constant(10.0f);
+
+ m.Goto(&header);
+
+ m.Bind(&header);
+ Node* phi = m.Phi(MachineRepresentation::kFloat32, minus_3, ten);
+ m.Branch(m.Float32LessThan(phi, ten), &body, &end);
+
+ m.Bind(&body);
+ phi->ReplaceInput(1, m.Float32Add(phi, m.Float32Constant(0.5f)));
+ m.Goto(&header);
+
+ m.Bind(&end);
+ m.Return(m.ChangeFloat64ToInt32(m.ChangeFloat32ToFloat64(phi)));
+
+ CHECK_EQ(10, m.Call());
+}
+
+
TEST(RunLoopIncrementFloat64) {
RawMachineAssemblerTester<int32_t> m;
// x = -3.0; while(x < 10) { x = x + 0.5; } return (int) x;
- MLabel header, body;
- MLabel* end = m.Exit();
+ RawMachineLabel header, body, end;
Node* minus_3 = m.Float64Constant(-3.0);
Node* ten = m.Float64Constant(10.0);
m.Goto(&header);
m.Bind(&header);
- Node* phi = m.Phi(kMachFloat64, minus_3, ten);
- m.Branch(m.Float64LessThan(phi, ten), &body, end);
+ Node* phi = m.Phi(MachineRepresentation::kFloat64, minus_3, ten);
+ m.Branch(m.Float64LessThan(phi, ten), &body, &end);
m.Bind(&body);
phi->ReplaceInput(1, m.Float64Add(phi, m.Float64Constant(0.5)));
m.Goto(&header);
- m.Bind(end);
+ m.Bind(&end);
m.Return(m.ChangeFloat64ToInt32(phi));
CHECK_EQ(10, m.Call());
}
+TEST(RunSwitch1) {
+ RawMachineAssemblerTester<int32_t> m;
+
+ int constant = 11223344;
+
+ RawMachineLabel block0, block1, def, end;
+ RawMachineLabel* case_labels[] = {&block0, &block1};
+ int32_t case_values[] = {0, 1};
+ m.Switch(m.Int32Constant(0), &def, case_values, case_labels,
+ arraysize(case_labels));
+ m.Bind(&block0);
+ m.Goto(&end);
+ m.Bind(&block1);
+ m.Goto(&end);
+ m.Bind(&def);
+ m.Goto(&end);
+ m.Bind(&end);
+ m.Return(m.Int32Constant(constant));
+
+ CHECK_EQ(constant, m.Call());
+}
+
+
+TEST(RunSwitch2) {
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
+
+ RawMachineLabel blocka, blockb, blockc;
+ RawMachineLabel* case_labels[] = {&blocka, &blockb};
+ int32_t case_values[] = {std::numeric_limits<int32_t>::min(),
+ std::numeric_limits<int32_t>::max()};
+ m.Switch(m.Parameter(0), &blockc, case_values, case_labels,
+ arraysize(case_labels));
+ m.Bind(&blocka);
+ m.Return(m.Int32Constant(-1));
+ m.Bind(&blockb);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&blockc);
+ m.Return(m.Int32Constant(0));
+
+ CHECK_EQ(1, m.Call(std::numeric_limits<int32_t>::max()));
+ CHECK_EQ(-1, m.Call(std::numeric_limits<int32_t>::min()));
+ for (int i = -100; i < 100; i += 25) {
+ CHECK_EQ(0, m.Call(i));
+ }
+}
+
+
+TEST(RunSwitch3) {
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
+
+ RawMachineLabel blocka, blockb, blockc;
+ RawMachineLabel* case_labels[] = {&blocka, &blockb};
+ int32_t case_values[] = {std::numeric_limits<int32_t>::min() + 0,
+ std::numeric_limits<int32_t>::min() + 1};
+ m.Switch(m.Parameter(0), &blockc, case_values, case_labels,
+ arraysize(case_labels));
+ m.Bind(&blocka);
+ m.Return(m.Int32Constant(0));
+ m.Bind(&blockb);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&blockc);
+ m.Return(m.Int32Constant(2));
+
+ CHECK_EQ(0, m.Call(std::numeric_limits<int32_t>::min() + 0));
+ CHECK_EQ(1, m.Call(std::numeric_limits<int32_t>::min() + 1));
+ for (int i = -100; i < 100; i += 25) {
+ CHECK_EQ(2, m.Call(i));
+ }
+}
+
+
+TEST(RunSwitch4) {
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
+
+ const size_t kNumCases = 512;
+ const size_t kNumValues = kNumCases + 1;
+ int32_t values[kNumValues];
+ m.main_isolate()->random_number_generator()->NextBytes(values,
+ sizeof(values));
+ RawMachineLabel end, def;
+ int32_t case_values[kNumCases];
+ RawMachineLabel* case_labels[kNumCases];
+ Node* results[kNumValues];
+ for (size_t i = 0; i < kNumCases; ++i) {
+ case_values[i] = static_cast<int32_t>(i);
+ case_labels[i] =
+ new (m.main_zone()->New(sizeof(RawMachineLabel))) RawMachineLabel;
+ }
+ m.Switch(m.Parameter(0), &def, case_values, case_labels,
+ arraysize(case_labels));
+ for (size_t i = 0; i < kNumCases; ++i) {
+ m.Bind(case_labels[i]);
+ results[i] = m.Int32Constant(values[i]);
+ m.Goto(&end);
+ }
+ m.Bind(&def);
+ results[kNumCases] = m.Int32Constant(values[kNumCases]);
+ m.Goto(&end);
+ m.Bind(&end);
+ const int num_results = static_cast<int>(arraysize(results));
+ Node* phi =
+ m.AddNode(m.common()->Phi(MachineRepresentation::kWord32, num_results),
+ num_results, results);
+ m.Return(phi);
+
+ for (size_t i = 0; i < kNumValues; ++i) {
+ CHECK_EQ(values[i], m.Call(static_cast<int>(i)));
+ }
+}
+
+
TEST(RunLoadInt32) {
RawMachineAssemblerTester<int32_t> m;
int32_t p1 = 0; // loads directly from this location.
- m.Return(m.LoadFromPointer(&p1, kMachInt32));
+ m.Return(m.LoadFromPointer(&p1, MachineType::Int32()));
FOR_INT32_INPUTS(i) {
p1 = *i;
@@ -475,7 +1129,7 @@
int32_t offset = offsets[i];
byte* pointer = reinterpret_cast<byte*>(&p1) - offset;
// generate load [#base + #index]
- m.Return(m.LoadFromPointer(pointer, kMachInt32, offset));
+ m.Return(m.LoadFromPointer(pointer, MachineType::Int32(), offset));
FOR_INT32_INPUTS(j) {
p1 = *j;
@@ -485,6 +1139,33 @@
}
+TEST(RunLoadStoreFloat32Offset) {
+ float p1 = 0.0f; // loads directly from this location.
+ float p2 = 0.0f; // and stores directly into this location.
+
+ FOR_INT32_INPUTS(i) {
+ int32_t magic = 0x2342aabb + *i * 3;
+ RawMachineAssemblerTester<int32_t> m;
+ int32_t offset = *i;
+ byte* from = reinterpret_cast<byte*>(&p1) - offset;
+ byte* to = reinterpret_cast<byte*>(&p2) - offset;
+ // generate load [#base + #index]
+ Node* load = m.Load(MachineType::Float32(), m.PointerConstant(from),
+ m.IntPtrConstant(offset));
+ m.Store(MachineRepresentation::kFloat32, m.PointerConstant(to),
+ m.IntPtrConstant(offset), load, kNoWriteBarrier);
+ m.Return(m.Int32Constant(magic));
+
+ FOR_FLOAT32_INPUTS(j) {
+ p1 = *j;
+ p2 = *j - 5;
+ CHECK_EQ(magic, m.Call());
+ CheckDoubleEq(p1, p2);
+ }
+ }
+}
+
+
TEST(RunLoadStoreFloat64Offset) {
double p1 = 0; // loads directly from this location.
double p2 = 0; // and stores directly into this location.
@@ -496,16 +1177,17 @@
byte* from = reinterpret_cast<byte*>(&p1) - offset;
byte* to = reinterpret_cast<byte*>(&p2) - offset;
// generate load [#base + #index]
- Node* load =
- m.Load(kMachFloat64, m.PointerConstant(from), m.Int32Constant(offset));
- m.Store(kMachFloat64, m.PointerConstant(to), m.Int32Constant(offset), load);
+ Node* load = m.Load(MachineType::Float64(), m.PointerConstant(from),
+ m.IntPtrConstant(offset));
+ m.Store(MachineRepresentation::kFloat64, m.PointerConstant(to),
+ m.IntPtrConstant(offset), load, kNoWriteBarrier);
m.Return(m.Int32Constant(magic));
FOR_FLOAT64_INPUTS(j) {
p1 = *j;
p2 = *j - 5;
CHECK_EQ(magic, m.Call());
- CHECK_EQ(p1, p2);
+ CheckDoubleEq(p1, p2);
}
}
}
@@ -529,7 +1211,8 @@
TEST(RunInt32AddAndWord32EqualP) {
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
m.Return(m.Int32Add(m.Parameter(0),
m.Word32Equal(m.Parameter(1), m.Parameter(2))));
FOR_INT32_INPUTS(i) {
@@ -544,7 +1227,8 @@
}
}
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
m.Return(m.Int32Add(m.Word32Equal(m.Parameter(0), m.Parameter(1)),
m.Parameter(2)));
FOR_INT32_INPUTS(i) {
@@ -564,7 +1248,8 @@
TEST(RunInt32AddAndWord32EqualImm) {
{
FOR_INT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+ MachineType::Int32());
m.Return(m.Int32Add(m.Int32Constant(*i),
m.Word32Equal(m.Parameter(0), m.Parameter(1))));
FOR_INT32_INPUTS(j) {
@@ -579,7 +1264,8 @@
}
{
FOR_INT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+ MachineType::Int32());
m.Return(m.Int32Add(m.Word32Equal(m.Int32Constant(*i), m.Parameter(0)),
m.Parameter(1)));
FOR_INT32_INPUTS(j) {
@@ -597,7 +1283,8 @@
TEST(RunInt32AddAndWord32NotEqualP) {
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
m.Return(m.Int32Add(m.Parameter(0),
m.Word32NotEqual(m.Parameter(1), m.Parameter(2))));
FOR_INT32_INPUTS(i) {
@@ -612,7 +1299,8 @@
}
}
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
m.Return(m.Int32Add(m.Word32NotEqual(m.Parameter(0), m.Parameter(1)),
m.Parameter(2)));
FOR_INT32_INPUTS(i) {
@@ -632,7 +1320,8 @@
TEST(RunInt32AddAndWord32NotEqualImm) {
{
FOR_INT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+ MachineType::Int32());
m.Return(m.Int32Add(m.Int32Constant(*i),
m.Word32NotEqual(m.Parameter(0), m.Parameter(1))));
FOR_INT32_INPUTS(j) {
@@ -647,7 +1336,8 @@
}
{
FOR_INT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+ MachineType::Int32());
m.Return(m.Int32Add(m.Word32NotEqual(m.Int32Constant(*i), m.Parameter(0)),
m.Parameter(1)));
FOR_INT32_INPUTS(j) {
@@ -665,7 +1355,8 @@
TEST(RunInt32AddAndWord32SarP) {
{
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachInt32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
m.Return(m.Int32Add(m.Parameter(0),
m.Word32Sar(m.Parameter(1), m.Parameter(2))));
FOR_UINT32_INPUTS(i) {
@@ -679,7 +1370,8 @@
}
}
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachUint32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Uint32(), MachineType::Uint32());
m.Return(m.Int32Add(m.Word32Sar(m.Parameter(0), m.Parameter(1)),
m.Parameter(2)));
FOR_INT32_INPUTS(i) {
@@ -697,7 +1389,8 @@
TEST(RunInt32AddAndWord32ShlP) {
{
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachInt32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
m.Return(m.Int32Add(m.Parameter(0),
m.Word32Shl(m.Parameter(1), m.Parameter(2))));
FOR_UINT32_INPUTS(i) {
@@ -711,7 +1404,8 @@
}
}
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachUint32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Uint32(), MachineType::Uint32());
m.Return(m.Int32Add(m.Word32Shl(m.Parameter(0), m.Parameter(1)),
m.Parameter(2)));
FOR_INT32_INPUTS(i) {
@@ -729,7 +1423,8 @@
TEST(RunInt32AddAndWord32ShrP) {
{
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachUint32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
m.Return(m.Int32Add(m.Parameter(0),
m.Word32Shr(m.Parameter(1), m.Parameter(2))));
FOR_UINT32_INPUTS(i) {
@@ -743,7 +1438,8 @@
}
}
{
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachUint32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
m.Return(m.Int32Add(m.Word32Shr(m.Parameter(0), m.Parameter(1)),
m.Parameter(2)));
FOR_UINT32_INPUTS(i) {
@@ -763,8 +1459,8 @@
static const int32_t constant = 987654321;
{
RawMachineAssemblerTester<int32_t> m;
- Uint32BinopTester bt(&m);
- MLabel blocka, blockb;
+ Int32BinopTester bt(&m);
+ RawMachineLabel blocka, blockb;
m.Branch(
m.Word32Equal(m.Int32Add(bt.param0, bt.param1), m.Int32Constant(0)),
&blocka, &blockb);
@@ -781,8 +1477,8 @@
}
{
RawMachineAssemblerTester<int32_t> m;
- Uint32BinopTester bt(&m);
- MLabel blocka, blockb;
+ Int32BinopTester bt(&m);
+ RawMachineLabel blocka, blockb;
m.Branch(
m.Word32NotEqual(m.Int32Add(bt.param0, bt.param1), m.Int32Constant(0)),
&blocka, &blockb);
@@ -799,8 +1495,8 @@
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32Equal(m.Int32Add(m.Int32Constant(*i), m.Parameter(0)),
m.Int32Constant(0)),
&blocka, &blockb);
@@ -810,14 +1506,14 @@
m.Return(m.Int32Constant(0 - constant));
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i + *j) == 0 ? constant : 0 - constant;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32NotEqual(m.Int32Add(m.Int32Constant(*i), m.Parameter(0)),
m.Int32Constant(0)),
&blocka, &blockb);
@@ -827,7 +1523,7 @@
m.Return(m.Int32Constant(0 - constant));
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i + *j) != 0 ? constant : 0 - constant;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
@@ -837,11 +1533,11 @@
m.machine()->Word32Shl(),
m.machine()->Word32Shr()};
for (size_t n = 0; n < arraysize(shops); n++) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachInt32,
- kMachUint32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32Equal(m.Int32Add(m.Parameter(0),
- m.NewNode(shops[n], m.Parameter(1),
+ m.AddNode(shops[n], m.Parameter(1),
m.Parameter(2))),
m.Int32Constant(0)),
&blocka, &blockb);
@@ -885,7 +1581,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i + *j) == 0;
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
@@ -897,29 +1593,29 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i + *j) == 0;
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32Equal(m.Int32Add(m.Int32Constant(*i), m.Parameter(0)),
m.Int32Constant(0)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i + *j) == 0;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32Equal(m.Int32Add(m.Parameter(0), m.Int32Constant(*i)),
m.Int32Constant(0)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*j + *i) == 0;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
@@ -929,11 +1625,11 @@
m.machine()->Word32Shl(),
m.machine()->Word32Shr()};
for (size_t n = 0; n < arraysize(shops); n++) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachInt32,
- kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
m.Return(m.Word32Equal(
m.Int32Add(m.Parameter(0),
- m.NewNode(shops[n], m.Parameter(1), m.Parameter(2))),
+ m.AddNode(shops[n], m.Parameter(1), m.Parameter(2))),
m.Int32Constant(0)));
FOR_UINT32_INPUTS(i) {
FOR_INT32_INPUTS(j) {
@@ -971,7 +1667,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = static_cast<int32_t>(*i - *j);
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
@@ -980,21 +1676,21 @@
TEST(RunInt32SubImm) {
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i - *j;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Int32Sub(m.Parameter(0), m.Int32Constant(*i)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = *j - *i;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
@@ -1003,7 +1699,8 @@
TEST(RunInt32SubAndWord32SarP) {
{
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachInt32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
m.Return(m.Int32Sub(m.Parameter(0),
m.Word32Sar(m.Parameter(1), m.Parameter(2))));
FOR_UINT32_INPUTS(i) {
@@ -1016,7 +1713,8 @@
}
}
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachUint32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Uint32(), MachineType::Uint32());
m.Return(m.Int32Sub(m.Word32Sar(m.Parameter(0), m.Parameter(1)),
m.Parameter(2)));
FOR_INT32_INPUTS(i) {
@@ -1033,7 +1731,8 @@
TEST(RunInt32SubAndWord32ShlP) {
{
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachInt32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
m.Return(m.Int32Sub(m.Parameter(0),
m.Word32Shl(m.Parameter(1), m.Parameter(2))));
FOR_UINT32_INPUTS(i) {
@@ -1046,7 +1745,8 @@
}
}
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachUint32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Uint32(), MachineType::Uint32());
m.Return(m.Int32Sub(m.Word32Shl(m.Parameter(0), m.Parameter(1)),
m.Parameter(2)));
FOR_INT32_INPUTS(i) {
@@ -1064,30 +1764,30 @@
TEST(RunInt32SubAndWord32ShrP) {
{
- RawMachineAssemblerTester<uint32_t> m(kMachUint32, kMachUint32,
- kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(
+ MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
m.Return(m.Int32Sub(m.Parameter(0),
m.Word32Shr(m.Parameter(1), m.Parameter(2))));
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
FOR_UINT32_SHIFTS(shift) {
// Use uint32_t because signed overflow is UB in C.
- int32_t expected = *i - (*j >> shift);
- CHECK_UINT32_EQ(expected, m.Call(*i, *j, shift));
+ uint32_t expected = *i - (*j >> shift);
+ CHECK_EQ(expected, m.Call(*i, *j, shift));
}
}
}
}
{
- RawMachineAssemblerTester<uint32_t> m(kMachUint32, kMachUint32,
- kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(
+ MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
m.Return(m.Int32Sub(m.Word32Shr(m.Parameter(0), m.Parameter(1)),
m.Parameter(2)));
FOR_UINT32_INPUTS(i) {
FOR_UINT32_SHIFTS(shift) {
FOR_UINT32_INPUTS(k) {
// Use uint32_t because signed overflow is UB in C.
- int32_t expected = (*i >> shift) - *k;
+ uint32_t expected = (*i >> shift) - *k;
CHECK_EQ(expected, m.Call(*i, shift, *k));
}
}
@@ -1100,8 +1800,8 @@
static const int constant = 987654321;
{
RawMachineAssemblerTester<int32_t> m;
- Uint32BinopTester bt(&m);
- MLabel blocka, blockb;
+ Int32BinopTester bt(&m);
+ RawMachineLabel blocka, blockb;
m.Branch(
m.Word32Equal(m.Int32Sub(bt.param0, bt.param1), m.Int32Constant(0)),
&blocka, &blockb);
@@ -1118,8 +1818,8 @@
}
{
RawMachineAssemblerTester<int32_t> m;
- Uint32BinopTester bt(&m);
- MLabel blocka, blockb;
+ Int32BinopTester bt(&m);
+ RawMachineLabel blocka, blockb;
m.Branch(
m.Word32NotEqual(m.Int32Sub(bt.param0, bt.param1), m.Int32Constant(0)),
&blocka, &blockb);
@@ -1136,8 +1836,8 @@
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32Equal(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)),
m.Int32Constant(0)),
&blocka, &blockb);
@@ -1146,15 +1846,15 @@
m.Bind(&blockb);
m.Return(m.Int32Constant(0 - constant));
FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i - *j) == 0 ? constant : 0 - constant;
+ uint32_t expected = (*i - *j) == 0 ? constant : 0 - constant;
CHECK_EQ(expected, m.Call(*j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32NotEqual(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)),
m.Int32Constant(0)),
&blocka, &blockb);
@@ -1174,11 +1874,11 @@
m.machine()->Word32Shl(),
m.machine()->Word32Shr()};
for (size_t n = 0; n < arraysize(shops); n++) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachInt32,
- kMachUint32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32Equal(m.Int32Sub(m.Parameter(0),
- m.NewNode(shops[n], m.Parameter(1),
+ m.AddNode(shops[n], m.Parameter(1),
m.Parameter(2))),
m.Int32Constant(0)),
&blocka, &blockb);
@@ -1222,7 +1922,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i - *j) == 0;
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
@@ -1234,29 +1934,29 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i - *j) == 0;
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32Equal(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)),
m.Int32Constant(0)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i - *j) == 0;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32Equal(m.Int32Sub(m.Parameter(0), m.Int32Constant(*i)),
m.Int32Constant(0)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*j - *i) == 0;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
@@ -1266,11 +1966,11 @@
m.machine()->Word32Shl(),
m.machine()->Word32Shr()};
for (size_t n = 0; n < arraysize(shops); n++) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachInt32,
- kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
m.Return(m.Word32Equal(
m.Int32Sub(m.Parameter(0),
- m.NewNode(shops[n], m.Parameter(1), m.Parameter(2))),
+ m.AddNode(shops[n], m.Parameter(1), m.Parameter(2))),
m.Int32Constant(0)));
FOR_UINT32_INPUTS(i) {
FOR_INT32_INPUTS(j) {
@@ -1318,7 +2018,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i * *j;
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
@@ -1342,21 +2042,21 @@
TEST(RunInt32MulImm) {
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Int32Mul(m.Int32Constant(*i), m.Parameter(0)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i * *j;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant(*i)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = *j * *i;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
@@ -1367,7 +2067,7 @@
{
FOR_INT32_INPUTS(i) {
FOR_INT32_INPUTS(j) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
int32_t p0 = *i;
int32_t p1 = *j;
m.Return(m.Int32Add(m.Int32Constant(p0),
@@ -1381,7 +2081,8 @@
}
}
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
m.Return(
m.Int32Add(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
FOR_INT32_INPUTS(i) {
@@ -1397,7 +2098,8 @@
}
}
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32());
m.Return(
m.Int32Add(m.Int32Mul(m.Parameter(0), m.Parameter(1)), m.Parameter(2)));
FOR_INT32_INPUTS(i) {
@@ -1433,7 +2135,8 @@
TEST(RunInt32MulAndInt32SubP) {
{
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Int32(), MachineType::Int32());
m.Return(
m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
FOR_UINT32_INPUTS(i) {
@@ -1527,7 +2230,7 @@
uint32_t p0 = *i;
uint32_t p1 = *j;
if (p1 != 0) {
- uint32_t expected = static_cast<uint32_t>(p0 / p1);
+ int32_t expected = bit_cast<int32_t>(p0 / p1);
CHECK_EQ(expected, bt.call(p0, p1));
}
}
@@ -1542,7 +2245,7 @@
uint32_t p0 = *i;
uint32_t p1 = *j;
if (p1 != 0) {
- uint32_t expected = static_cast<uint32_t>(p0 + (p0 / p1));
+ int32_t expected = bit_cast<int32_t>(p0 + (p0 / p1));
CHECK_EQ(expected, bt.call(p0, p1));
}
}
@@ -1588,7 +2291,7 @@
TEST(RunUint32ModP) {
{
RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
+ Uint32BinopTester bt(&m);
bt.AddReturn(m.Uint32Mod(bt.param0, bt.param1));
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
@@ -1603,7 +2306,7 @@
}
{
RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
+ Uint32BinopTester bt(&m);
bt.AddReturn(m.Int32Add(bt.param0, m.Uint32Mod(bt.param0, bt.param1)));
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
@@ -1626,7 +2329,7 @@
bt.AddReturn(m.Word32And(bt.param0, bt.param1));
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i & *j;
+ int32_t expected = *i & *j;
CHECK_EQ(expected, bt.call(*i, *j));
}
}
@@ -1637,7 +2340,7 @@
bt.AddReturn(m.Word32And(bt.param0, m.Word32Not(bt.param1)));
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i & ~(*j);
+ int32_t expected = *i & ~(*j);
CHECK_EQ(expected, bt.call(*i, *j));
}
}
@@ -1648,7 +2351,7 @@
bt.AddReturn(m.Word32And(m.Word32Not(bt.param0), bt.param1));
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
- uint32_t expected = ~(*i) & *j;
+ int32_t expected = ~(*i) & *j;
CHECK_EQ(expected, bt.call(*i, *j));
}
}
@@ -1665,7 +2368,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i << (*j & 0x1f);
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
@@ -1677,7 +2380,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i << (0x1f & *j);
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
@@ -1693,7 +2396,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i >> (*j & 0x1f);
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
@@ -1705,7 +2408,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i >> (0x1f & *j);
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
@@ -1732,7 +2435,7 @@
m.Word32Sar(bt.param0, m.Word32And(m.Int32Constant(0x1f), bt.param1)));
FOR_INT32_INPUTS(i) {
FOR_INT32_INPUTS(j) {
- uint32_t expected = *i >> (0x1f & *j);
+ int32_t expected = *i >> (0x1f & *j);
CHECK_EQ(expected, bt.call(*i, *j));
}
}
@@ -1743,21 +2446,21 @@
TEST(RunWord32AndImm) {
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32And(m.Int32Constant(*i), m.Parameter(0)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i & *j;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32And(m.Int32Constant(*i), m.Word32Not(m.Parameter(0))));
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i & ~(*j);
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
@@ -1768,8 +2471,8 @@
static const int constant = 987654321;
{
RawMachineAssemblerTester<int32_t> m;
- Uint32BinopTester bt(&m);
- MLabel blocka, blockb;
+ Int32BinopTester bt(&m);
+ RawMachineLabel blocka, blockb;
m.Branch(
m.Word32Equal(m.Word32And(bt.param0, bt.param1), m.Int32Constant(0)),
&blocka, &blockb);
@@ -1786,8 +2489,8 @@
}
{
RawMachineAssemblerTester<int32_t> m;
- Uint32BinopTester bt(&m);
- MLabel blocka, blockb;
+ Int32BinopTester bt(&m);
+ RawMachineLabel blocka, blockb;
m.Branch(
m.Word32NotEqual(m.Word32And(bt.param0, bt.param1), m.Int32Constant(0)),
&blocka, &blockb);
@@ -1804,8 +2507,8 @@
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32Equal(m.Word32And(m.Int32Constant(*i), m.Parameter(0)),
m.Int32Constant(0)),
&blocka, &blockb);
@@ -1821,8 +2524,8 @@
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
+ RawMachineLabel blocka, blockb;
m.Branch(
m.Word32NotEqual(m.Word32And(m.Int32Constant(*i), m.Parameter(0)),
m.Int32Constant(0)),
@@ -1843,11 +2546,11 @@
m.machine()->Word32Shl(),
m.machine()->Word32Shr()};
for (size_t n = 0; n < arraysize(shops); n++) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachInt32,
- kMachUint32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32Equal(m.Word32And(m.Parameter(0),
- m.NewNode(shops[n], m.Parameter(1),
+ m.AddNode(shops[n], m.Parameter(1),
m.Parameter(2))),
m.Int32Constant(0)),
&blocka, &blockb);
@@ -1891,7 +2594,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i & *j) == 0;
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
@@ -1903,29 +2606,29 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i & *j) == 0;
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32Equal(m.Word32And(m.Int32Constant(*i), m.Parameter(0)),
m.Int32Constant(0)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i & *j) == 0;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32Equal(m.Word32And(m.Parameter(0), m.Int32Constant(*i)),
m.Int32Constant(0)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*j & *i) == 0;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
@@ -1940,7 +2643,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i | *j;
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
@@ -1951,7 +2654,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i | ~(*j);
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
@@ -1962,7 +2665,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = ~(*i) | *j;
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
@@ -1972,21 +2675,21 @@
TEST(RunWord32OrImm) {
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32Or(m.Int32Constant(*i), m.Parameter(0)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i | *j;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32Or(m.Int32Constant(*i), m.Word32Not(m.Parameter(0))));
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i | ~(*j);
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
@@ -1998,7 +2701,7 @@
{
RawMachineAssemblerTester<int32_t> m;
Int32BinopTester bt(&m);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
m.Branch(
m.Word32Equal(m.Word32Or(bt.param0, bt.param1), m.Int32Constant(0)),
&blocka, &blockb);
@@ -2016,7 +2719,7 @@
{
RawMachineAssemblerTester<int32_t> m;
Int32BinopTester bt(&m);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
m.Branch(
m.Word32NotEqual(m.Word32Or(bt.param0, bt.param1), m.Int32Constant(0)),
&blocka, &blockb);
@@ -2033,8 +2736,8 @@
}
{
FOR_INT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32Equal(m.Word32Or(m.Int32Constant(*i), m.Parameter(0)),
m.Int32Constant(0)),
&blocka, &blockb);
@@ -2050,8 +2753,8 @@
}
{
FOR_INT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32NotEqual(m.Word32Or(m.Int32Constant(*i), m.Parameter(0)),
m.Int32Constant(0)),
&blocka, &blockb);
@@ -2071,11 +2774,11 @@
m.machine()->Word32Shl(),
m.machine()->Word32Shr()};
for (size_t n = 0; n < arraysize(shops); n++) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachInt32,
- kMachUint32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32Equal(m.Word32Or(m.Parameter(0),
- m.NewNode(shops[n], m.Parameter(1),
+ m.AddNode(shops[n], m.Parameter(1),
m.Parameter(2))),
m.Int32Constant(0)),
&blocka, &blockb);
@@ -2113,7 +2816,7 @@
TEST(RunWord32OrInComparison) {
{
RawMachineAssemblerTester<int32_t> m;
- Uint32BinopTester bt(&m);
+ Int32BinopTester bt(&m);
bt.AddReturn(
m.Word32Equal(m.Word32Or(bt.param0, bt.param1), m.Int32Constant(0)));
FOR_UINT32_INPUTS(i) {
@@ -2125,7 +2828,7 @@
}
{
RawMachineAssemblerTester<int32_t> m;
- Uint32BinopTester bt(&m);
+ Int32BinopTester bt(&m);
bt.AddReturn(
m.Word32Equal(m.Int32Constant(0), m.Word32Or(bt.param0, bt.param1)));
FOR_UINT32_INPUTS(i) {
@@ -2137,23 +2840,23 @@
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32Equal(m.Word32Or(m.Int32Constant(*i), m.Parameter(0)),
m.Int32Constant(0)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i | *j) == 0;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32Equal(m.Word32Or(m.Parameter(0), m.Int32Constant(*i)),
m.Int32Constant(0)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*j | *i) == 0;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
@@ -2163,11 +2866,11 @@
TEST(RunWord32XorP) {
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32Xor(m.Int32Constant(*i), m.Parameter(0)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i ^ *j;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
@@ -2177,8 +2880,8 @@
bt.AddReturn(m.Word32Xor(bt.param0, bt.param1));
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
- int32_t expected = *i ^ *j;
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ uint32_t expected = *i ^ *j;
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
@@ -2206,11 +2909,11 @@
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32Xor(m.Int32Constant(*i), m.Word32Not(m.Parameter(0))));
FOR_UINT32_INPUTS(j) {
uint32_t expected = *i ^ ~(*j);
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
@@ -2222,7 +2925,7 @@
{
RawMachineAssemblerTester<int32_t> m;
Uint32BinopTester bt(&m);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
m.Branch(
m.Word32Equal(m.Word32Xor(bt.param0, bt.param1), m.Int32Constant(0)),
&blocka, &blockb);
@@ -2233,14 +2936,14 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i ^ *j) == 0 ? constant : 0 - constant;
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
{
RawMachineAssemblerTester<int32_t> m;
Uint32BinopTester bt(&m);
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
m.Branch(
m.Word32NotEqual(m.Word32Xor(bt.param0, bt.param1), m.Int32Constant(0)),
&blocka, &blockb);
@@ -2251,14 +2954,14 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i ^ *j) != 0 ? constant : 0 - constant;
- CHECK_UINT32_EQ(expected, bt.call(*i, *j));
+ CHECK_EQ(expected, bt.call(*i, *j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32Equal(m.Word32Xor(m.Int32Constant(*i), m.Parameter(0)),
m.Int32Constant(0)),
&blocka, &blockb);
@@ -2268,14 +2971,14 @@
m.Return(m.Int32Constant(0 - constant));
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i ^ *j) == 0 ? constant : 0 - constant;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
{
FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
+ RawMachineLabel blocka, blockb;
m.Branch(
m.Word32NotEqual(m.Word32Xor(m.Int32Constant(*i), m.Parameter(0)),
m.Int32Constant(0)),
@@ -2286,7 +2989,7 @@
m.Return(m.Int32Constant(0 - constant));
FOR_UINT32_INPUTS(j) {
uint32_t expected = (*i ^ *j) != 0 ? constant : 0 - constant;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
@@ -2296,11 +2999,11 @@
m.machine()->Word32Shl(),
m.machine()->Word32Shr()};
for (size_t n = 0; n < arraysize(shops); n++) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachInt32,
- kMachUint32);
- MLabel blocka, blockb;
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Int32(), MachineType::Uint32());
+ RawMachineLabel blocka, blockb;
m.Branch(m.Word32Equal(m.Word32Xor(m.Parameter(0),
- m.NewNode(shops[n], m.Parameter(1),
+ m.AddNode(shops[n], m.Parameter(1),
m.Parameter(2))),
m.Int32Constant(0)),
&blocka, &blockb);
@@ -2338,11 +3041,11 @@
TEST(RunWord32ShlP) {
{
FOR_UINT32_SHIFTS(shift) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32Shl(m.Parameter(0), m.Int32Constant(shift)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = *j << shift;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
@@ -2353,7 +3056,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_SHIFTS(shift) {
uint32_t expected = *i << shift;
- CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ CHECK_EQ(expected, bt.call(*i, shift));
}
}
}
@@ -2369,7 +3072,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_SHIFTS(shift) {
uint32_t expected = 0 == (*i << shift);
- CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ CHECK_EQ(expected, bt.call(*i, shift));
}
}
}
@@ -2381,31 +3084,31 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_SHIFTS(shift) {
uint32_t expected = 0 == (*i << shift);
- CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ CHECK_EQ(expected, bt.call(*i, shift));
}
}
}
{
FOR_UINT32_SHIFTS(shift) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(
m.Word32Equal(m.Int32Constant(0),
m.Word32Shl(m.Parameter(0), m.Int32Constant(shift))));
FOR_UINT32_INPUTS(i) {
uint32_t expected = 0 == (*i << shift);
- CHECK_UINT32_EQ(expected, m.Call(*i));
+ CHECK_EQ(expected, m.Call(*i));
}
}
}
{
FOR_UINT32_SHIFTS(shift) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(
m.Word32Equal(m.Word32Shl(m.Parameter(0), m.Int32Constant(shift)),
m.Int32Constant(0)));
FOR_UINT32_INPUTS(i) {
uint32_t expected = 0 == (*i << shift);
- CHECK_UINT32_EQ(expected, m.Call(*i));
+ CHECK_EQ(expected, m.Call(*i));
}
}
}
@@ -2415,11 +3118,11 @@
TEST(RunWord32ShrP) {
{
FOR_UINT32_SHIFTS(shift) {
- RawMachineAssemblerTester<uint32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)));
FOR_UINT32_INPUTS(j) {
uint32_t expected = *j >> shift;
- CHECK_UINT32_EQ(expected, m.Call(*j));
+ CHECK_EQ(expected, m.Call(*j));
}
}
}
@@ -2430,10 +3133,10 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_SHIFTS(shift) {
uint32_t expected = *i >> shift;
- CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ CHECK_EQ(expected, bt.call(*i, shift));
}
}
- CHECK_EQ(0x00010000, bt.call(0x80000000, 15));
+ CHECK_EQ(0x00010000u, bt.call(0x80000000, 15));
}
}
@@ -2447,7 +3150,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_SHIFTS(shift) {
uint32_t expected = 0 == (*i >> shift);
- CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ CHECK_EQ(expected, bt.call(*i, shift));
}
}
}
@@ -2459,31 +3162,31 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_SHIFTS(shift) {
uint32_t expected = 0 == (*i >> shift);
- CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ CHECK_EQ(expected, bt.call(*i, shift));
}
}
}
{
FOR_UINT32_SHIFTS(shift) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(
m.Word32Equal(m.Int32Constant(0),
m.Word32Shr(m.Parameter(0), m.Int32Constant(shift))));
FOR_UINT32_INPUTS(i) {
uint32_t expected = 0 == (*i >> shift);
- CHECK_UINT32_EQ(expected, m.Call(*i));
+ CHECK_EQ(expected, m.Call(*i));
}
}
}
{
FOR_UINT32_SHIFTS(shift) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(
m.Word32Equal(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)),
m.Int32Constant(0)));
FOR_UINT32_INPUTS(i) {
uint32_t expected = 0 == (*i >> shift);
- CHECK_UINT32_EQ(expected, m.Call(*i));
+ CHECK_EQ(expected, m.Call(*i));
}
}
}
@@ -2493,7 +3196,7 @@
TEST(RunWord32SarP) {
{
FOR_INT32_SHIFTS(shift) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
m.Return(m.Word32Sar(m.Parameter(0), m.Int32Constant(shift)));
FOR_INT32_INPUTS(j) {
int32_t expected = *j >> shift;
@@ -2511,7 +3214,7 @@
CHECK_EQ(expected, bt.call(*i, shift));
}
}
- CHECK_EQ(0xFFFF0000, bt.call(0x80000000, 15));
+ CHECK_EQ(bit_cast<int32_t>(0xFFFF0000), bt.call(0x80000000, 15));
}
}
@@ -2543,7 +3246,7 @@
}
{
FOR_INT32_SHIFTS(shift) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
m.Return(
m.Word32Equal(m.Int32Constant(0),
m.Word32Sar(m.Parameter(0), m.Int32Constant(shift))));
@@ -2555,12 +3258,12 @@
}
{
FOR_INT32_SHIFTS(shift) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
m.Return(
m.Word32Equal(m.Word32Sar(m.Parameter(0), m.Int32Constant(shift)),
m.Int32Constant(0)));
FOR_INT32_INPUTS(i) {
- uint32_t expected = 0 == (*i >> shift);
+ int32_t expected = 0 == (*i >> shift);
CHECK_EQ(expected, m.Call(*i));
}
}
@@ -2571,7 +3274,7 @@
TEST(RunWord32RorP) {
{
FOR_UINT32_SHIFTS(shift) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
m.Return(m.Word32Ror(m.Parameter(0), m.Int32Constant(shift)));
FOR_UINT32_INPUTS(j) {
int32_t expected = bits::RotateRight32(*j, shift);
@@ -2586,7 +3289,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_SHIFTS(shift) {
uint32_t expected = bits::RotateRight32(*i, shift);
- CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ CHECK_EQ(expected, bt.call(*i, shift));
}
}
}
@@ -2602,7 +3305,7 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_SHIFTS(shift) {
uint32_t expected = 0 == bits::RotateRight32(*i, shift);
- CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ CHECK_EQ(expected, bt.call(*i, shift));
}
}
}
@@ -2614,31 +3317,31 @@
FOR_UINT32_INPUTS(i) {
FOR_UINT32_SHIFTS(shift) {
uint32_t expected = 0 == bits::RotateRight32(*i, shift);
- CHECK_UINT32_EQ(expected, bt.call(*i, shift));
+ CHECK_EQ(expected, bt.call(*i, shift));
}
}
}
{
FOR_UINT32_SHIFTS(shift) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(
m.Word32Equal(m.Int32Constant(0),
m.Word32Ror(m.Parameter(0), m.Int32Constant(shift))));
FOR_UINT32_INPUTS(i) {
uint32_t expected = 0 == bits::RotateRight32(*i, shift);
- CHECK_UINT32_EQ(expected, m.Call(*i));
+ CHECK_EQ(expected, m.Call(*i));
}
}
}
{
FOR_UINT32_SHIFTS(shift) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
+ RawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
m.Return(
m.Word32Equal(m.Word32Ror(m.Parameter(0), m.Int32Constant(shift)),
m.Int32Constant(0)));
FOR_UINT32_INPUTS(i) {
uint32_t expected = 0 == bits::RotateRight32(*i, shift);
- CHECK_UINT32_EQ(expected, m.Call(*i));
+ CHECK_EQ(expected, m.Call(*i));
}
}
}
@@ -2646,7 +3349,7 @@
TEST(RunWord32NotP) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
m.Return(m.Word32Not(m.Parameter(0)));
FOR_INT32_INPUTS(i) {
int expected = ~(*i);
@@ -2656,7 +3359,7 @@
TEST(RunInt32NegP) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
m.Return(m.Int32Neg(m.Parameter(0)));
FOR_INT32_INPUTS(i) {
int expected = -*i;
@@ -2667,7 +3370,8 @@
TEST(RunWord32EqualAndWord32SarP) {
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Int32(), MachineType::Uint32());
m.Return(m.Word32Equal(m.Parameter(0),
m.Word32Sar(m.Parameter(1), m.Parameter(2))));
FOR_INT32_INPUTS(i) {
@@ -2680,7 +3384,8 @@
}
}
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachUint32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Int32(), MachineType::Uint32(), MachineType::Int32());
m.Return(m.Word32Equal(m.Word32Sar(m.Parameter(0), m.Parameter(1)),
m.Parameter(2)));
FOR_INT32_INPUTS(i) {
@@ -2697,7 +3402,8 @@
TEST(RunWord32EqualAndWord32ShlP) {
{
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachUint32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
m.Return(m.Word32Equal(m.Parameter(0),
m.Word32Shl(m.Parameter(1), m.Parameter(2))));
FOR_UINT32_INPUTS(i) {
@@ -2710,7 +3416,8 @@
}
}
{
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachUint32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
m.Return(m.Word32Equal(m.Word32Shl(m.Parameter(0), m.Parameter(1)),
m.Parameter(2)));
FOR_UINT32_INPUTS(i) {
@@ -2727,7 +3434,8 @@
TEST(RunWord32EqualAndWord32ShrP) {
{
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachUint32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
m.Return(m.Word32Equal(m.Parameter(0),
m.Word32Shr(m.Parameter(1), m.Parameter(2))));
FOR_UINT32_INPUTS(i) {
@@ -2740,7 +3448,8 @@
}
}
{
- RawMachineAssemblerTester<int32_t> m(kMachUint32, kMachUint32, kMachUint32);
+ RawMachineAssemblerTester<int32_t> m(
+ MachineType::Uint32(), MachineType::Uint32(), MachineType::Uint32());
m.Return(m.Word32Equal(m.Word32Shr(m.Parameter(0), m.Parameter(1)),
m.Parameter(2)));
FOR_UINT32_INPUTS(i) {
@@ -2757,7 +3466,8 @@
TEST(RunDeadNodes) {
for (int i = 0; true; i++) {
- RawMachineAssemblerTester<int32_t> m(i == 5 ? kMachInt32 : kMachNone);
+ RawMachineAssemblerTester<int32_t> m(i == 5 ? MachineType::Int32()
+ : MachineType::None());
int constant = 0x55 + i;
switch (i) {
case 0:
@@ -2773,7 +3483,7 @@
m.PointerConstant(&constant);
break;
case 4:
- m.LoadFromPointer(&constant, kMachInt32);
+ m.LoadFromPointer(&constant, MachineType::Int32());
break;
case 5:
m.Parameter(0);
@@ -2808,9 +3518,10 @@
m.machine()->Uint32LessThanOrEqual()};
for (size_t i = 0; i < arraysize(kOps); ++i) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+ MachineType::Int32());
int32_t constant = static_cast<int32_t>(0x55555 + i);
- m.NewNode(kOps[i], m.Parameter(0), m.Parameter(1));
+ m.AddNode(kOps[i], m.Parameter(0), m.Parameter(1));
m.Return(m.Int32Constant(constant));
CHECK_EQ(constant, m.Call(1, 1));
@@ -2846,16 +3557,16 @@
TEST(RunLoadImmIndex) {
- RunLoadImmIndex<int8_t>(kMachInt8);
- RunLoadImmIndex<uint8_t>(kMachUint8);
- RunLoadImmIndex<int16_t>(kMachInt16);
- RunLoadImmIndex<uint16_t>(kMachUint16);
- RunLoadImmIndex<int32_t>(kMachInt32);
- RunLoadImmIndex<uint32_t>(kMachUint32);
- RunLoadImmIndex<int32_t*>(kMachAnyTagged);
+ RunLoadImmIndex<int8_t>(MachineType::Int8());
+ RunLoadImmIndex<uint8_t>(MachineType::Uint8());
+ RunLoadImmIndex<int16_t>(MachineType::Int16());
+ RunLoadImmIndex<uint16_t>(MachineType::Uint16());
+ RunLoadImmIndex<int32_t>(MachineType::Int32());
+ RunLoadImmIndex<uint32_t>(MachineType::Uint32());
+ RunLoadImmIndex<int32_t*>(MachineType::AnyTagged());
// TODO(titzer): test kRepBit loads
- // TODO(titzer): test kMachFloat64 loads
+ // TODO(titzer): test MachineType::Float64() loads
// TODO(titzer): test various indexing modes.
}
@@ -2876,10 +3587,10 @@
RawMachineAssemblerTester<int32_t> m;
int32_t OK = 0x29000 + x;
Node* base = m.PointerConstant(buffer);
- Node* index0 = m.Int32Constant(x * sizeof(buffer[0]));
+ Node* index0 = m.IntPtrConstant(x * sizeof(buffer[0]));
Node* load = m.Load(rep, base, index0);
- Node* index1 = m.Int32Constant(y * sizeof(buffer[0]));
- m.Store(rep, base, index1, load);
+ Node* index1 = m.IntPtrConstant(y * sizeof(buffer[0]));
+ m.Store(rep.representation(), base, index1, load, kNoWriteBarrier);
m.Return(m.Int32Constant(OK));
CHECK(buffer[x] != buffer[y]);
@@ -2890,50 +3601,154 @@
TEST(RunLoadStore) {
- RunLoadStore<int8_t>(kMachInt8);
- RunLoadStore<uint8_t>(kMachUint8);
- RunLoadStore<int16_t>(kMachInt16);
- RunLoadStore<uint16_t>(kMachUint16);
- RunLoadStore<int32_t>(kMachInt32);
- RunLoadStore<uint32_t>(kMachUint32);
- RunLoadStore<void*>(kMachAnyTagged);
- RunLoadStore<float>(kMachFloat32);
- RunLoadStore<double>(kMachFloat64);
+ RunLoadStore<int8_t>(MachineType::Int8());
+ RunLoadStore<uint8_t>(MachineType::Uint8());
+ RunLoadStore<int16_t>(MachineType::Int16());
+ RunLoadStore<uint16_t>(MachineType::Uint16());
+ RunLoadStore<int32_t>(MachineType::Int32());
+ RunLoadStore<uint32_t>(MachineType::Uint32());
+ RunLoadStore<void*>(MachineType::AnyTagged());
+ RunLoadStore<float>(MachineType::Float32());
+ RunLoadStore<double>(MachineType::Float64());
}
-TEST(RunFloat64Binop) {
+TEST(RunFloat32Add) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Float32(),
+ MachineType::Float32());
+ m.Return(m.Float32Add(m.Parameter(0), m.Parameter(1)));
+
+ FOR_FLOAT32_INPUTS(i) {
+ FOR_FLOAT32_INPUTS(j) {
+ volatile float expected = *i + *j;
+ CheckFloatEq(expected, m.Call(*i, *j));
+ }
+ }
+}
+
+
+TEST(RunFloat32Sub) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Float32(),
+ MachineType::Float32());
+ m.Return(m.Float32Sub(m.Parameter(0), m.Parameter(1)));
+
+ FOR_FLOAT32_INPUTS(i) {
+ FOR_FLOAT32_INPUTS(j) {
+ volatile float expected = *i - *j;
+ CheckFloatEq(expected, m.Call(*i, *j));
+ }
+ }
+}
+
+
+TEST(RunFloat32Mul) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Float32(),
+ MachineType::Float32());
+ m.Return(m.Float32Mul(m.Parameter(0), m.Parameter(1)));
+
+ FOR_FLOAT32_INPUTS(i) {
+ FOR_FLOAT32_INPUTS(j) {
+ volatile float expected = *i * *j;
+ CheckFloatEq(expected, m.Call(*i, *j));
+ }
+ }
+}
+
+
+TEST(RunFloat32Div) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Float32(),
+ MachineType::Float32());
+ m.Return(m.Float32Div(m.Parameter(0), m.Parameter(1)));
+
+ FOR_FLOAT32_INPUTS(i) {
+ FOR_FLOAT32_INPUTS(j) {
+ volatile float expected = *i / *j;
+ CheckFloatEq(expected, m.Call(*i, *j));
+ }
+ }
+}
+
+
+TEST(RunFloat64Add) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
+ MachineType::Float64());
+ m.Return(m.Float64Add(m.Parameter(0), m.Parameter(1)));
+
+ FOR_FLOAT64_INPUTS(i) {
+ FOR_FLOAT64_INPUTS(j) {
+ volatile double expected = *i + *j;
+ CheckDoubleEq(expected, m.Call(*i, *j));
+ }
+ }
+}
+
+
+TEST(RunFloat64Sub) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
+ MachineType::Float64());
+ m.Return(m.Float64Sub(m.Parameter(0), m.Parameter(1)));
+
+ FOR_FLOAT64_INPUTS(i) {
+ FOR_FLOAT64_INPUTS(j) {
+ volatile double expected = *i - *j;
+ CheckDoubleEq(expected, m.Call(*i, *j));
+ }
+ }
+}
+
+
+TEST(RunFloat64Mul) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
+ MachineType::Float64());
+ m.Return(m.Float64Mul(m.Parameter(0), m.Parameter(1)));
+
+ FOR_FLOAT64_INPUTS(i) {
+ FOR_FLOAT64_INPUTS(j) {
+ volatile double expected = *i * *j;
+ CheckDoubleEq(expected, m.Call(*i, *j));
+ }
+ }
+}
+
+
+TEST(RunFloat64Div) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
+ MachineType::Float64());
+ m.Return(m.Float64Div(m.Parameter(0), m.Parameter(1)));
+
+ FOR_FLOAT64_INPUTS(i) {
+ FOR_FLOAT64_INPUTS(j) {
+ volatile double expected = *i / *j;
+ CheckDoubleEq(expected, m.Call(*i, *j));
+ }
+ }
+}
+
+
+TEST(RunFloat64Mod) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
+ MachineType::Float64());
+ m.Return(m.Float64Mod(m.Parameter(0), m.Parameter(1)));
+
+ FOR_FLOAT64_INPUTS(i) {
+ FOR_FLOAT64_INPUTS(j) { CheckDoubleEq(modulo(*i, *j), m.Call(*i, *j)); }
+ }
+}
+
+
+TEST(RunDeadFloat32Binops) {
RawMachineAssemblerTester<int32_t> m;
- double result;
- const Operator* ops[] = {m.machine()->Float64Add(), m.machine()->Float64Sub(),
- m.machine()->Float64Mul(), m.machine()->Float64Div(),
- m.machine()->Float64Mod(), NULL};
-
- double inf = V8_INFINITY;
- const Operator* inputs[] = {
- m.common()->Float64Constant(0), m.common()->Float64Constant(1),
- m.common()->Float64Constant(1), m.common()->Float64Constant(0),
- m.common()->Float64Constant(0), m.common()->Float64Constant(-1),
- m.common()->Float64Constant(-1), m.common()->Float64Constant(0),
- m.common()->Float64Constant(0.22), m.common()->Float64Constant(-1.22),
- m.common()->Float64Constant(-1.22), m.common()->Float64Constant(0.22),
- m.common()->Float64Constant(inf), m.common()->Float64Constant(0.22),
- m.common()->Float64Constant(inf), m.common()->Float64Constant(-inf),
- NULL};
+ const Operator* ops[] = {m.machine()->Float32Add(), m.machine()->Float32Sub(),
+ m.machine()->Float32Mul(), m.machine()->Float32Div(),
+ NULL};
for (int i = 0; ops[i] != NULL; i++) {
- for (int j = 0; inputs[j] != NULL; j += 2) {
- RawMachineAssemblerTester<int32_t> m;
- Node* a = m.NewNode(inputs[j]);
- Node* b = m.NewNode(inputs[j + 1]);
- Node* binop = m.NewNode(ops[i], a, b);
- Node* base = m.PointerConstant(&result);
- Node* zero = m.Int32Constant(0);
- m.Store(kMachFloat64, base, zero, binop);
- m.Return(m.Int32Constant(i + j));
- CHECK_EQ(i + j, m.Call());
- }
+ RawMachineAssemblerTester<int32_t> m;
+ int constant = 0x53355 + i;
+ m.AddNode(ops[i], m.Float32Constant(0.1f), m.Float32Constant(1.11f));
+ m.Return(m.Int32Constant(constant));
+ CHECK_EQ(constant, m.Call());
}
}
@@ -2948,13 +3763,28 @@
for (int i = 0; ops[i] != NULL; i++) {
RawMachineAssemblerTester<int32_t> m;
int constant = 0x53355 + i;
- m.NewNode(ops[i], m.Float64Constant(0.1), m.Float64Constant(1.11));
+ m.AddNode(ops[i], m.Float64Constant(0.1), m.Float64Constant(1.11));
m.Return(m.Int32Constant(constant));
CHECK_EQ(constant, m.Call());
}
}
+TEST(RunFloat32AddP) {
+ RawMachineAssemblerTester<int32_t> m;
+ Float32BinopTester bt(&m);
+
+ bt.AddReturn(m.Float32Add(bt.param0, bt.param1));
+
+ FOR_FLOAT32_INPUTS(pl) {
+ FOR_FLOAT32_INPUTS(pr) {
+ float expected = *pl + *pr;
+ CheckFloatEq(expected, bt.call(*pl, *pr));
+ }
+ }
+}
+
+
TEST(RunFloat64AddP) {
RawMachineAssemblerTester<int32_t> m;
Float64BinopTester bt(&m);
@@ -2964,12 +3794,137 @@
FOR_FLOAT64_INPUTS(pl) {
FOR_FLOAT64_INPUTS(pr) {
double expected = *pl + *pr;
- CHECK_EQ(expected, bt.call(*pl, *pr));
+ CheckDoubleEq(expected, bt.call(*pl, *pr));
}
}
}
+TEST(RunFloa32MaxP) {
+ RawMachineAssemblerTester<int32_t> m;
+ Float32BinopTester bt(&m);
+ if (!m.machine()->Float32Max().IsSupported()) return;
+
+ bt.AddReturn(m.Float32Max(bt.param0, bt.param1));
+
+ FOR_FLOAT32_INPUTS(pl) {
+ FOR_FLOAT32_INPUTS(pr) {
+ double expected = *pl > *pr ? *pl : *pr;
+ CheckDoubleEq(expected, bt.call(*pl, *pr));
+ }
+ }
+}
+
+
+TEST(RunFloat64MaxP) {
+ RawMachineAssemblerTester<int32_t> m;
+ Float64BinopTester bt(&m);
+ if (!m.machine()->Float64Max().IsSupported()) return;
+
+ bt.AddReturn(m.Float64Max(bt.param0, bt.param1));
+
+ FOR_FLOAT64_INPUTS(pl) {
+ FOR_FLOAT64_INPUTS(pr) {
+ double expected = *pl > *pr ? *pl : *pr;
+ CheckDoubleEq(expected, bt.call(*pl, *pr));
+ }
+ }
+}
+
+
+TEST(RunFloat32MinP) {
+ RawMachineAssemblerTester<int32_t> m;
+ Float32BinopTester bt(&m);
+ if (!m.machine()->Float32Min().IsSupported()) return;
+
+ bt.AddReturn(m.Float32Min(bt.param0, bt.param1));
+
+ FOR_FLOAT32_INPUTS(pl) {
+ FOR_FLOAT32_INPUTS(pr) {
+ double expected = *pl < *pr ? *pl : *pr;
+ CheckDoubleEq(expected, bt.call(*pl, *pr));
+ }
+ }
+}
+
+
+TEST(RunFloat64MinP) {
+ RawMachineAssemblerTester<int32_t> m;
+ Float64BinopTester bt(&m);
+ if (!m.machine()->Float64Min().IsSupported()) return;
+
+ bt.AddReturn(m.Float64Min(bt.param0, bt.param1));
+
+ FOR_FLOAT64_INPUTS(pl) {
+ FOR_FLOAT64_INPUTS(pr) {
+ double expected = *pl < *pr ? *pl : *pr;
+ CheckDoubleEq(expected, bt.call(*pl, *pr));
+ }
+ }
+}
+
+
+TEST(RunFloat32SubP) {
+ RawMachineAssemblerTester<int32_t> m;
+ Float32BinopTester bt(&m);
+
+ bt.AddReturn(m.Float32Sub(bt.param0, bt.param1));
+
+ FOR_FLOAT32_INPUTS(pl) {
+ FOR_FLOAT32_INPUTS(pr) {
+ float expected = *pl - *pr;
+ CheckFloatEq(expected, bt.call(*pl, *pr));
+ }
+ }
+}
+
+
+TEST(RunFloat32SubImm1) {
+ FOR_FLOAT32_INPUTS(i) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
+ m.Return(m.Float32Sub(m.Float32Constant(*i), m.Parameter(0)));
+
+ FOR_FLOAT32_INPUTS(j) {
+ volatile float expected = *i - *j;
+ CheckFloatEq(expected, m.Call(*j));
+ }
+ }
+}
+
+
+TEST(RunFloat32SubImm2) {
+ FOR_FLOAT32_INPUTS(i) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
+ m.Return(m.Float32Sub(m.Parameter(0), m.Float32Constant(*i)));
+
+ FOR_FLOAT32_INPUTS(j) {
+ volatile float expected = *j - *i;
+ CheckFloatEq(expected, m.Call(*j));
+ }
+ }
+}
+
+
+TEST(RunFloat64SubImm1) {
+ FOR_FLOAT64_INPUTS(i) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+ m.Return(m.Float64Sub(m.Float64Constant(*i), m.Parameter(0)));
+
+ FOR_FLOAT64_INPUTS(j) { CheckFloatEq(*i - *j, m.Call(*j)); }
+ }
+}
+
+
+TEST(RunFloat64SubImm2) {
+ FOR_FLOAT64_INPUTS(i) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+ m.Return(m.Float64Sub(m.Parameter(0), m.Float64Constant(*i)));
+
+ FOR_FLOAT64_INPUTS(j) { CheckFloatEq(*j - *i, m.Call(*j)); }
+ }
+}
+
+
TEST(RunFloat64SubP) {
RawMachineAssemblerTester<int32_t> m;
Float64BinopTester bt(&m);
@@ -2979,47 +3934,22 @@
FOR_FLOAT64_INPUTS(pl) {
FOR_FLOAT64_INPUTS(pr) {
double expected = *pl - *pr;
- CHECK_EQ(expected, bt.call(*pl, *pr));
+ CheckDoubleEq(expected, bt.call(*pl, *pr));
}
}
}
-TEST(RunFloat64SubImm1) {
- double input = 0.0;
- double output = 0.0;
+TEST(RunFloat32MulP) {
+ RawMachineAssemblerTester<int32_t> m;
+ Float32BinopTester bt(&m);
- FOR_FLOAT64_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m;
- Node* t0 = m.LoadFromPointer(&input, kMachFloat64);
- Node* t1 = m.Float64Sub(m.Float64Constant(*i), t0);
- m.StoreToPointer(&output, kMachFloat64, t1);
- m.Return(m.Int32Constant(0));
- FOR_FLOAT64_INPUTS(j) {
- input = *j;
- double expected = *i - input;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, output);
- }
- }
-}
+ bt.AddReturn(m.Float32Mul(bt.param0, bt.param1));
-
-TEST(RunFloat64SubImm2) {
- double input = 0.0;
- double output = 0.0;
-
- FOR_FLOAT64_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m;
- Node* t0 = m.LoadFromPointer(&input, kMachFloat64);
- Node* t1 = m.Float64Sub(t0, m.Float64Constant(*i));
- m.StoreToPointer(&output, kMachFloat64, t1);
- m.Return(m.Int32Constant(0));
- FOR_FLOAT64_INPUTS(j) {
- input = *j;
- double expected = input - *i;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, output);
+ FOR_FLOAT32_INPUTS(pl) {
+ FOR_FLOAT32_INPUTS(pr) {
+ float expected = *pl * *pr;
+ CheckFloatEq(expected, bt.call(*pl, *pr));
}
}
}
@@ -3034,131 +3964,111 @@
FOR_FLOAT64_INPUTS(pl) {
FOR_FLOAT64_INPUTS(pr) {
double expected = *pl * *pr;
- CHECK_EQ(expected, bt.call(*pl, *pr));
+ CheckDoubleEq(expected, bt.call(*pl, *pr));
}
}
}
-TEST(RunFloat64MulAndFloat64AddP) {
- double input_a = 0.0;
- double input_b = 0.0;
- double input_c = 0.0;
- double output = 0.0;
-
- {
- RawMachineAssemblerTester<int32_t> m;
- Node* a = m.LoadFromPointer(&input_a, kMachFloat64);
- Node* b = m.LoadFromPointer(&input_b, kMachFloat64);
- Node* c = m.LoadFromPointer(&input_c, kMachFloat64);
- m.StoreToPointer(&output, kMachFloat64,
- m.Float64Add(m.Float64Mul(a, b), c));
- m.Return(m.Int32Constant(0));
- FOR_FLOAT64_INPUTS(i) {
- FOR_FLOAT64_INPUTS(j) {
- FOR_FLOAT64_INPUTS(k) {
- input_a = *i;
- input_b = *j;
- input_c = *k;
- volatile double temp = input_a * input_b;
- volatile double expected = temp + input_c;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, output);
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Node* a = m.LoadFromPointer(&input_a, kMachFloat64);
- Node* b = m.LoadFromPointer(&input_b, kMachFloat64);
- Node* c = m.LoadFromPointer(&input_c, kMachFloat64);
- m.StoreToPointer(&output, kMachFloat64,
- m.Float64Add(a, m.Float64Mul(b, c)));
- m.Return(m.Int32Constant(0));
- FOR_FLOAT64_INPUTS(i) {
- FOR_FLOAT64_INPUTS(j) {
- FOR_FLOAT64_INPUTS(k) {
- input_a = *i;
- input_b = *j;
- input_c = *k;
- volatile double temp = input_b * input_c;
- volatile double expected = input_a + temp;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, output);
- }
- }
- }
- }
-}
-
-
-TEST(RunFloat64MulAndFloat64SubP) {
- double input_a = 0.0;
- double input_b = 0.0;
- double input_c = 0.0;
- double output = 0.0;
-
- RawMachineAssemblerTester<int32_t> m;
- Node* a = m.LoadFromPointer(&input_a, kMachFloat64);
- Node* b = m.LoadFromPointer(&input_b, kMachFloat64);
- Node* c = m.LoadFromPointer(&input_c, kMachFloat64);
- m.StoreToPointer(&output, kMachFloat64, m.Float64Sub(a, m.Float64Mul(b, c)));
- m.Return(m.Int32Constant(0));
+TEST(RunFloat64MulAndFloat64Add1) {
+ BufferedRawMachineAssemblerTester<double> m(
+ MachineType::Float64(), MachineType::Float64(), MachineType::Float64());
+ m.Return(m.Float64Add(m.Float64Mul(m.Parameter(0), m.Parameter(1)),
+ m.Parameter(2)));
FOR_FLOAT64_INPUTS(i) {
FOR_FLOAT64_INPUTS(j) {
FOR_FLOAT64_INPUTS(k) {
- input_a = *i;
- input_b = *j;
- input_c = *k;
- volatile double temp = input_b * input_c;
- volatile double expected = input_a - temp;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, output);
+ CheckDoubleEq((*i * *j) + *k, m.Call(*i, *j, *k));
}
}
}
}
-TEST(RunFloat64MulImm) {
- double input = 0.0;
- double output = 0.0;
+TEST(RunFloat64MulAndFloat64Add2) {
+ BufferedRawMachineAssemblerTester<double> m(
+ MachineType::Float64(), MachineType::Float64(), MachineType::Float64());
+ m.Return(m.Float64Add(m.Parameter(0),
+ m.Float64Mul(m.Parameter(1), m.Parameter(2))));
- {
- FOR_FLOAT64_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m;
- Node* t0 = m.LoadFromPointer(&input, kMachFloat64);
- Node* t1 = m.Float64Mul(m.Float64Constant(*i), t0);
- m.StoreToPointer(&output, kMachFloat64, t1);
- m.Return(m.Int32Constant(0));
- FOR_FLOAT64_INPUTS(j) {
- input = *j;
- double expected = *i * input;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, output);
+ FOR_FLOAT64_INPUTS(i) {
+ FOR_FLOAT64_INPUTS(j) {
+ FOR_FLOAT64_INPUTS(k) {
+ CheckDoubleEq(*i + (*j * *k), m.Call(*i, *j, *k));
}
}
}
- {
- FOR_FLOAT64_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m;
- Node* t0 = m.LoadFromPointer(&input, kMachFloat64);
- Node* t1 = m.Float64Mul(t0, m.Float64Constant(*i));
- m.StoreToPointer(&output, kMachFloat64, t1);
- m.Return(m.Int32Constant(0));
- FOR_FLOAT64_INPUTS(j) {
- input = *j;
- double expected = input * *i;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, output);
+}
+
+
+TEST(RunFloat64MulAndFloat64Sub1) {
+ BufferedRawMachineAssemblerTester<double> m(
+ MachineType::Float64(), MachineType::Float64(), MachineType::Float64());
+ m.Return(m.Float64Sub(m.Float64Mul(m.Parameter(0), m.Parameter(1)),
+ m.Parameter(2)));
+
+ FOR_FLOAT64_INPUTS(i) {
+ FOR_FLOAT64_INPUTS(j) {
+ FOR_FLOAT64_INPUTS(k) {
+ CheckDoubleEq((*i * *j) - *k, m.Call(*i, *j, *k));
}
}
}
}
+TEST(RunFloat64MulAndFloat64Sub2) {
+ BufferedRawMachineAssemblerTester<double> m(
+ MachineType::Float64(), MachineType::Float64(), MachineType::Float64());
+ m.Return(m.Float64Sub(m.Parameter(0),
+ m.Float64Mul(m.Parameter(1), m.Parameter(2))));
+
+ FOR_FLOAT64_INPUTS(i) {
+ FOR_FLOAT64_INPUTS(j) {
+ FOR_FLOAT64_INPUTS(k) {
+ CheckDoubleEq(*i - (*j * *k), m.Call(*i, *j, *k));
+ }
+ }
+ }
+}
+
+
+TEST(RunFloat64MulImm1) {
+ FOR_FLOAT64_INPUTS(i) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+ m.Return(m.Float64Mul(m.Float64Constant(*i), m.Parameter(0)));
+
+ FOR_FLOAT64_INPUTS(j) { CheckFloatEq(*i * *j, m.Call(*j)); }
+ }
+}
+
+
+TEST(RunFloat64MulImm2) {
+ FOR_FLOAT64_INPUTS(i) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+ m.Return(m.Float64Mul(m.Parameter(0), m.Float64Constant(*i)));
+
+ FOR_FLOAT64_INPUTS(j) { CheckFloatEq(*j * *i, m.Call(*j)); }
+ }
+}
+
+
+TEST(RunFloat32DivP) {
+ RawMachineAssemblerTester<int32_t> m;
+ Float32BinopTester bt(&m);
+
+ bt.AddReturn(m.Float32Div(bt.param0, bt.param1));
+
+ FOR_FLOAT32_INPUTS(pl) {
+ FOR_FLOAT32_INPUTS(pr) {
+ float expected = *pl / *pr;
+ CheckFloatEq(expected, bt.call(*pl, *pr));
+ }
+ }
+}
+
+
TEST(RunFloat64DivP) {
RawMachineAssemblerTester<int32_t> m;
Float64BinopTester bt(&m);
@@ -3168,7 +4078,7 @@
FOR_FLOAT64_INPUTS(pl) {
FOR_FLOAT64_INPUTS(pr) {
double expected = *pl / *pr;
- CHECK_EQ(expected, bt.call(*pl, *pr));
+ CheckDoubleEq(expected, bt.call(*pl, *pr));
}
}
}
@@ -3184,292 +4094,87 @@
FOR_FLOAT64_INPUTS(j) {
double expected = modulo(*i, *j);
double found = bt.call(*i, *j);
- CHECK_EQ(expected, found);
+ CheckDoubleEq(expected, found);
}
}
}
TEST(RunChangeInt32ToFloat64_A) {
- RawMachineAssemblerTester<int32_t> m;
int32_t magic = 0x986234;
- double result = 0;
-
- Node* convert = m.ChangeInt32ToFloat64(m.Int32Constant(magic));
- m.Store(kMachFloat64, m.PointerConstant(&result), m.Int32Constant(0),
- convert);
- m.Return(m.Int32Constant(magic));
-
- CHECK_EQ(magic, m.Call());
- CHECK_EQ(static_cast<double>(magic), result);
+ BufferedRawMachineAssemblerTester<double> m;
+ m.Return(m.ChangeInt32ToFloat64(m.Int32Constant(magic)));
+ CheckDoubleEq(static_cast<double>(magic), m.Call());
}
TEST(RunChangeInt32ToFloat64_B) {
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
- double output = 0;
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Int32());
+ m.Return(m.ChangeInt32ToFloat64(m.Parameter(0)));
- Node* convert = m.ChangeInt32ToFloat64(m.Parameter(0));
- m.Store(kMachFloat64, m.PointerConstant(&output), m.Int32Constant(0),
- convert);
- m.Return(m.Parameter(0));
-
- FOR_INT32_INPUTS(i) {
- int32_t expect = *i;
- CHECK_EQ(expect, m.Call(expect));
- CHECK_EQ(static_cast<double>(expect), output);
- }
+ FOR_INT32_INPUTS(i) { CheckDoubleEq(static_cast<double>(*i), m.Call(*i)); }
}
-TEST(RunChangeUint32ToFloat64_B) {
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
- double output = 0;
+TEST(RunChangeUint32ToFloat64) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Uint32());
+ m.Return(m.ChangeUint32ToFloat64(m.Parameter(0)));
- Node* convert = m.ChangeUint32ToFloat64(m.Parameter(0));
- m.Store(kMachFloat64, m.PointerConstant(&output), m.Int32Constant(0),
- convert);
- m.Return(m.Parameter(0));
-
- FOR_UINT32_INPUTS(i) {
- uint32_t expect = *i;
- CHECK_EQ(expect, m.Call(expect));
- CHECK_EQ(static_cast<double>(expect), output);
- }
-}
-
-
-TEST(RunChangeUint32ToFloat64_spilled) {
- RawMachineAssemblerTester<int32_t> m;
- const int kNumInputs = 32;
- int32_t magic = 0x786234;
- uint32_t input[kNumInputs];
- double result[kNumInputs];
- Node* input_node[kNumInputs];
-
- for (int i = 0; i < kNumInputs; i++) {
- input_node[i] =
- m.Load(kMachUint32, m.PointerConstant(&input), m.Int32Constant(i * 4));
- }
-
- for (int i = 0; i < kNumInputs; i++) {
- m.Store(kMachFloat64, m.PointerConstant(&result), m.Int32Constant(i * 8),
- m.ChangeUint32ToFloat64(input_node[i]));
- }
-
- m.Return(m.Int32Constant(magic));
-
- for (int i = 0; i < kNumInputs; i++) {
- input[i] = 100 + i;
- }
-
- CHECK_EQ(magic, m.Call());
-
- for (int i = 0; i < kNumInputs; i++) {
- CHECK_EQ(result[i], static_cast<double>(100 + i));
- }
+ FOR_UINT32_INPUTS(i) { CheckDoubleEq(static_cast<double>(*i), m.Call(*i)); }
}
TEST(RunChangeFloat64ToInt32_A) {
- RawMachineAssemblerTester<int32_t> m;
- int32_t magic = 0x786234;
- double input = 11.1;
- int32_t result = 0;
-
- m.Store(kMachInt32, m.PointerConstant(&result), m.Int32Constant(0),
- m.ChangeFloat64ToInt32(m.Float64Constant(input)));
- m.Return(m.Int32Constant(magic));
-
- CHECK_EQ(magic, m.Call());
- CHECK_EQ(static_cast<int32_t>(input), result);
+ BufferedRawMachineAssemblerTester<int32_t> m;
+ double magic = 11.1;
+ m.Return(m.ChangeFloat64ToInt32(m.Float64Constant(magic)));
+ CHECK_EQ(static_cast<int32_t>(magic), m.Call());
}
TEST(RunChangeFloat64ToInt32_B) {
- RawMachineAssemblerTester<int32_t> m;
- double input = 0;
- int32_t output = 0;
+ BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Float64());
+ m.Return(m.ChangeFloat64ToInt32(m.Parameter(0)));
- Node* load =
- m.Load(kMachFloat64, m.PointerConstant(&input), m.Int32Constant(0));
- Node* convert = m.ChangeFloat64ToInt32(load);
- m.Store(kMachInt32, m.PointerConstant(&output), m.Int32Constant(0), convert);
- m.Return(convert);
+ // Note we don't check fractional inputs, or inputs outside the range of
+ // int32, because these Convert operators really should be Change operators.
+ FOR_INT32_INPUTS(i) { CHECK_EQ(*i, m.Call(static_cast<double>(*i))); }
+
+ for (int32_t n = 1; n < 31; ++n) {
+ CHECK_EQ(1 << n, m.Call(static_cast<double>(1 << n)));
+ }
+
+ for (int32_t n = 1; n < 31; ++n) {
+ CHECK_EQ(3 << n, m.Call(static_cast<double>(3 << n)));
+ }
+}
+
+
+TEST(RunChangeFloat64ToUint32) {
+ BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Float64());
+ m.Return(m.ChangeFloat64ToUint32(m.Parameter(0)));
{
- FOR_INT32_INPUTS(i) {
- input = *i;
- int32_t expect = *i;
- CHECK_EQ(expect, m.Call());
- CHECK_EQ(expect, output);
- }
+ FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, m.Call(static_cast<double>(*i))); }
}
// Check various powers of 2.
for (int32_t n = 1; n < 31; ++n) {
- {
- input = 1 << n;
- int32_t expect = static_cast<int32_t>(input);
- CHECK_EQ(expect, m.Call());
- CHECK_EQ(expect, output);
- }
+ { CHECK_EQ(1u << n, m.Call(static_cast<double>(1u << n))); }
- {
- input = 3 << n;
- int32_t expect = static_cast<int32_t>(input);
- CHECK_EQ(expect, m.Call());
- CHECK_EQ(expect, output);
- }
+ { CHECK_EQ(3u << n, m.Call(static_cast<double>(3u << n))); }
}
// Note we don't check fractional inputs, because these Convert operators
// really should be Change operators.
}
-TEST(RunChangeFloat64ToUint32_B) {
- RawMachineAssemblerTester<int32_t> m;
- double input = 0;
- int32_t output = 0;
+TEST(RunTruncateFloat64ToFloat32) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Float64());
- Node* load =
- m.Load(kMachFloat64, m.PointerConstant(&input), m.Int32Constant(0));
- Node* convert = m.ChangeFloat64ToUint32(load);
- m.Store(kMachInt32, m.PointerConstant(&output), m.Int32Constant(0), convert);
- m.Return(convert);
+ m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0)));
- {
- FOR_UINT32_INPUTS(i) {
- input = *i;
- // TODO(titzer): add a CheckEqualsHelper overload for uint32_t.
- int32_t expect = static_cast<int32_t>(*i);
- CHECK_EQ(expect, m.Call());
- CHECK_EQ(expect, output);
- }
- }
-
- // Check various powers of 2.
- for (int32_t n = 1; n < 31; ++n) {
- {
- input = 1u << n;
- int32_t expect = static_cast<int32_t>(static_cast<uint32_t>(input));
- CHECK_EQ(expect, m.Call());
- CHECK_EQ(expect, output);
- }
-
- {
- input = 3u << n;
- int32_t expect = static_cast<int32_t>(static_cast<uint32_t>(input));
- CHECK_EQ(expect, m.Call());
- CHECK_EQ(expect, output);
- }
- }
- // Note we don't check fractional inputs, because these Convert operators
- // really should be Change operators.
-}
-
-
-TEST(RunChangeFloat64ToInt32_spilled) {
- RawMachineAssemblerTester<int32_t> m;
- const int kNumInputs = 32;
- int32_t magic = 0x786234;
- double input[kNumInputs];
- int32_t result[kNumInputs];
- Node* input_node[kNumInputs];
-
- for (int i = 0; i < kNumInputs; i++) {
- input_node[i] =
- m.Load(kMachFloat64, m.PointerConstant(&input), m.Int32Constant(i * 8));
- }
-
- for (int i = 0; i < kNumInputs; i++) {
- m.Store(kMachInt32, m.PointerConstant(&result), m.Int32Constant(i * 4),
- m.ChangeFloat64ToInt32(input_node[i]));
- }
-
- m.Return(m.Int32Constant(magic));
-
- for (int i = 0; i < kNumInputs; i++) {
- input[i] = 100.9 + i;
- }
-
- CHECK_EQ(magic, m.Call());
-
- for (int i = 0; i < kNumInputs; i++) {
- CHECK_EQ(result[i], 100 + i);
- }
-}
-
-
-TEST(RunChangeFloat64ToUint32_spilled) {
- RawMachineAssemblerTester<uint32_t> m;
- const int kNumInputs = 32;
- int32_t magic = 0x786234;
- double input[kNumInputs];
- uint32_t result[kNumInputs];
- Node* input_node[kNumInputs];
-
- for (int i = 0; i < kNumInputs; i++) {
- input_node[i] =
- m.Load(kMachFloat64, m.PointerConstant(&input), m.Int32Constant(i * 8));
- }
-
- for (int i = 0; i < kNumInputs; i++) {
- m.Store(kMachUint32, m.PointerConstant(&result), m.Int32Constant(i * 4),
- m.ChangeFloat64ToUint32(input_node[i]));
- }
-
- m.Return(m.Int32Constant(magic));
-
- for (int i = 0; i < kNumInputs; i++) {
- if (i % 2) {
- input[i] = 100 + i + 2147483648u;
- } else {
- input[i] = 100 + i;
- }
- }
-
- CHECK_EQ(magic, m.Call());
-
- for (int i = 0; i < kNumInputs; i++) {
- if (i % 2) {
- CHECK_UINT32_EQ(result[i], static_cast<uint32_t>(100 + i + 2147483648u));
- } else {
- CHECK_UINT32_EQ(result[i], static_cast<uint32_t>(100 + i));
- }
- }
-}
-
-
-TEST(RunTruncateFloat64ToFloat32_spilled) {
- RawMachineAssemblerTester<uint32_t> m;
- const int kNumInputs = 32;
- int32_t magic = 0x786234;
- double input[kNumInputs];
- float result[kNumInputs];
- Node* input_node[kNumInputs];
-
- for (int i = 0; i < kNumInputs; i++) {
- input_node[i] =
- m.Load(kMachFloat64, m.PointerConstant(&input), m.Int32Constant(i * 8));
- }
-
- for (int i = 0; i < kNumInputs; i++) {
- m.Store(kMachFloat32, m.PointerConstant(&result), m.Int32Constant(i * 4),
- m.TruncateFloat64ToFloat32(input_node[i]));
- }
-
- m.Return(m.Int32Constant(magic));
-
- for (int i = 0; i < kNumInputs; i++) {
- input[i] = 0.1 + i;
- }
-
- CHECK_EQ(magic, m.Call());
-
- for (int i = 0; i < kNumInputs; i++) {
- CHECK_EQ(result[i], DoubleToFloat32(input[i]));
- }
+ FOR_FLOAT64_INPUTS(i) { CheckFloatEq(DoubleToFloat32(*i), m.Call(*i)); }
}
@@ -3497,11 +4202,11 @@
int false_val = 0x10777;
// x = false_val; while(false) { x++; } return x;
- MLabel header, body, end;
+ RawMachineLabel header, body, end;
Node* false_node = m.Int32Constant(false_val);
m.Goto(&header);
m.Bind(&header);
- Node* phi = m.Phi(kMachInt32, false_node, false_node);
+ Node* phi = m.Phi(MachineRepresentation::kWord32, false_node, false_node);
m.Branch(m.Int32Constant(0), &body, &end);
m.Bind(&body);
Node* add = m.Int32Add(phi, m.Int32Constant(1));
@@ -3514,6 +4219,32 @@
}
+TEST(RunFloatDiamond) {
+ RawMachineAssemblerTester<int32_t> m;
+
+ const int magic = 99645;
+ float buffer = 0.1f;
+ float constant = 99.99f;
+
+ RawMachineLabel blocka, blockb, end;
+ Node* k1 = m.Float32Constant(constant);
+ Node* k2 = m.Float32Constant(0 - constant);
+ m.Branch(m.Int32Constant(0), &blocka, &blockb);
+ m.Bind(&blocka);
+ m.Goto(&end);
+ m.Bind(&blockb);
+ m.Goto(&end);
+ m.Bind(&end);
+ Node* phi = m.Phi(MachineRepresentation::kFloat32, k2, k1);
+ m.Store(MachineRepresentation::kFloat32, m.PointerConstant(&buffer),
+ m.IntPtrConstant(0), phi, kNoWriteBarrier);
+ m.Return(m.Int32Constant(magic));
+
+ CHECK_EQ(magic, m.Call());
+ CHECK(constant == buffer);
+}
+
+
TEST(RunDoubleDiamond) {
RawMachineAssemblerTester<int32_t> m;
@@ -3521,7 +4252,7 @@
double buffer = 0.1;
double constant = 99.99;
- MLabel blocka, blockb, end;
+ RawMachineLabel blocka, blockb, end;
Node* k1 = m.Float64Constant(constant);
Node* k2 = m.Float64Constant(0 - constant);
m.Branch(m.Int32Constant(0), &blocka, &blockb);
@@ -3530,8 +4261,9 @@
m.Bind(&blockb);
m.Goto(&end);
m.Bind(&end);
- Node* phi = m.Phi(kMachFloat64, k2, k1);
- m.Store(kMachFloat64, m.PointerConstant(&buffer), m.Int32Constant(0), phi);
+ Node* phi = m.Phi(MachineRepresentation::kFloat64, k2, k1);
+ m.Store(MachineRepresentation::kFloat64, m.PointerConstant(&buffer),
+ m.Int32Constant(0), phi, kNoWriteBarrier);
m.Return(m.Int32Constant(magic));
CHECK_EQ(magic, m.Call());
@@ -3547,7 +4279,7 @@
CcTest::i_isolate()->factory()->InternalizeUtf8String("A");
String* buffer;
- MLabel blocka, blockb, end;
+ RawMachineLabel blocka, blockb, end;
Node* k1 = m.StringConstant("A");
Node* k2 = m.StringConstant("B");
m.Branch(m.Int32Constant(0), &blocka, &blockb);
@@ -3556,8 +4288,9 @@
m.Bind(&blockb);
m.Goto(&end);
m.Bind(&end);
- Node* phi = m.Phi(kMachAnyTagged, k2, k1);
- m.Store(kMachAnyTagged, m.PointerConstant(&buffer), m.Int32Constant(0), phi);
+ Node* phi = m.Phi(MachineRepresentation::kTagged, k2, k1);
+ m.Store(MachineRepresentation::kTagged, m.PointerConstant(&buffer),
+ m.Int32Constant(0), phi, kNoWriteBarrier);
m.Return(m.Int32Constant(magic));
CHECK_EQ(magic, m.Call());
@@ -3575,7 +4308,7 @@
CcTest::i_isolate()->factory()->InternalizeUtf8String("AX");
String* rbuffer;
- MLabel blocka, blockb, end;
+ RawMachineLabel blocka, blockb, end;
Node* d1 = m.Float64Constant(dconstant);
Node* d2 = m.Float64Constant(0 - dconstant);
Node* r1 = m.StringConstant("AX");
@@ -3586,11 +4319,12 @@
m.Bind(&blockb);
m.Goto(&end);
m.Bind(&end);
- Node* dphi = m.Phi(kMachFloat64, d2, d1);
- Node* rphi = m.Phi(kMachAnyTagged, r2, r1);
- m.Store(kMachFloat64, m.PointerConstant(&dbuffer), m.Int32Constant(0), dphi);
- m.Store(kMachAnyTagged, m.PointerConstant(&rbuffer), m.Int32Constant(0),
- rphi);
+ Node* dphi = m.Phi(MachineRepresentation::kFloat64, d2, d1);
+ Node* rphi = m.Phi(MachineRepresentation::kTagged, r2, r1);
+ m.Store(MachineRepresentation::kFloat64, m.PointerConstant(&dbuffer),
+ m.Int32Constant(0), dphi, kNoWriteBarrier);
+ m.Store(MachineRepresentation::kTagged, m.PointerConstant(&rbuffer),
+ m.Int32Constant(0), rphi, kNoWriteBarrier);
m.Return(m.Int32Constant(magic));
CHECK_EQ(magic, m.Call());
@@ -3609,7 +4343,7 @@
CcTest::i_isolate()->factory()->InternalizeUtf8String("AD");
String* rbuffer;
- MLabel blocka, blockb, mid, blockd, blocke, end;
+ RawMachineLabel blocka, blockb, mid, blockd, blocke, end;
Node* d1 = m.Float64Constant(dconstant);
Node* d2 = m.Float64Constant(0 - dconstant);
Node* r1 = m.StringConstant("AD");
@@ -3620,8 +4354,8 @@
m.Bind(&blockb);
m.Goto(&mid);
m.Bind(&mid);
- Node* dphi1 = m.Phi(kMachFloat64, d2, d1);
- Node* rphi1 = m.Phi(kMachAnyTagged, r2, r1);
+ Node* dphi1 = m.Phi(MachineRepresentation::kFloat64, d2, d1);
+ Node* rphi1 = m.Phi(MachineRepresentation::kTagged, r2, r1);
m.Branch(m.Int32Constant(0), &blockd, &blocke);
m.Bind(&blockd);
@@ -3629,12 +4363,13 @@
m.Bind(&blocke);
m.Goto(&end);
m.Bind(&end);
- Node* dphi2 = m.Phi(kMachFloat64, d1, dphi1);
- Node* rphi2 = m.Phi(kMachAnyTagged, r1, rphi1);
+ Node* dphi2 = m.Phi(MachineRepresentation::kFloat64, d1, dphi1);
+ Node* rphi2 = m.Phi(MachineRepresentation::kTagged, r1, rphi1);
- m.Store(kMachFloat64, m.PointerConstant(&dbuffer), m.Int32Constant(0), dphi2);
- m.Store(kMachAnyTagged, m.PointerConstant(&rbuffer), m.Int32Constant(0),
- rphi2);
+ m.Store(MachineRepresentation::kFloat64, m.PointerConstant(&dbuffer),
+ m.Int32Constant(0), dphi2, kNoWriteBarrier);
+ m.Store(MachineRepresentation::kTagged, m.PointerConstant(&rbuffer),
+ m.Int32Constant(0), rphi2, kNoWriteBarrier);
m.Return(m.Int32Constant(magic));
CHECK_EQ(magic, m.Call());
@@ -3645,7 +4380,7 @@
TEST(RunDoubleLoopPhi) {
RawMachineAssemblerTester<int32_t> m;
- MLabel header, body, end;
+ RawMachineLabel header, body, end;
int magic = 99773;
double buffer = 0.99;
@@ -3656,13 +4391,14 @@
m.Goto(&header);
m.Bind(&header);
- Node* phi = m.Phi(kMachFloat64, dk, dk);
+ Node* phi = m.Phi(MachineRepresentation::kFloat64, dk, dk);
phi->ReplaceInput(1, phi);
m.Branch(zero, &body, &end);
m.Bind(&body);
m.Goto(&header);
m.Bind(&end);
- m.Store(kMachFloat64, m.PointerConstant(&buffer), m.Int32Constant(0), phi);
+ m.Store(MachineRepresentation::kFloat64, m.PointerConstant(&buffer),
+ m.Int32Constant(0), phi, kNoWriteBarrier);
m.Return(m.Int32Constant(magic));
CHECK_EQ(magic, m.Call());
@@ -3676,13 +4412,13 @@
Node* ten = m.Int32Constant(10);
Node* one = m.Int32Constant(1);
- MLabel header, body, body_cont, end;
+ RawMachineLabel header, body, body_cont, end;
m.Goto(&header);
m.Bind(&header);
- Node* i = m.Phi(kMachInt32, zero, zero);
- Node* j = m.Phi(kMachInt32, zero, zero);
+ Node* i = m.Phi(MachineRepresentation::kWord32, zero, zero);
+ Node* j = m.Phi(MachineRepresentation::kWord32, zero, zero);
m.Goto(&body);
m.Bind(&body);
@@ -3709,14 +4445,14 @@
Node* ten = m.Int32Constant(10);
Node* one = m.Int32Constant(1);
- MLabel header, body, body_cont, end;
+ RawMachineLabel header, body, body_cont, end;
m.Goto(&header);
m.Bind(&header);
- Node* i = m.Phi(kMachInt32, zero, zero);
- Node* j = m.Phi(kMachInt32, zero, zero);
- Node* k = m.Phi(kMachInt32, zero, zero);
+ Node* i = m.Phi(MachineRepresentation::kWord32, zero, zero);
+ Node* j = m.Phi(MachineRepresentation::kWord32, zero, zero);
+ Node* k = m.Phi(MachineRepresentation::kWord32, zero, zero);
m.Goto(&body);
m.Bind(&body);
@@ -3743,14 +4479,22 @@
int32_t inputs[] = {11, 12, 13, 14, 15, 16, 17, 18};
Node* base = m.PointerConstant(inputs);
- Node* n0 = m.Load(kMachInt32, base, m.Int32Constant(0 * sizeof(int32_t)));
- Node* n1 = m.Load(kMachInt32, base, m.Int32Constant(1 * sizeof(int32_t)));
- Node* n2 = m.Load(kMachInt32, base, m.Int32Constant(2 * sizeof(int32_t)));
- Node* n3 = m.Load(kMachInt32, base, m.Int32Constant(3 * sizeof(int32_t)));
- Node* n4 = m.Load(kMachInt32, base, m.Int32Constant(4 * sizeof(int32_t)));
- Node* n5 = m.Load(kMachInt32, base, m.Int32Constant(5 * sizeof(int32_t)));
- Node* n6 = m.Load(kMachInt32, base, m.Int32Constant(6 * sizeof(int32_t)));
- Node* n7 = m.Load(kMachInt32, base, m.Int32Constant(7 * sizeof(int32_t)));
+ Node* n0 =
+ m.Load(MachineType::Int32(), base, m.Int32Constant(0 * sizeof(int32_t)));
+ Node* n1 =
+ m.Load(MachineType::Int32(), base, m.Int32Constant(1 * sizeof(int32_t)));
+ Node* n2 =
+ m.Load(MachineType::Int32(), base, m.Int32Constant(2 * sizeof(int32_t)));
+ Node* n3 =
+ m.Load(MachineType::Int32(), base, m.Int32Constant(3 * sizeof(int32_t)));
+ Node* n4 =
+ m.Load(MachineType::Int32(), base, m.Int32Constant(4 * sizeof(int32_t)));
+ Node* n5 =
+ m.Load(MachineType::Int32(), base, m.Int32Constant(5 * sizeof(int32_t)));
+ Node* n6 =
+ m.Load(MachineType::Int32(), base, m.Int32Constant(6 * sizeof(int32_t)));
+ Node* n7 =
+ m.Load(MachineType::Int32(), base, m.Int32Constant(7 * sizeof(int32_t)));
Node* i1 = m.Int32Add(n0, n1);
Node* i2 = m.Int32Add(n2, n3);
@@ -3782,10 +4526,12 @@
CHECK(x < y);
bool load_a = node_type / 2 == 1;
bool load_b = node_type % 2 == 1;
- Node* a = load_a ? m->Load(kMachFloat64, m->PointerConstant(&buffer[0]))
- : m->Float64Constant(x);
- Node* b = load_b ? m->Load(kMachFloat64, m->PointerConstant(&buffer[1]))
- : m->Float64Constant(y);
+ Node* a =
+ load_a ? m->Load(MachineType::Float64(), m->PointerConstant(&buffer[0]))
+ : m->Float64Constant(x);
+ Node* b =
+ load_b ? m->Load(MachineType::Float64(), m->PointerConstant(&buffer[1]))
+ : m->Float64Constant(y);
Node* cmp = NULL;
bool expected = false;
switch (test_case) {
@@ -3890,7 +4636,7 @@
m.machine()->Float64LessThan(),
m.machine()->Float64LessThanOrEqual()};
- double nan = v8::base::OS::nan_value();
+ double nan = std::numeric_limits<double>::quiet_NaN();
FOR_FLOAT64_INPUTS(i) {
for (size_t o = 0; o < arraysize(operators); ++o) {
@@ -3899,7 +4645,7 @@
Node* a = m.Float64Constant(*i);
Node* b = m.Float64Constant(nan);
if (j == 1) std::swap(a, b);
- m.Return(m.NewNode(operators[o], a, b));
+ m.Return(m.AddNode(operators[o], a, b));
CHECK_EQ(0, m.Call());
}
}
@@ -3912,8 +4658,8 @@
double input_b = 0.0;
RawMachineAssemblerTester<int32_t> m;
- Node* a = m.LoadFromPointer(&input_a, kMachFloat64);
- Node* b = m.LoadFromPointer(&input_b, kMachFloat64);
+ Node* a = m.LoadFromPointer(&input_a, MachineType::Float64());
+ Node* b = m.LoadFromPointer(&input_b, MachineType::Float64());
m.Return(m.Float64Equal(a, b));
CompareWrapper cmp(IrOpcode::kFloat64Equal);
@@ -3933,8 +4679,8 @@
double input_b = 0.0;
RawMachineAssemblerTester<int32_t> m;
- Node* a = m.LoadFromPointer(&input_a, kMachFloat64);
- Node* b = m.LoadFromPointer(&input_b, kMachFloat64);
+ Node* a = m.LoadFromPointer(&input_a, MachineType::Float64());
+ Node* b = m.LoadFromPointer(&input_b, MachineType::Float64());
m.Return(m.Float64LessThan(a, b));
CompareWrapper cmp(IrOpcode::kFloat64LessThan);
@@ -3949,14 +4695,14 @@
}
-template <typename IntType, MachineType kRepresentation>
-static void LoadStoreTruncation() {
+template <typename IntType>
+static void LoadStoreTruncation(MachineType kRepresentation) {
IntType input;
RawMachineAssemblerTester<int32_t> m;
Node* a = m.LoadFromPointer(&input, kRepresentation);
Node* ap1 = m.Int32Add(a, m.Int32Constant(1));
- m.StoreToPointer(&input, kRepresentation, ap1);
+ m.StoreToPointer(&input, kRepresentation.representation(), ap1);
m.Return(ap1);
const IntType max = std::numeric_limits<IntType>::max();
@@ -3983,14 +4729,15 @@
TEST(RunLoadStoreTruncation) {
- LoadStoreTruncation<int8_t, kMachInt8>();
- LoadStoreTruncation<int16_t, kMachInt16>();
+ LoadStoreTruncation<int8_t>(MachineType::Int8());
+ LoadStoreTruncation<int16_t>(MachineType::Int16());
}
static void IntPtrCompare(intptr_t left, intptr_t right) {
for (int test = 0; test < 7; test++) {
- RawMachineAssemblerTester<bool> m(kMachPtr, kMachPtr);
+ RawMachineAssemblerTester<bool> m(MachineType::Pointer(),
+ MachineType::Pointer());
Node* p0 = m.Parameter(0);
Node* p1 = m.Parameter(1);
Node* res = NULL;
@@ -4057,9 +4804,10 @@
RawMachineAssemblerTester<int32_t*> m;
Node* input = m.PointerConstant(&inputs[0]);
Node* output = m.PointerConstant(&outputs[kInputSize - 1]);
- Node* elem_size = m.ConvertInt32ToIntPtr(m.Int32Constant(sizeof(inputs[0])));
+ Node* elem_size = m.IntPtrConstant(sizeof(inputs[0]));
for (int i = 0; i < kInputSize; i++) {
- m.Store(kMachInt32, output, m.Load(kMachInt32, input));
+ m.Store(MachineRepresentation::kWord32, output,
+ m.Load(MachineType::Int32(), input), kNoWriteBarrier);
input = m.IntPtrAdd(input, elem_size);
output = m.IntPtrSub(output, elem_size);
}
@@ -4074,7 +4822,7 @@
TEST(RunSpillLotsOfThings) {
static const int kInputSize = 1000;
- RawMachineAssemblerTester<void> m;
+ RawMachineAssemblerTester<int32_t> m;
Node* accs[kInputSize];
int32_t outputs[kInputSize];
Node* one = m.Int32Constant(1);
@@ -4084,7 +4832,7 @@
accs[i] = acc;
}
for (int i = 0; i < kInputSize; i++) {
- m.StoreToPointer(&outputs[i], kMachInt32, accs[i]);
+ m.StoreToPointer(&outputs[i], MachineRepresentation::kWord32, accs[i]);
}
m.Return(one);
m.Call();
@@ -4097,7 +4845,8 @@
TEST(RunSpillConstantsAndParameters) {
static const int kInputSize = 1000;
static const int32_t kBase = 987;
- RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+ MachineType::Int32());
int32_t outputs[kInputSize];
Node* csts[kInputSize];
Node* accs[kInputSize];
@@ -4110,7 +4859,7 @@
accs[i] = acc;
}
for (int i = 0; i < kInputSize; i++) {
- m.StoreToPointer(&outputs[i], kMachInt32, accs[i]);
+ m.StoreToPointer(&outputs[i], MachineRepresentation::kWord32, accs[i]);
}
m.Return(m.Int32Add(acc, m.Int32Add(m.Parameter(0), m.Parameter(1))));
FOR_INT32_INPUTS(i) {
@@ -4131,7 +4880,7 @@
TEST(RunNewSpaceConstantsInPhi) {
- RawMachineAssemblerTester<Object*> m(kMachInt32);
+ RawMachineAssemblerTester<Object*> m(MachineType::Int32());
Isolate* isolate = CcTest::i_isolate();
Handle<HeapNumber> true_val = isolate->factory()->NewHeapNumber(11.2);
@@ -4139,7 +4888,7 @@
Node* true_node = m.HeapConstant(true_val);
Node* false_node = m.HeapConstant(false_val);
- MLabel blocka, blockb, end;
+ RawMachineLabel blocka, blockb, end;
m.Branch(m.Parameter(0), &blocka, &blockb);
m.Bind(&blocka);
m.Goto(&end);
@@ -4147,7 +4896,7 @@
m.Goto(&end);
m.Bind(&end);
- Node* phi = m.Phi(kMachAnyTagged, true_node, false_node);
+ Node* phi = m.Phi(MachineRepresentation::kTagged, true_node, false_node);
m.Return(phi);
CHECK_EQ(*false_val, m.Call(0));
@@ -4162,7 +4911,7 @@
Node* add = m.Int32AddWithOverflow(bt.param0, bt.param1);
Node* val = m.Projection(0, add);
Node* ovf = m.Projection(1, add);
- m.StoreToPointer(&actual_val, kMachInt32, val);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
bt.AddReturn(ovf);
FOR_INT32_INPUTS(i) {
FOR_INT32_INPUTS(j) {
@@ -4179,11 +4928,11 @@
int32_t actual_val = -1, expected_val = 0;
FOR_INT32_INPUTS(i) {
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
Node* add = m.Int32AddWithOverflow(m.Int32Constant(*i), m.Parameter(0));
Node* val = m.Projection(0, add);
Node* ovf = m.Projection(1, add);
- m.StoreToPointer(&actual_val, kMachInt32, val);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
m.Return(ovf);
FOR_INT32_INPUTS(j) {
int expected_ovf = bits::SignedAddOverflow32(*i, *j, &expected_val);
@@ -4192,11 +4941,11 @@
}
}
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
Node* add = m.Int32AddWithOverflow(m.Parameter(0), m.Int32Constant(*i));
Node* val = m.Projection(0, add);
Node* ovf = m.Projection(1, add);
- m.StoreToPointer(&actual_val, kMachInt32, val);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
m.Return(ovf);
FOR_INT32_INPUTS(j) {
int expected_ovf = bits::SignedAddOverflow32(*i, *j, &expected_val);
@@ -4210,7 +4959,7 @@
m.Int32AddWithOverflow(m.Int32Constant(*i), m.Int32Constant(*j));
Node* val = m.Projection(0, add);
Node* ovf = m.Projection(1, add);
- m.StoreToPointer(&actual_val, kMachInt32, val);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
m.Return(ovf);
int expected_ovf = bits::SignedAddOverflow32(*i, *j, &expected_val);
CHECK_EQ(expected_ovf, m.Call());
@@ -4222,7 +4971,7 @@
TEST(RunInt32AddWithOverflowInBranchP) {
int constant = 911777;
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
RawMachineAssemblerTester<int32_t> m;
Int32BinopTester bt(&m);
Node* add = m.Int32AddWithOverflow(bt.param0, bt.param1);
@@ -4250,7 +4999,7 @@
Node* add = m.Int32SubWithOverflow(bt.param0, bt.param1);
Node* val = m.Projection(0, add);
Node* ovf = m.Projection(1, add);
- m.StoreToPointer(&actual_val, kMachInt32, val);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
bt.AddReturn(ovf);
FOR_INT32_INPUTS(i) {
FOR_INT32_INPUTS(j) {
@@ -4267,11 +5016,11 @@
int32_t actual_val = -1, expected_val = 0;
FOR_INT32_INPUTS(i) {
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
Node* add = m.Int32SubWithOverflow(m.Int32Constant(*i), m.Parameter(0));
Node* val = m.Projection(0, add);
Node* ovf = m.Projection(1, add);
- m.StoreToPointer(&actual_val, kMachInt32, val);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
m.Return(ovf);
FOR_INT32_INPUTS(j) {
int expected_ovf = bits::SignedSubOverflow32(*i, *j, &expected_val);
@@ -4280,11 +5029,11 @@
}
}
{
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
Node* add = m.Int32SubWithOverflow(m.Parameter(0), m.Int32Constant(*i));
Node* val = m.Projection(0, add);
Node* ovf = m.Projection(1, add);
- m.StoreToPointer(&actual_val, kMachInt32, val);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
m.Return(ovf);
FOR_INT32_INPUTS(j) {
int expected_ovf = bits::SignedSubOverflow32(*j, *i, &expected_val);
@@ -4298,7 +5047,7 @@
m.Int32SubWithOverflow(m.Int32Constant(*i), m.Int32Constant(*j));
Node* val = m.Projection(0, add);
Node* ovf = m.Projection(1, add);
- m.StoreToPointer(&actual_val, kMachInt32, val);
+ m.StoreToPointer(&actual_val, MachineRepresentation::kWord32, val);
m.Return(ovf);
int expected_ovf = bits::SignedSubOverflow32(*i, *j, &expected_val);
CHECK_EQ(expected_ovf, m.Call());
@@ -4310,7 +5059,7 @@
TEST(RunInt32SubWithOverflowInBranchP) {
int constant = 911999;
- MLabel blocka, blockb;
+ RawMachineLabel blocka, blockb;
RawMachineAssemblerTester<int32_t> m;
Int32BinopTester bt(&m);
Node* sub = m.Int32SubWithOverflow(bt.param0, bt.param1);
@@ -4331,11 +5080,32 @@
}
+TEST(RunWord64EqualInBranchP) {
+ int64_t input;
+ RawMachineLabel blocka, blockb;
+ RawMachineAssemblerTester<int64_t> m;
+ if (!m.machine()->Is64()) return;
+ Node* value = m.LoadFromPointer(&input, MachineType::Int64());
+ m.Branch(m.Word64Equal(value, m.Int64Constant(0)), &blocka, &blockb);
+ m.Bind(&blocka);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&blockb);
+ m.Return(m.Int32Constant(2));
+ input = V8_INT64_C(0);
+ CHECK_EQ(1, m.Call());
+ input = V8_INT64_C(1);
+ CHECK_EQ(2, m.Call());
+ input = V8_INT64_C(0x100000000);
+ CHECK_EQ(2, m.Call());
+}
+
+
TEST(RunChangeInt32ToInt64P) {
if (kPointerSize < 8) return;
int64_t actual = -1;
- RawMachineAssemblerTester<int32_t> m(kMachInt32);
- m.StoreToPointer(&actual, kMachInt64, m.ChangeInt32ToInt64(m.Parameter(0)));
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
+ m.StoreToPointer(&actual, MachineRepresentation::kWord64,
+ m.ChangeInt32ToInt64(m.Parameter(0)));
m.Return(m.Int32Constant(0));
FOR_INT32_INPUTS(i) {
int64_t expected = *i;
@@ -4348,8 +5118,8 @@
TEST(RunChangeUint32ToUint64P) {
if (kPointerSize < 8) return;
int64_t actual = -1;
- RawMachineAssemblerTester<int32_t> m(kMachUint32);
- m.StoreToPointer(&actual, kMachUint64,
+ RawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
+ m.StoreToPointer(&actual, MachineRepresentation::kWord64,
m.ChangeUint32ToUint64(m.Parameter(0)));
m.Return(m.Int32Constant(0));
FOR_UINT32_INPUTS(i) {
@@ -4364,11 +5134,12 @@
if (kPointerSize < 8) return;
int64_t expected = -1;
RawMachineAssemblerTester<int32_t> m;
- m.Return(m.TruncateInt64ToInt32(m.LoadFromPointer(&expected, kMachInt64)));
+ m.Return(m.TruncateInt64ToInt32(
+ m.LoadFromPointer(&expected, MachineType::Int64())));
FOR_UINT32_INPUTS(i) {
FOR_UINT32_INPUTS(j) {
expected = (static_cast<uint64_t>(*j) << 32) | *i;
- CHECK_UINT32_EQ(expected, m.Call());
+ CHECK_EQ(static_cast<int32_t>(expected), m.Call());
}
}
}
@@ -4385,9 +5156,9 @@
{-1.5, -1},
{5.5, 5},
{-5.0, -5},
- {v8::base::OS::nan_value(), 0},
+ {std::numeric_limits<double>::quiet_NaN(), 0},
{std::numeric_limits<double>::infinity(), 0},
- {-v8::base::OS::nan_value(), 0},
+ {-std::numeric_limits<double>::quiet_NaN(), 0},
{-std::numeric_limits<double>::infinity(), 0},
{4.94065645841e-324, 0},
{-4.94065645841e-324, 0},
@@ -4435,7 +5206,9 @@
{-1.7976931348623157e+308, 0}};
double input = -1.0;
RawMachineAssemblerTester<int32_t> m;
- m.Return(m.TruncateFloat64ToInt32(m.LoadFromPointer(&input, kMachFloat64)));
+ m.Return(m.TruncateFloat64ToInt32(
+ TruncationMode::kJavaScript,
+ m.LoadFromPointer(&input, MachineType::Float64())));
for (size_t i = 0; i < arraysize(kValues); ++i) {
input = kValues[i].from;
uint64_t expected = static_cast<int64_t>(kValues[i].raw);
@@ -4445,83 +5218,87 @@
TEST(RunChangeFloat32ToFloat64) {
- double actual = 0.0f;
- float expected = 0.0;
- RawMachineAssemblerTester<int32_t> m;
- m.StoreToPointer(
- &actual, kMachFloat64,
- m.ChangeFloat32ToFloat64(m.LoadFromPointer(&expected, kMachFloat32)));
- m.Return(m.Int32Constant(0));
- FOR_FLOAT32_INPUTS(i) {
- expected = *i;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, actual);
- }
-}
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float32());
+ m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0)));
-TEST(RunChangeFloat32ToFloat64_spilled) {
- RawMachineAssemblerTester<int32_t> m;
- const int kNumInputs = 32;
- int32_t magic = 0x786234;
- float input[kNumInputs];
- double result[kNumInputs];
- Node* input_node[kNumInputs];
-
- for (int i = 0; i < kNumInputs; i++) {
- input_node[i] =
- m.Load(kMachFloat32, m.PointerConstant(&input), m.Int32Constant(i * 4));
- }
-
- for (int i = 0; i < kNumInputs; i++) {
- m.Store(kMachFloat64, m.PointerConstant(&result), m.Int32Constant(i * 8),
- m.ChangeFloat32ToFloat64(input_node[i]));
- }
-
- m.Return(m.Int32Constant(magic));
-
- for (int i = 0; i < kNumInputs; i++) {
- input[i] = 100.9f + i;
- }
-
- CHECK_EQ(magic, m.Call());
-
- for (int i = 0; i < kNumInputs; i++) {
- CHECK_EQ(result[i], static_cast<double>(input[i]));
- }
-}
-
-
-TEST(RunTruncateFloat64ToFloat32) {
- float actual = 0.0f;
- double input = 0.0;
- RawMachineAssemblerTester<int32_t> m;
- m.StoreToPointer(
- &actual, kMachFloat32,
- m.TruncateFloat64ToFloat32(m.LoadFromPointer(&input, kMachFloat64)));
- m.Return(m.Int32Constant(0));
- FOR_FLOAT64_INPUTS(i) {
- input = *i;
- volatile double expected = DoubleToFloat32(input);
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, actual);
- }
+ FOR_FLOAT32_INPUTS(i) { CheckDoubleEq(static_cast<double>(*i), m.Call(*i)); }
}
TEST(RunFloat32Constant) {
FOR_FLOAT32_INPUTS(i) {
- float expected = *i;
- float actual = *i;
- RawMachineAssemblerTester<int32_t> m;
- m.StoreToPointer(&actual, kMachFloat32, m.Float32Constant(expected));
- m.Return(m.Int32Constant(0));
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, actual);
+ BufferedRawMachineAssemblerTester<float> m;
+ m.Return(m.Float32Constant(*i));
+ CheckFloatEq(*i, m.Call());
}
}
+TEST(RunFloat64ExtractLowWord32) {
+ BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Float64());
+ m.Return(m.Float64ExtractLowWord32(m.Parameter(0)));
+ FOR_FLOAT64_INPUTS(i) {
+ uint32_t expected = static_cast<uint32_t>(bit_cast<uint64_t>(*i));
+ CHECK_EQ(expected, m.Call(*i));
+ }
+}
+
+
+TEST(RunFloat64ExtractHighWord32) {
+ BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Float64());
+ m.Return(m.Float64ExtractHighWord32(m.Parameter(0)));
+ FOR_FLOAT64_INPUTS(i) {
+ uint32_t expected = static_cast<uint32_t>(bit_cast<uint64_t>(*i) >> 32);
+ CHECK_EQ(expected, m.Call(*i));
+ }
+}
+
+
+TEST(RunFloat64InsertLowWord32) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
+ MachineType::Int32());
+ m.Return(m.Float64InsertLowWord32(m.Parameter(0), m.Parameter(1)));
+ FOR_FLOAT64_INPUTS(i) {
+ FOR_INT32_INPUTS(j) {
+ double expected = bit_cast<double>(
+ (bit_cast<uint64_t>(*i) & ~(V8_UINT64_C(0xFFFFFFFF))) |
+ (static_cast<uint64_t>(bit_cast<uint32_t>(*j))));
+ CheckDoubleEq(expected, m.Call(*i, *j));
+ }
+ }
+}
+
+
+TEST(RunFloat64InsertHighWord32) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64(),
+ MachineType::Uint32());
+ m.Return(m.Float64InsertHighWord32(m.Parameter(0), m.Parameter(1)));
+ FOR_FLOAT64_INPUTS(i) {
+ FOR_UINT32_INPUTS(j) {
+ uint64_t expected = (bit_cast<uint64_t>(*i) & 0xFFFFFFFF) |
+ (static_cast<uint64_t>(*j) << 32);
+
+ CheckDoubleEq(bit_cast<double>(expected), m.Call(*i, *j));
+ }
+ }
+}
+
+
+TEST(RunFloat32Abs) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
+ m.Return(m.Float32Abs(m.Parameter(0)));
+ FOR_FLOAT32_INPUTS(i) { CheckFloatEq(std::abs(*i), m.Call(*i)); }
+}
+
+
+TEST(RunFloat64Abs) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+ m.Return(m.Float64Abs(m.Parameter(0)));
+ FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(std::abs(*i), m.Call(*i)); }
+}
+
+
static double two_30 = 1 << 30; // 2^30 is a smi boundary.
static double two_52 = two_30 * (1 << 22); // 2^52 is a precision boundary.
static double kValues[] = {0.1,
@@ -4620,72 +5397,677 @@
-two_52 + 1 - 0.7};
-TEST(RunFloat64Floor) {
- double input = -1.0;
- double result = 0.0;
- RawMachineAssemblerTester<int32_t> m;
- if (!m.machine()->HasFloat64Floor()) return;
- m.StoreToPointer(&result, kMachFloat64,
- m.Float64Floor(m.LoadFromPointer(&input, kMachFloat64)));
- m.Return(m.Int32Constant(0));
+TEST(RunFloat32RoundDown) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
+ if (!m.machine()->Float32RoundDown().IsSupported()) return;
+
+ m.Return(m.Float32RoundDown(m.Parameter(0)));
+
+ FOR_FLOAT32_INPUTS(i) { CheckFloatEq(floorf(*i), m.Call(*i)); }
+}
+
+
+TEST(RunFloat64RoundDown1) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+ if (!m.machine()->Float64RoundDown().IsSupported()) return;
+
+ m.Return(m.Float64RoundDown(m.Parameter(0)));
+
+ FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(floor(*i), m.Call(*i)); }
+}
+
+
+TEST(RunFloat64RoundDown2) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+ if (!m.machine()->Float64RoundDown().IsSupported()) return;
+ m.Return(m.Float64Sub(m.Float64Constant(-0.0),
+ m.Float64RoundDown(m.Float64Sub(m.Float64Constant(-0.0),
+ m.Parameter(0)))));
+
for (size_t i = 0; i < arraysize(kValues); ++i) {
- input = kValues[i];
- CHECK_EQ(0, m.Call());
- double expected = std::floor(kValues[i]);
- CHECK_EQ(expected, result);
+ CHECK_EQ(ceil(kValues[i]), m.Call(kValues[i]));
}
}
-TEST(RunFloat64Ceil) {
- double input = -1.0;
- double result = 0.0;
- RawMachineAssemblerTester<int32_t> m;
- if (!m.machine()->HasFloat64Ceil()) return;
- m.StoreToPointer(&result, kMachFloat64,
- m.Float64Ceil(m.LoadFromPointer(&input, kMachFloat64)));
- m.Return(m.Int32Constant(0));
- for (size_t i = 0; i < arraysize(kValues); ++i) {
- input = kValues[i];
- CHECK_EQ(0, m.Call());
- double expected = std::ceil(kValues[i]);
- CHECK_EQ(expected, result);
- }
+TEST(RunFloat32RoundUp) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
+ if (!m.machine()->Float32RoundUp().IsSupported()) return;
+ m.Return(m.Float32RoundUp(m.Parameter(0)));
+
+ FOR_FLOAT32_INPUTS(i) { CheckFloatEq(ceilf(*i), m.Call(*i)); }
+}
+
+
+TEST(RunFloat64RoundUp) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+ if (!m.machine()->Float64RoundUp().IsSupported()) return;
+ m.Return(m.Float64RoundUp(m.Parameter(0)));
+
+ FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(ceil(*i), m.Call(*i)); }
+}
+
+
+TEST(RunFloat32RoundTiesEven) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
+ if (!m.machine()->Float32RoundTiesEven().IsSupported()) return;
+ m.Return(m.Float32RoundTiesEven(m.Parameter(0)));
+
+ FOR_FLOAT32_INPUTS(i) { CheckFloatEq(nearbyint(*i), m.Call(*i)); }
+}
+
+
+TEST(RunFloat64RoundTiesEven) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+ if (!m.machine()->Float64RoundTiesEven().IsSupported()) return;
+ m.Return(m.Float64RoundTiesEven(m.Parameter(0)));
+
+ FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(nearbyint(*i), m.Call(*i)); }
+}
+
+
+TEST(RunFloat32RoundTruncate) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Float32());
+ if (!m.machine()->Float32RoundTruncate().IsSupported()) return;
+
+ m.Return(m.Float32RoundTruncate(m.Parameter(0)));
+
+ FOR_FLOAT32_INPUTS(i) { CheckFloatEq(truncf(*i), m.Call(*i)); }
}
TEST(RunFloat64RoundTruncate) {
- double input = -1.0;
- double result = 0.0;
- RawMachineAssemblerTester<int32_t> m;
- if (!m.machine()->HasFloat64Ceil()) return;
- m.StoreToPointer(
- &result, kMachFloat64,
- m.Float64RoundTruncate(m.LoadFromPointer(&input, kMachFloat64)));
- m.Return(m.Int32Constant(0));
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+ if (!m.machine()->Float64RoundTruncate().IsSupported()) return;
+ m.Return(m.Float64RoundTruncate(m.Parameter(0)));
for (size_t i = 0; i < arraysize(kValues); ++i) {
- input = kValues[i];
- CHECK_EQ(0, m.Call());
- double expected = trunc(kValues[i]);
- CHECK_EQ(expected, result);
+ CHECK_EQ(trunc(kValues[i]), m.Call(kValues[i]));
}
}
TEST(RunFloat64RoundTiesAway) {
- double input = -1.0;
- double result = 0.0;
- RawMachineAssemblerTester<int32_t> m;
- if (!m.machine()->HasFloat64RoundTiesAway()) return;
- m.StoreToPointer(
- &result, kMachFloat64,
- m.Float64RoundTiesAway(m.LoadFromPointer(&input, kMachFloat64)));
- m.Return(m.Int32Constant(0));
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Float64());
+ if (!m.machine()->Float64RoundTiesAway().IsSupported()) return;
+ m.Return(m.Float64RoundTiesAway(m.Parameter(0)));
for (size_t i = 0; i < arraysize(kValues); ++i) {
- input = kValues[i];
- CHECK_EQ(0, m.Call());
- double expected = round(kValues[i]);
- CHECK_EQ(expected, result);
+ CHECK_EQ(round(kValues[i]), m.Call(kValues[i]));
}
}
-#endif // V8_TURBOFAN_TARGET
+
+
+#if !USE_SIMULATOR
+
+namespace {
+
+int32_t const kMagicFoo0 = 0xdeadbeef;
+
+
+int32_t foo0() { return kMagicFoo0; }
+
+
+int32_t foo1(int32_t x) { return x; }
+
+
+int32_t foo2(int32_t x, int32_t y) { return x - y; }
+
+
+int32_t foo8(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, int32_t f,
+ int32_t g, int32_t h) {
+ return a + b + c + d + e + f + g + h;
+}
+
+} // namespace
+
+
+TEST(RunCallCFunction0) {
+ auto* foo0_ptr = &foo0;
+ RawMachineAssemblerTester<int32_t> m;
+ Node* function = m.LoadFromPointer(&foo0_ptr, MachineType::Pointer());
+ m.Return(m.CallCFunction0(MachineType::Int32(), function));
+ CHECK_EQ(kMagicFoo0, m.Call());
+}
+
+
+TEST(RunCallCFunction1) {
+ auto* foo1_ptr = &foo1;
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
+ Node* function = m.LoadFromPointer(&foo1_ptr, MachineType::Pointer());
+ m.Return(m.CallCFunction1(MachineType::Int32(), MachineType::Int32(),
+ function, m.Parameter(0)));
+ FOR_INT32_INPUTS(i) {
+ int32_t const expected = *i;
+ CHECK_EQ(expected, m.Call(expected));
+ }
+}
+
+
+TEST(RunCallCFunction2) {
+ auto* foo2_ptr = &foo2;
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32(),
+ MachineType::Int32());
+ Node* function = m.LoadFromPointer(&foo2_ptr, MachineType::Pointer());
+ m.Return(m.CallCFunction2(MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), function, m.Parameter(0),
+ m.Parameter(1)));
+ FOR_INT32_INPUTS(i) {
+ int32_t const x = *i;
+ FOR_INT32_INPUTS(j) {
+ int32_t const y = *j;
+ CHECK_EQ(x - y, m.Call(x, y));
+ }
+ }
+}
+
+
+TEST(RunCallCFunction8) {
+ auto* foo8_ptr = &foo8;
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
+ Node* function = m.LoadFromPointer(&foo8_ptr, MachineType::Pointer());
+ Node* param = m.Parameter(0);
+ m.Return(m.CallCFunction8(
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ function, param, param, param, param, param, param, param, param));
+ FOR_INT32_INPUTS(i) {
+ int32_t const x = *i;
+ CHECK_EQ(x * 8, m.Call(x));
+ }
+}
+#endif // USE_SIMULATOR
+
+#if V8_TARGET_ARCH_64_BIT
+// TODO(titzer): run int64 tests on all platforms when supported.
+TEST(RunCheckedLoadInt64) {
+ int64_t buffer[] = {0x66bbccddeeff0011LL, 0x1122334455667788LL};
+ RawMachineAssemblerTester<int64_t> m(MachineType::Int32());
+ Node* base = m.PointerConstant(buffer);
+ Node* index = m.Parameter(0);
+ Node* length = m.Int32Constant(16);
+ Node* load = m.AddNode(m.machine()->CheckedLoad(MachineType::Int64()), base,
+ index, length);
+ m.Return(load);
+
+ CHECK_EQ(buffer[0], m.Call(0));
+ CHECK_EQ(buffer[1], m.Call(8));
+ CHECK_EQ(0, m.Call(16));
+}
+
+
+TEST(RunCheckedStoreInt64) {
+ const int64_t write = 0x5566778899aabbLL;
+ const int64_t before = 0x33bbccddeeff0011LL;
+ int64_t buffer[] = {before, before};
+ RawMachineAssemblerTester<int32_t> m(MachineType::Int32());
+ Node* base = m.PointerConstant(buffer);
+ Node* index = m.Parameter(0);
+ Node* length = m.Int32Constant(16);
+ Node* value = m.Int64Constant(write);
+ Node* store =
+ m.AddNode(m.machine()->CheckedStore(MachineRepresentation::kWord64), base,
+ index, length, value);
+ USE(store);
+ m.Return(m.Int32Constant(11));
+
+ CHECK_EQ(11, m.Call(16));
+ CHECK_EQ(before, buffer[0]);
+ CHECK_EQ(before, buffer[1]);
+
+ CHECK_EQ(11, m.Call(0));
+ CHECK_EQ(write, buffer[0]);
+ CHECK_EQ(before, buffer[1]);
+
+ CHECK_EQ(11, m.Call(8));
+ CHECK_EQ(write, buffer[0]);
+ CHECK_EQ(write, buffer[1]);
+}
+
+
+TEST(RunBitcastInt64ToFloat64) {
+ int64_t input = 1;
+ double output = 0.0;
+ RawMachineAssemblerTester<int32_t> m;
+ m.StoreToPointer(
+ &output, MachineRepresentation::kFloat64,
+ m.BitcastInt64ToFloat64(m.LoadFromPointer(&input, MachineType::Int64())));
+ m.Return(m.Int32Constant(11));
+ FOR_INT64_INPUTS(i) {
+ input = *i;
+ CHECK_EQ(11, m.Call());
+ double expected = bit_cast<double>(input);
+ CHECK_EQ(bit_cast<int64_t>(expected), bit_cast<int64_t>(output));
+ }
+}
+
+
+TEST(RunBitcastFloat64ToInt64) {
+ BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Float64());
+
+ m.Return(m.BitcastFloat64ToInt64(m.Parameter(0)));
+ FOR_FLOAT64_INPUTS(i) { CHECK_EQ(bit_cast<int64_t>(*i), m.Call(*i)); }
+}
+
+
+TEST(RunTryTruncateFloat32ToInt64WithoutCheck) {
+ BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Float32());
+ m.Return(m.TryTruncateFloat32ToInt64(m.Parameter(0)));
+
+ FOR_INT64_INPUTS(i) {
+ float input = static_cast<float>(*i);
+ if (input < static_cast<float>(INT64_MAX) &&
+ input >= static_cast<float>(INT64_MIN)) {
+ CHECK_EQ(static_cast<int64_t>(input), m.Call(input));
+ }
+ }
+}
+
+
+TEST(RunTryTruncateFloat32ToInt64WithCheck) {
+ int64_t success = 0;
+ BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Float32());
+ Node* trunc = m.TryTruncateFloat32ToInt64(m.Parameter(0));
+ Node* val = m.Projection(0, trunc);
+ Node* check = m.Projection(1, trunc);
+ m.StoreToPointer(&success, MachineRepresentation::kWord64, check);
+ m.Return(val);
+
+ FOR_FLOAT32_INPUTS(i) {
+ if (*i < static_cast<float>(INT64_MAX) &&
+ *i >= static_cast<float>(INT64_MIN)) {
+ CHECK_EQ(static_cast<int64_t>(*i), m.Call(*i));
+ CHECK_NE(0, success);
+ } else {
+ m.Call(*i);
+ CHECK_EQ(0, success);
+ }
+ }
+}
+
+
+TEST(RunTryTruncateFloat64ToInt64WithoutCheck) {
+ BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Float64());
+ m.Return(m.TryTruncateFloat64ToInt64(m.Parameter(0)));
+
+ FOR_INT64_INPUTS(i) {
+ double input = static_cast<double>(*i);
+ CHECK_EQ(static_cast<int64_t>(input), m.Call(input));
+ }
+}
+
+
+TEST(RunTryTruncateFloat64ToInt64WithCheck) {
+ int64_t success = 0;
+ BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Float64());
+ Node* trunc = m.TryTruncateFloat64ToInt64(m.Parameter(0));
+ Node* val = m.Projection(0, trunc);
+ Node* check = m.Projection(1, trunc);
+ m.StoreToPointer(&success, MachineRepresentation::kWord64, check);
+ m.Return(val);
+
+ FOR_FLOAT64_INPUTS(i) {
+ if (*i < static_cast<double>(INT64_MAX) &&
+ *i >= static_cast<double>(INT64_MIN)) {
+ // Conversions within this range should succeed.
+ CHECK_EQ(static_cast<int64_t>(*i), m.Call(*i));
+ CHECK_NE(0, success);
+ } else {
+ m.Call(*i);
+ CHECK_EQ(0, success);
+ }
+ }
+}
+
+
+TEST(RunTryTruncateFloat32ToUint64WithoutCheck) {
+ BufferedRawMachineAssemblerTester<uint64_t> m(MachineType::Float32());
+ m.Return(m.TryTruncateFloat32ToUint64(m.Parameter(0)));
+
+ FOR_UINT64_INPUTS(i) {
+ float input = static_cast<float>(*i);
+ // This condition on 'input' is required because
+ // static_cast<float>(UINT64_MAX) results in a value outside uint64 range.
+ if (input < static_cast<float>(UINT64_MAX)) {
+ CHECK_EQ(static_cast<uint64_t>(input), m.Call(input));
+ }
+ }
+}
+
+
+TEST(RunTryTruncateFloat32ToUint64WithCheck) {
+ int64_t success = 0;
+ BufferedRawMachineAssemblerTester<uint64_t> m(MachineType::Float32());
+ Node* trunc = m.TryTruncateFloat32ToUint64(m.Parameter(0));
+ Node* val = m.Projection(0, trunc);
+ Node* check = m.Projection(1, trunc);
+ m.StoreToPointer(&success, MachineRepresentation::kWord64, check);
+ m.Return(val);
+
+ FOR_FLOAT32_INPUTS(i) {
+ if (*i < static_cast<float>(UINT64_MAX) && *i > -1.0) {
+ // Conversions within this range should succeed.
+ CHECK_EQ(static_cast<uint64_t>(*i), m.Call(*i));
+ CHECK_NE(0, success);
+ } else {
+ m.Call(*i);
+ CHECK_EQ(0, success);
+ }
+ }
+}
+
+
+TEST(RunTryTruncateFloat64ToUint64WithoutCheck) {
+ BufferedRawMachineAssemblerTester<uint64_t> m(MachineType::Float64());
+ m.Return(m.TruncateFloat64ToUint64(m.Parameter(0)));
+
+ FOR_UINT64_INPUTS(j) {
+ double input = static_cast<double>(*j);
+
+ if (input < static_cast<float>(UINT64_MAX)) {
+ CHECK_EQ(static_cast<uint64_t>(input), m.Call(input));
+ }
+ }
+}
+
+
+TEST(RunTryTruncateFloat64ToUint64WithCheck) {
+ int64_t success = 0;
+ BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Float64());
+ Node* trunc = m.TryTruncateFloat64ToUint64(m.Parameter(0));
+ Node* val = m.Projection(0, trunc);
+ Node* check = m.Projection(1, trunc);
+ m.StoreToPointer(&success, MachineRepresentation::kWord64, check);
+ m.Return(val);
+
+ FOR_FLOAT64_INPUTS(i) {
+ if (*i < 18446744073709551616.0 && *i > -1) {
+ // Conversions within this range should succeed.
+ CHECK_EQ(static_cast<uint64_t>(*i), m.Call(*i));
+ CHECK_NE(0, success);
+ } else {
+ m.Call(*i);
+ CHECK_EQ(0, success);
+ }
+ }
+}
+
+
+TEST(RunRoundInt64ToFloat32) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Int64());
+ m.Return(m.RoundInt64ToFloat32(m.Parameter(0)));
+ FOR_INT64_INPUTS(i) { CHECK_EQ(static_cast<float>(*i), m.Call(*i)); }
+}
+
+
+TEST(RunRoundInt64ToFloat64) {
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Int64());
+ m.Return(m.RoundInt64ToFloat64(m.Parameter(0)));
+ FOR_INT64_INPUTS(i) { CHECK_EQ(static_cast<double>(*i), m.Call(*i)); }
+}
+
+
+TEST(RunRoundUint64ToFloat64) {
+ struct {
+ uint64_t input;
+ uint64_t expected;
+ } values[] = {{0x0, 0x0},
+ {0x1, 0x3ff0000000000000},
+ {0xffffffff, 0x41efffffffe00000},
+ {0x1b09788b, 0x41bb09788b000000},
+ {0x4c5fce8, 0x419317f3a0000000},
+ {0xcc0de5bf, 0x41e981bcb7e00000},
+ {0x2, 0x4000000000000000},
+ {0x3, 0x4008000000000000},
+ {0x4, 0x4010000000000000},
+ {0x5, 0x4014000000000000},
+ {0x8, 0x4020000000000000},
+ {0x9, 0x4022000000000000},
+ {0xffffffffffffffff, 0x43f0000000000000},
+ {0xfffffffffffffffe, 0x43f0000000000000},
+ {0xfffffffffffffffd, 0x43f0000000000000},
+ {0x100000000, 0x41f0000000000000},
+ {0xffffffff00000000, 0x43efffffffe00000},
+ {0x1b09788b00000000, 0x43bb09788b000000},
+ {0x4c5fce800000000, 0x439317f3a0000000},
+ {0xcc0de5bf00000000, 0x43e981bcb7e00000},
+ {0x200000000, 0x4200000000000000},
+ {0x300000000, 0x4208000000000000},
+ {0x400000000, 0x4210000000000000},
+ {0x500000000, 0x4214000000000000},
+ {0x800000000, 0x4220000000000000},
+ {0x900000000, 0x4222000000000000},
+ {0x273a798e187937a3, 0x43c39d3cc70c3c9c},
+ {0xece3af835495a16b, 0x43ed9c75f06a92b4},
+ {0xb668ecc11223344, 0x43a6cd1d98224467},
+ {0x9e, 0x4063c00000000000},
+ {0x43, 0x4050c00000000000},
+ {0xaf73, 0x40e5ee6000000000},
+ {0x116b, 0x40b16b0000000000},
+ {0x658ecc, 0x415963b300000000},
+ {0x2b3b4c, 0x41459da600000000},
+ {0x88776655, 0x41e10eeccaa00000},
+ {0x70000000, 0x41dc000000000000},
+ {0x7200000, 0x419c800000000000},
+ {0x7fffffff, 0x41dfffffffc00000},
+ {0x56123761, 0x41d5848dd8400000},
+ {0x7fffff00, 0x41dfffffc0000000},
+ {0x761c4761eeeeeeee, 0x43dd8711d87bbbbc},
+ {0x80000000eeeeeeee, 0x43e00000001dddde},
+ {0x88888888dddddddd, 0x43e11111111bbbbc},
+ {0xa0000000dddddddd, 0x43e40000001bbbbc},
+ {0xddddddddaaaaaaaa, 0x43ebbbbbbbb55555},
+ {0xe0000000aaaaaaaa, 0x43ec000000155555},
+ {0xeeeeeeeeeeeeeeee, 0x43edddddddddddde},
+ {0xfffffffdeeeeeeee, 0x43efffffffbdddde},
+ {0xf0000000dddddddd, 0x43ee0000001bbbbc},
+ {0x7fffffdddddddd, 0x435ffffff7777777},
+ {0x3fffffaaaaaaaa, 0x434fffffd5555555},
+ {0x1fffffaaaaaaaa, 0x433fffffaaaaaaaa},
+ {0xfffff, 0x412ffffe00000000},
+ {0x7ffff, 0x411ffffc00000000},
+ {0x3ffff, 0x410ffff800000000},
+ {0x1ffff, 0x40fffff000000000},
+ {0xffff, 0x40efffe000000000},
+ {0x7fff, 0x40dfffc000000000},
+ {0x3fff, 0x40cfff8000000000},
+ {0x1fff, 0x40bfff0000000000},
+ {0xfff, 0x40affe0000000000},
+ {0x7ff, 0x409ffc0000000000},
+ {0x3ff, 0x408ff80000000000},
+ {0x1ff, 0x407ff00000000000},
+ {0x3fffffffffff, 0x42cfffffffffff80},
+ {0x1fffffffffff, 0x42bfffffffffff00},
+ {0xfffffffffff, 0x42affffffffffe00},
+ {0x7ffffffffff, 0x429ffffffffffc00},
+ {0x3ffffffffff, 0x428ffffffffff800},
+ {0x1ffffffffff, 0x427ffffffffff000},
+ {0x8000008000000000, 0x43e0000010000000},
+ {0x8000008000000001, 0x43e0000010000000},
+ {0x8000000000000400, 0x43e0000000000000},
+ {0x8000000000000401, 0x43e0000000000001}};
+
+ BufferedRawMachineAssemblerTester<double> m(MachineType::Uint64());
+ m.Return(m.RoundUint64ToFloat64(m.Parameter(0)));
+
+ for (size_t i = 0; i < arraysize(values); i++) {
+ CHECK_EQ(bit_cast<double>(values[i].expected), m.Call(values[i].input));
+ }
+}
+
+
+TEST(RunRoundUint64ToFloat32) {
+ struct {
+ uint64_t input;
+ uint32_t expected;
+ } values[] = {{0x0, 0x0},
+ {0x1, 0x3f800000},
+ {0xffffffff, 0x4f800000},
+ {0x1b09788b, 0x4dd84bc4},
+ {0x4c5fce8, 0x4c98bf9d},
+ {0xcc0de5bf, 0x4f4c0de6},
+ {0x2, 0x40000000},
+ {0x3, 0x40400000},
+ {0x4, 0x40800000},
+ {0x5, 0x40a00000},
+ {0x8, 0x41000000},
+ {0x9, 0x41100000},
+ {0xffffffffffffffff, 0x5f800000},
+ {0xfffffffffffffffe, 0x5f800000},
+ {0xfffffffffffffffd, 0x5f800000},
+ {0x0, 0x0},
+ {0x100000000, 0x4f800000},
+ {0xffffffff00000000, 0x5f800000},
+ {0x1b09788b00000000, 0x5dd84bc4},
+ {0x4c5fce800000000, 0x5c98bf9d},
+ {0xcc0de5bf00000000, 0x5f4c0de6},
+ {0x200000000, 0x50000000},
+ {0x300000000, 0x50400000},
+ {0x400000000, 0x50800000},
+ {0x500000000, 0x50a00000},
+ {0x800000000, 0x51000000},
+ {0x900000000, 0x51100000},
+ {0x273a798e187937a3, 0x5e1ce9e6},
+ {0xece3af835495a16b, 0x5f6ce3b0},
+ {0xb668ecc11223344, 0x5d3668ed},
+ {0x9e, 0x431e0000},
+ {0x43, 0x42860000},
+ {0xaf73, 0x472f7300},
+ {0x116b, 0x458b5800},
+ {0x658ecc, 0x4acb1d98},
+ {0x2b3b4c, 0x4a2ced30},
+ {0x88776655, 0x4f087766},
+ {0x70000000, 0x4ee00000},
+ {0x7200000, 0x4ce40000},
+ {0x7fffffff, 0x4f000000},
+ {0x56123761, 0x4eac246f},
+ {0x7fffff00, 0x4efffffe},
+ {0x761c4761eeeeeeee, 0x5eec388f},
+ {0x80000000eeeeeeee, 0x5f000000},
+ {0x88888888dddddddd, 0x5f088889},
+ {0xa0000000dddddddd, 0x5f200000},
+ {0xddddddddaaaaaaaa, 0x5f5dddde},
+ {0xe0000000aaaaaaaa, 0x5f600000},
+ {0xeeeeeeeeeeeeeeee, 0x5f6eeeef},
+ {0xfffffffdeeeeeeee, 0x5f800000},
+ {0xf0000000dddddddd, 0x5f700000},
+ {0x7fffffdddddddd, 0x5b000000},
+ {0x3fffffaaaaaaaa, 0x5a7fffff},
+ {0x1fffffaaaaaaaa, 0x59fffffd},
+ {0xfffff, 0x497ffff0},
+ {0x7ffff, 0x48ffffe0},
+ {0x3ffff, 0x487fffc0},
+ {0x1ffff, 0x47ffff80},
+ {0xffff, 0x477fff00},
+ {0x7fff, 0x46fffe00},
+ {0x3fff, 0x467ffc00},
+ {0x1fff, 0x45fff800},
+ {0xfff, 0x457ff000},
+ {0x7ff, 0x44ffe000},
+ {0x3ff, 0x447fc000},
+ {0x1ff, 0x43ff8000},
+ {0x3fffffffffff, 0x56800000},
+ {0x1fffffffffff, 0x56000000},
+ {0xfffffffffff, 0x55800000},
+ {0x7ffffffffff, 0x55000000},
+ {0x3ffffffffff, 0x54800000},
+ {0x1ffffffffff, 0x54000000},
+ {0x8000008000000000, 0x5f000000},
+ {0x8000008000000001, 0x5f000001},
+ {0x8000000000000400, 0x5f000000},
+ {0x8000000000000401, 0x5f000000}};
+
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Uint64());
+ m.Return(m.RoundUint64ToFloat32(m.Parameter(0)));
+
+ for (size_t i = 0; i < arraysize(values); i++) {
+ CHECK_EQ(bit_cast<float>(values[i].expected), m.Call(values[i].input));
+ }
+}
+
+
+#endif
+
+
+TEST(RunBitcastFloat32ToInt32) {
+ float input = 32.25;
+ RawMachineAssemblerTester<int32_t> m;
+ m.Return(m.BitcastFloat32ToInt32(
+ m.LoadFromPointer(&input, MachineType::Float32())));
+ FOR_FLOAT32_INPUTS(i) {
+ input = *i;
+ int32_t expected = bit_cast<int32_t>(input);
+ CHECK_EQ(expected, m.Call());
+ }
+}
+
+
+TEST(RunBitcastInt32ToFloat32) {
+ int32_t input = 1;
+ float output = 0.0;
+ RawMachineAssemblerTester<int32_t> m;
+ m.StoreToPointer(
+ &output, MachineRepresentation::kFloat32,
+ m.BitcastInt32ToFloat32(m.LoadFromPointer(&input, MachineType::Int32())));
+ m.Return(m.Int32Constant(11));
+ FOR_INT32_INPUTS(i) {
+ input = *i;
+ CHECK_EQ(11, m.Call());
+ float expected = bit_cast<float>(input);
+ CHECK_EQ(bit_cast<int32_t>(expected), bit_cast<int32_t>(output));
+ }
+}
+
+
+TEST(RunComputedCodeObject) {
+ GraphBuilderTester<int32_t> a;
+ a.Return(a.Int32Constant(33));
+ a.End();
+ Handle<Code> code_a = a.GetCode();
+
+ GraphBuilderTester<int32_t> b;
+ b.Return(b.Int32Constant(44));
+ b.End();
+ Handle<Code> code_b = b.GetCode();
+
+ RawMachineAssemblerTester<int32_t> r(MachineType::Int32());
+ RawMachineLabel tlabel;
+ RawMachineLabel flabel;
+ RawMachineLabel merge;
+ r.Branch(r.Parameter(0), &tlabel, &flabel);
+ r.Bind(&tlabel);
+ Node* fa = r.HeapConstant(code_a);
+ r.Goto(&merge);
+ r.Bind(&flabel);
+ Node* fb = r.HeapConstant(code_b);
+ r.Goto(&merge);
+ r.Bind(&merge);
+ Node* phi = r.Phi(MachineRepresentation::kWord32, fa, fb);
+
+ // TODO(titzer): all this descriptor hackery is just to call the above
+ // functions as code objects instead of direct addresses.
+ CSignature0<int32_t> sig;
+ CallDescriptor* c = Linkage::GetSimplifiedCDescriptor(r.zone(), &sig);
+ LinkageLocation ret[] = {c->GetReturnLocation(0)};
+ Signature<LinkageLocation> loc(1, 0, ret);
+ CallDescriptor* desc = new (r.zone()) CallDescriptor( // --
+ CallDescriptor::kCallCodeObject, // kind
+ MachineType::AnyTagged(), // target_type
+ c->GetInputLocation(0), // target_loc
+ &sig, // machine_sig
+ &loc, // location_sig
+ 0, // stack count
+ Operator::kNoProperties, // properties
+ c->CalleeSavedRegisters(), // callee saved
+ c->CalleeSavedFPRegisters(), // callee saved FP
+ CallDescriptor::kNoFlags, // flags
+ "c-call-as-code");
+ Node* call = r.AddNode(r.common()->Call(desc), phi);
+ r.Return(call);
+
+ CHECK_EQ(33, r.Call(1));
+ CHECK_EQ(44, r.Call(0));
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-native-calls.cc b/test/cctest/compiler/test-run-native-calls.cc
new file mode 100644
index 0000000..791b0d7
--- /dev/null
+++ b/test/cctest/compiler/test-run-native-calls.cc
@@ -0,0 +1,1162 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/assembler.h"
+#include "src/codegen.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/raw-machine-assembler.h"
+#include "src/machine-type.h"
+#include "src/register-configuration.h"
+
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/codegen-tester.h"
+#include "test/cctest/compiler/graph-builder-tester.h"
+#include "test/cctest/compiler/value-helper.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+namespace {
+typedef float float32;
+typedef double float64;
+
+// Picks a representative pair of integers from the given range.
+// If there are less than {max_pairs} possible pairs, do them all, otherwise try
+// to select a representative set.
+class Pairs {
+ public:
+ Pairs(int max_pairs, int range, const int* codes)
+ : range_(range),
+ codes_(codes),
+ max_pairs_(std::min(max_pairs, range_ * range_)),
+ counter_(0) {}
+
+ bool More() { return counter_ < max_pairs_; }
+
+ void Next(int* r0, int* r1, bool same_is_ok) {
+ do {
+ // Find the next pair.
+ if (exhaustive()) {
+ *r0 = codes_[counter_ % range_];
+ *r1 = codes_[counter_ / range_];
+ } else {
+ // Try each integer at least once for both r0 and r1.
+ int index = counter_ / 2;
+ if (counter_ & 1) {
+ *r0 = codes_[index % range_];
+ *r1 = codes_[index / range_];
+ } else {
+ *r1 = codes_[index % range_];
+ *r0 = codes_[index / range_];
+ }
+ }
+ counter_++;
+ if ((same_is_ok) || (*r0 != *r1)) break;
+ if (counter_ == max_pairs_) {
+ // For the last hurrah, reg#0 with reg#n-1
+ *r0 = codes_[0];
+ *r1 = codes_[range_ - 1];
+ break;
+ }
+ } while (true);
+ }
+
+ private:
+ int range_;
+ const int* codes_;
+ int max_pairs_;
+ int counter_;
+ bool exhaustive() { return max_pairs_ == (range_ * range_); }
+};
+
+
+// Pairs of general purpose registers.
+class RegisterPairs : public Pairs {
+ public:
+ RegisterPairs()
+ : Pairs(
+ 100,
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->num_allocatable_general_registers(),
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->allocatable_general_codes()) {}
+};
+
+
+// Pairs of double registers.
+class Float32RegisterPairs : public Pairs {
+ public:
+ Float32RegisterPairs()
+ : Pairs(
+ 100,
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->num_allocatable_aliased_double_registers(),
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->allocatable_double_codes()) {}
+};
+
+
+// Pairs of double registers.
+class Float64RegisterPairs : public Pairs {
+ public:
+ Float64RegisterPairs()
+ : Pairs(
+ 100,
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->num_allocatable_aliased_double_registers(),
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->allocatable_double_codes()) {}
+};
+
+
+// Helper for allocating either an GP or FP reg, or the next stack slot.
+struct Allocator {
+ Allocator(int* gp, int gpc, int* fp, int fpc)
+ : gp_count(gpc),
+ gp_offset(0),
+ gp_regs(gp),
+ fp_count(fpc),
+ fp_offset(0),
+ fp_regs(fp),
+ stack_offset(0) {}
+
+ int gp_count;
+ int gp_offset;
+ int* gp_regs;
+
+ int fp_count;
+ int fp_offset;
+ int* fp_regs;
+
+ int stack_offset;
+
+ LinkageLocation Next(MachineType type) {
+ if (IsFloatingPoint(type.representation())) {
+ // Allocate a floating point register/stack location.
+ if (fp_offset < fp_count) {
+ return LinkageLocation::ForRegister(fp_regs[fp_offset++]);
+ } else {
+ int offset = -1 - stack_offset;
+ stack_offset += StackWords(type);
+ return LinkageLocation::ForCallerFrameSlot(offset);
+ }
+ } else {
+ // Allocate a general purpose register/stack location.
+ if (gp_offset < gp_count) {
+ return LinkageLocation::ForRegister(gp_regs[gp_offset++]);
+ } else {
+ int offset = -1 - stack_offset;
+ stack_offset += StackWords(type);
+ return LinkageLocation::ForCallerFrameSlot(offset);
+ }
+ }
+ }
+ int StackWords(MachineType type) {
+ // TODO(titzer): hack. float32 occupies 8 bytes on stack.
+ int size = IsFloatingPoint(type.representation())
+ ? kDoubleSize
+ : (1 << ElementSizeLog2Of(type.representation()));
+ return size <= kPointerSize ? 1 : size / kPointerSize;
+ }
+ void Reset() {
+ fp_offset = 0;
+ gp_offset = 0;
+ stack_offset = 0;
+ }
+};
+
+
+class RegisterConfig {
+ public:
+ RegisterConfig(Allocator& p, Allocator& r) : params(p), rets(r) {}
+
+ CallDescriptor* Create(Zone* zone, MachineSignature* msig) {
+ rets.Reset();
+ params.Reset();
+
+ LocationSignature::Builder locations(zone, msig->return_count(),
+ msig->parameter_count());
+ // Add return location(s).
+ const int return_count = static_cast<int>(locations.return_count_);
+ for (int i = 0; i < return_count; i++) {
+ locations.AddReturn(rets.Next(msig->GetReturn(i)));
+ }
+
+ // Add register and/or stack parameter(s).
+ const int parameter_count = static_cast<int>(msig->parameter_count());
+ for (int i = 0; i < parameter_count; i++) {
+ locations.AddParam(params.Next(msig->GetParam(i)));
+ }
+
+ const RegList kCalleeSaveRegisters = 0;
+ const RegList kCalleeSaveFPRegisters = 0;
+
+ MachineType target_type = MachineType::AnyTagged();
+ LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
+ int stack_param_count = params.stack_offset;
+ return new (zone) CallDescriptor( // --
+ CallDescriptor::kCallCodeObject, // kind
+ target_type, // target MachineType
+ target_loc, // target location
+ msig, // machine_sig
+ locations.Build(), // location_sig
+ stack_param_count, // stack_parameter_count
+ compiler::Operator::kNoProperties, // properties
+ kCalleeSaveRegisters, // callee-saved registers
+ kCalleeSaveFPRegisters, // callee-saved fp regs
+ CallDescriptor::kUseNativeStack, // flags
+ "c-call");
+ }
+
+ private:
+ Allocator& params;
+ Allocator& rets;
+};
+
+const int kMaxParamCount = 64;
+
+MachineType kIntTypes[kMaxParamCount + 1] = {
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32(), MachineType::Int32()};
+
+
+// For making uniform int32 signatures shorter.
+class Int32Signature : public MachineSignature {
+ public:
+ explicit Int32Signature(int param_count)
+ : MachineSignature(1, param_count, kIntTypes) {
+ CHECK(param_count <= kMaxParamCount);
+ }
+};
+
+
+Handle<Code> CompileGraph(const char* name, CallDescriptor* desc, Graph* graph,
+ Schedule* schedule = nullptr) {
+ Isolate* isolate = CcTest::InitIsolateOnce();
+ CompilationInfo info("testing", isolate, graph->zone());
+ Handle<Code> code =
+ Pipeline::GenerateCodeForTesting(&info, desc, graph, schedule);
+ CHECK(!code.is_null());
+#ifdef ENABLE_DISASSEMBLER
+ if (FLAG_print_opt_code) {
+ OFStream os(stdout);
+ code->Disassemble(name, os);
+ }
+#endif
+ return code;
+}
+
+
+Handle<Code> WrapWithCFunction(Handle<Code> inner, CallDescriptor* desc) {
+ Zone zone;
+ MachineSignature* msig =
+ const_cast<MachineSignature*>(desc->GetMachineSignature());
+ int param_count = static_cast<int>(msig->parameter_count());
+ GraphAndBuilders caller(&zone);
+ {
+ GraphAndBuilders& b = caller;
+ Node* start = b.graph()->NewNode(b.common()->Start(param_count + 3));
+ b.graph()->SetStart(start);
+ Node* target = b.graph()->NewNode(b.common()->HeapConstant(inner));
+
+ // Add arguments to the call.
+ Node** args = zone.NewArray<Node*>(param_count + 3);
+ int index = 0;
+ args[index++] = target;
+ for (int i = 0; i < param_count; i++) {
+ args[index] = b.graph()->NewNode(b.common()->Parameter(i), start);
+ index++;
+ }
+ args[index++] = start; // effect.
+ args[index++] = start; // control.
+
+ // Build the call and return nodes.
+ Node* call =
+ b.graph()->NewNode(b.common()->Call(desc), param_count + 3, args);
+ Node* ret = b.graph()->NewNode(b.common()->Return(), call, call, start);
+ b.graph()->SetEnd(ret);
+ }
+
+ CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, msig);
+
+ return CompileGraph("wrapper", cdesc, caller.graph());
+}
+
+
+template <typename CType>
+class ArgsBuffer {
+ public:
+ static const int kMaxParamCount = 64;
+
+ explicit ArgsBuffer(int count, int seed = 1) : count_(count), seed_(seed) {
+ // initialize the buffer with "seed 0"
+ seed_ = 0;
+ Mutate();
+ seed_ = seed;
+ }
+
+ class Sig : public MachineSignature {
+ public:
+ explicit Sig(int param_count)
+ : MachineSignature(1, param_count, MachTypes()) {
+ CHECK(param_count <= kMaxParamCount);
+ }
+ };
+
+ static MachineType* MachTypes() {
+ MachineType t = MachineTypeForC<CType>();
+ static MachineType kTypes[kMaxParamCount + 1] = {
+ t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t,
+ t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t,
+ t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t};
+ return kTypes;
+ }
+
+ Node* MakeConstant(RawMachineAssembler& raw, int32_t value) {
+ return raw.Int32Constant(value);
+ }
+
+ Node* MakeConstant(RawMachineAssembler& raw, int64_t value) {
+ return raw.Int64Constant(value);
+ }
+
+ Node* MakeConstant(RawMachineAssembler& raw, float32 value) {
+ return raw.Float32Constant(value);
+ }
+
+ Node* MakeConstant(RawMachineAssembler& raw, float64 value) {
+ return raw.Float64Constant(value);
+ }
+
+ Node* LoadInput(RawMachineAssembler& raw, Node* base, int index) {
+ Node* offset = raw.Int32Constant(index * sizeof(CType));
+ return raw.Load(MachineTypeForC<CType>(), base, offset);
+ }
+
+ Node* StoreOutput(RawMachineAssembler& raw, Node* value) {
+ Node* base = raw.PointerConstant(&output);
+ Node* offset = raw.Int32Constant(0);
+ return raw.Store(MachineTypeForC<CType>().representation(), base, offset,
+ value, kNoWriteBarrier);
+ }
+
+ // Computes the next set of inputs by updating the {input} array.
+ void Mutate();
+
+ void Reset() { memset(input, 0, sizeof(input)); }
+
+ int count_;
+ int seed_;
+ CType input[kMaxParamCount];
+ CType output;
+};
+
+
+template <>
+void ArgsBuffer<int32_t>::Mutate() {
+ uint32_t base = 1111111111u * seed_;
+ for (int j = 0; j < count_ && j < kMaxParamCount; j++) {
+ input[j] = static_cast<int32_t>(256 + base + j + seed_ * 13);
+ }
+ output = -1;
+ seed_++;
+}
+
+
+template <>
+void ArgsBuffer<int64_t>::Mutate() {
+ uint64_t base = 11111111111111111ull * seed_;
+ for (int j = 0; j < count_ && j < kMaxParamCount; j++) {
+ input[j] = static_cast<int64_t>(256 + base + j + seed_ * 13);
+ }
+ output = -1;
+ seed_++;
+}
+
+
+template <>
+void ArgsBuffer<float32>::Mutate() {
+ float64 base = -33.25 * seed_;
+ for (int j = 0; j < count_ && j < kMaxParamCount; j++) {
+ input[j] = 256 + base + j + seed_ * 13;
+ }
+ output = std::numeric_limits<float32>::quiet_NaN();
+ seed_++;
+}
+
+
+template <>
+void ArgsBuffer<float64>::Mutate() {
+ float64 base = -111.25 * seed_;
+ for (int j = 0; j < count_ && j < kMaxParamCount; j++) {
+ input[j] = 256 + base + j + seed_ * 13;
+ }
+ output = std::numeric_limits<float64>::quiet_NaN();
+ seed_++;
+}
+
+
+int ParamCount(CallDescriptor* desc) {
+ return static_cast<int>(desc->GetMachineSignature()->parameter_count());
+}
+
+
+template <typename CType>
+class Computer {
+ public:
+ static void Run(CallDescriptor* desc,
+ void (*build)(CallDescriptor*, RawMachineAssembler&),
+ CType (*compute)(CallDescriptor*, CType* inputs),
+ int seed = 1) {
+ int num_params = ParamCount(desc);
+ CHECK_LE(num_params, kMaxParamCount);
+ Isolate* isolate = CcTest::InitIsolateOnce();
+ HandleScope scope(isolate);
+ Handle<Code> inner = Handle<Code>::null();
+ {
+ // Build the graph for the computation.
+ Zone zone;
+ Graph graph(&zone);
+ RawMachineAssembler raw(isolate, &graph, desc);
+ build(desc, raw);
+ inner = CompileGraph("Compute", desc, &graph, raw.Export());
+ }
+
+ CSignature0<int32_t> csig;
+ ArgsBuffer<CType> io(num_params, seed);
+
+ {
+ // constant mode.
+ Handle<Code> wrapper = Handle<Code>::null();
+ {
+ // Wrap the above code with a callable function that passes constants.
+ Zone zone;
+ Graph graph(&zone);
+ CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig);
+ RawMachineAssembler raw(isolate, &graph, cdesc);
+ Node* target = raw.HeapConstant(inner);
+ Node** args = zone.NewArray<Node*>(num_params);
+ for (int i = 0; i < num_params; i++) {
+ args[i] = io.MakeConstant(raw, io.input[i]);
+ }
+
+ Node* call = raw.CallN(desc, target, args);
+ Node* store = io.StoreOutput(raw, call);
+ USE(store);
+ raw.Return(raw.Int32Constant(seed));
+ wrapper =
+ CompileGraph("Compute-wrapper-const", cdesc, &graph, raw.Export());
+ }
+
+ CodeRunner<int32_t> runnable(isolate, wrapper, &csig);
+
+ // Run the code, checking it against the reference.
+ CType expected = compute(desc, io.input);
+ int32_t check_seed = runnable.Call();
+ CHECK_EQ(seed, check_seed);
+ CHECK_EQ(expected, io.output);
+ }
+
+ {
+ // buffer mode.
+ Handle<Code> wrapper = Handle<Code>::null();
+ {
+ // Wrap the above code with a callable function that loads from {input}.
+ Zone zone;
+ Graph graph(&zone);
+ CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig);
+ RawMachineAssembler raw(isolate, &graph, cdesc);
+ Node* base = raw.PointerConstant(io.input);
+ Node* target = raw.HeapConstant(inner);
+ Node** args = zone.NewArray<Node*>(kMaxParamCount);
+ for (int i = 0; i < num_params; i++) {
+ args[i] = io.LoadInput(raw, base, i);
+ }
+
+ Node* call = raw.CallN(desc, target, args);
+ Node* store = io.StoreOutput(raw, call);
+ USE(store);
+ raw.Return(raw.Int32Constant(seed));
+ wrapper = CompileGraph("Compute-wrapper", cdesc, &graph, raw.Export());
+ }
+
+ CodeRunner<int32_t> runnable(isolate, wrapper, &csig);
+
+ // Run the code, checking it against the reference.
+ for (int i = 0; i < 5; i++) {
+ CType expected = compute(desc, io.input);
+ int32_t check_seed = runnable.Call();
+ CHECK_EQ(seed, check_seed);
+ CHECK_EQ(expected, io.output);
+ io.Mutate();
+ }
+ }
+ }
+};
+
+} // namespace
+
+
+static void TestInt32Sub(CallDescriptor* desc) {
+ Isolate* isolate = CcTest::InitIsolateOnce();
+ HandleScope scope(isolate);
+ Zone zone;
+ GraphAndBuilders inner(&zone);
+ {
+ // Build the add function.
+ GraphAndBuilders& b = inner;
+ Node* start = b.graph()->NewNode(b.common()->Start(5));
+ b.graph()->SetStart(start);
+ Node* p0 = b.graph()->NewNode(b.common()->Parameter(0), start);
+ Node* p1 = b.graph()->NewNode(b.common()->Parameter(1), start);
+ Node* add = b.graph()->NewNode(b.machine()->Int32Sub(), p0, p1);
+ Node* ret = b.graph()->NewNode(b.common()->Return(), add, start, start);
+ b.graph()->SetEnd(ret);
+ }
+
+ Handle<Code> inner_code = CompileGraph("Int32Sub", desc, inner.graph());
+ Handle<Code> wrapper = WrapWithCFunction(inner_code, desc);
+ MachineSignature* msig =
+ const_cast<MachineSignature*>(desc->GetMachineSignature());
+ CodeRunner<int32_t> runnable(isolate, wrapper,
+ CSignature::FromMachine(&zone, msig));
+
+ FOR_INT32_INPUTS(i) {
+ FOR_INT32_INPUTS(j) {
+ int32_t expected = static_cast<int32_t>(static_cast<uint32_t>(*i) -
+ static_cast<uint32_t>(*j));
+ int32_t result = runnable.Call(*i, *j);
+ CHECK_EQ(expected, result);
+ }
+ }
+}
+
+
+static void CopyTwentyInt32(CallDescriptor* desc) {
+ const int kNumParams = 20;
+ int32_t input[kNumParams];
+ int32_t output[kNumParams];
+ Isolate* isolate = CcTest::InitIsolateOnce();
+ HandleScope scope(isolate);
+ Handle<Code> inner = Handle<Code>::null();
+ {
+ // Writes all parameters into the output buffer.
+ Zone zone;
+ Graph graph(&zone);
+ RawMachineAssembler raw(isolate, &graph, desc);
+ Node* base = raw.PointerConstant(output);
+ for (int i = 0; i < kNumParams; i++) {
+ Node* offset = raw.Int32Constant(i * sizeof(int32_t));
+ raw.Store(MachineRepresentation::kWord32, base, offset, raw.Parameter(i),
+ kNoWriteBarrier);
+ }
+ raw.Return(raw.Int32Constant(42));
+ inner = CompileGraph("CopyTwentyInt32", desc, &graph, raw.Export());
+ }
+
+ CSignature0<int32_t> csig;
+ Handle<Code> wrapper = Handle<Code>::null();
+ {
+ // Loads parameters from the input buffer and calls the above code.
+ Zone zone;
+ Graph graph(&zone);
+ CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig);
+ RawMachineAssembler raw(isolate, &graph, cdesc);
+ Node* base = raw.PointerConstant(input);
+ Node* target = raw.HeapConstant(inner);
+ Node** args = zone.NewArray<Node*>(kNumParams);
+ for (int i = 0; i < kNumParams; i++) {
+ Node* offset = raw.Int32Constant(i * sizeof(int32_t));
+ args[i] = raw.Load(MachineType::Int32(), base, offset);
+ }
+
+ Node* call = raw.CallN(desc, target, args);
+ raw.Return(call);
+ wrapper =
+ CompileGraph("CopyTwentyInt32-wrapper", cdesc, &graph, raw.Export());
+ }
+
+ CodeRunner<int32_t> runnable(isolate, wrapper, &csig);
+
+ // Run the code, checking it correctly implements the memcpy.
+ for (int i = 0; i < 5; i++) {
+ uint32_t base = 1111111111u * i;
+ for (int j = 0; j < kNumParams; j++) {
+ input[j] = static_cast<int32_t>(base + 13 * j);
+ }
+
+ memset(output, 0, sizeof(output));
+ CHECK_EQ(42, runnable.Call());
+
+ for (int j = 0; j < kNumParams; j++) {
+ CHECK_EQ(input[j], output[j]);
+ }
+ }
+}
+
+
+static void Test_RunInt32SubWithRet(int retreg) {
+ Int32Signature sig(2);
+ Zone zone;
+ RegisterPairs pairs;
+ while (pairs.More()) {
+ int parray[2];
+ int rarray[] = {retreg};
+ pairs.Next(&parray[0], &parray[1], false);
+ Allocator params(parray, 2, nullptr, 0);
+ Allocator rets(rarray, 1, nullptr, 0);
+ RegisterConfig config(params, rets);
+ CallDescriptor* desc = config.Create(&zone, &sig);
+ TestInt32Sub(desc);
+ }
+}
+
+
+// Separate tests for parallelization.
+#define TEST_INT32_SUB_WITH_RET(x) \
+ TEST(Run_Int32Sub_all_allocatable_pairs_##x) { \
+ if (x < Register::kNumRegisters && \
+ Register::from_code(x).IsAllocatable()) { \
+ Test_RunInt32SubWithRet(x); \
+ } \
+ }
+
+
+TEST_INT32_SUB_WITH_RET(0)
+TEST_INT32_SUB_WITH_RET(1)
+TEST_INT32_SUB_WITH_RET(2)
+TEST_INT32_SUB_WITH_RET(3)
+TEST_INT32_SUB_WITH_RET(4)
+TEST_INT32_SUB_WITH_RET(5)
+TEST_INT32_SUB_WITH_RET(6)
+TEST_INT32_SUB_WITH_RET(7)
+TEST_INT32_SUB_WITH_RET(8)
+TEST_INT32_SUB_WITH_RET(9)
+TEST_INT32_SUB_WITH_RET(10)
+TEST_INT32_SUB_WITH_RET(11)
+TEST_INT32_SUB_WITH_RET(12)
+TEST_INT32_SUB_WITH_RET(13)
+TEST_INT32_SUB_WITH_RET(14)
+TEST_INT32_SUB_WITH_RET(15)
+TEST_INT32_SUB_WITH_RET(16)
+TEST_INT32_SUB_WITH_RET(17)
+TEST_INT32_SUB_WITH_RET(18)
+TEST_INT32_SUB_WITH_RET(19)
+
+
+TEST(Run_Int32Sub_all_allocatable_single) {
+ Int32Signature sig(2);
+ RegisterPairs pairs;
+ while (pairs.More()) {
+ Zone zone;
+ int parray[1];
+ int rarray[1];
+ pairs.Next(&rarray[0], &parray[0], true);
+ Allocator params(parray, 1, nullptr, 0);
+ Allocator rets(rarray, 1, nullptr, 0);
+ RegisterConfig config(params, rets);
+ CallDescriptor* desc = config.Create(&zone, &sig);
+ TestInt32Sub(desc);
+ }
+}
+
+
+TEST(Run_CopyTwentyInt32_all_allocatable_pairs) {
+ Int32Signature sig(20);
+ RegisterPairs pairs;
+ while (pairs.More()) {
+ Zone zone;
+ int parray[2];
+ int rarray[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableGeneralCode(0)};
+ pairs.Next(&parray[0], &parray[1], false);
+ Allocator params(parray, 2, nullptr, 0);
+ Allocator rets(rarray, 1, nullptr, 0);
+ RegisterConfig config(params, rets);
+ CallDescriptor* desc = config.Create(&zone, &sig);
+ CopyTwentyInt32(desc);
+ }
+}
+
+
+template <typename CType>
+static void Run_Computation(
+ CallDescriptor* desc, void (*build)(CallDescriptor*, RawMachineAssembler&),
+ CType (*compute)(CallDescriptor*, CType* inputs), int seed = 1) {
+ Computer<CType>::Run(desc, build, compute, seed);
+}
+
+
+static uint32_t coeff[] = {1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
+ 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73,
+ 79, 83, 89, 97, 101, 103, 107, 109, 113};
+
+
+static void Build_Int32_WeightedSum(CallDescriptor* desc,
+ RawMachineAssembler& raw) {
+ Node* result = raw.Int32Constant(0);
+ for (int i = 0; i < ParamCount(desc); i++) {
+ Node* term = raw.Int32Mul(raw.Parameter(i), raw.Int32Constant(coeff[i]));
+ result = raw.Int32Add(result, term);
+ }
+ raw.Return(result);
+}
+
+
+static int32_t Compute_Int32_WeightedSum(CallDescriptor* desc, int32_t* input) {
+ uint32_t result = 0;
+ for (int i = 0; i < ParamCount(desc); i++) {
+ result += static_cast<uint32_t>(input[i]) * coeff[i];
+ }
+ return static_cast<int32_t>(result);
+}
+
+
+static void Test_Int32_WeightedSum_of_size(int count) {
+ Int32Signature sig(count);
+ for (int p0 = 0; p0 < Register::kNumRegisters; p0++) {
+ if (Register::from_code(p0).IsAllocatable()) {
+ Zone zone;
+
+ int parray[] = {p0};
+ int rarray[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableGeneralCode(0)};
+ Allocator params(parray, 1, nullptr, 0);
+ Allocator rets(rarray, 1, nullptr, 0);
+ RegisterConfig config(params, rets);
+ CallDescriptor* desc = config.Create(&zone, &sig);
+ Run_Computation<int32_t>(desc, Build_Int32_WeightedSum,
+ Compute_Int32_WeightedSum, 257 + count);
+ }
+ }
+}
+
+
+// Separate tests for parallelization.
+#define TEST_INT32_WEIGHTEDSUM(x) \
+ TEST(Run_Int32_WeightedSum_##x) { Test_Int32_WeightedSum_of_size(x); }
+
+
+TEST_INT32_WEIGHTEDSUM(1)
+TEST_INT32_WEIGHTEDSUM(2)
+TEST_INT32_WEIGHTEDSUM(3)
+TEST_INT32_WEIGHTEDSUM(4)
+TEST_INT32_WEIGHTEDSUM(5)
+TEST_INT32_WEIGHTEDSUM(7)
+TEST_INT32_WEIGHTEDSUM(9)
+TEST_INT32_WEIGHTEDSUM(11)
+TEST_INT32_WEIGHTEDSUM(17)
+TEST_INT32_WEIGHTEDSUM(19)
+
+
+template <int which>
+static void Build_Select(CallDescriptor* desc, RawMachineAssembler& raw) {
+ raw.Return(raw.Parameter(which));
+}
+
+
+template <typename CType, int which>
+static CType Compute_Select(CallDescriptor* desc, CType* inputs) {
+ return inputs[which];
+}
+
+
+template <typename CType, int which>
+static void RunSelect(CallDescriptor* desc) {
+ int count = ParamCount(desc);
+ if (count <= which) return;
+ Run_Computation<CType>(desc, Build_Select<which>,
+ Compute_Select<CType, which>,
+ 1044 + which + 3 * sizeof(CType));
+}
+
+
+template <int which>
+void Test_Int32_Select() {
+ int parray[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableGeneralCode(0)};
+ int rarray[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableGeneralCode(0)};
+ Allocator params(parray, 1, nullptr, 0);
+ Allocator rets(rarray, 1, nullptr, 0);
+ RegisterConfig config(params, rets);
+
+ Zone zone;
+
+ for (int i = which + 1; i <= 64; i++) {
+ Int32Signature sig(i);
+ CallDescriptor* desc = config.Create(&zone, &sig);
+ RunSelect<int32_t, which>(desc);
+ }
+}
+
+
+// Separate tests for parallelization.
+#define TEST_INT32_SELECT(x) \
+ TEST(Run_Int32_Select_##x) { Test_Int32_Select<x>(); }
+
+
+TEST_INT32_SELECT(0)
+TEST_INT32_SELECT(1)
+TEST_INT32_SELECT(2)
+TEST_INT32_SELECT(3)
+TEST_INT32_SELECT(4)
+TEST_INT32_SELECT(5)
+TEST_INT32_SELECT(6)
+TEST_INT32_SELECT(11)
+TEST_INT32_SELECT(15)
+TEST_INT32_SELECT(19)
+TEST_INT32_SELECT(45)
+TEST_INT32_SELECT(62)
+TEST_INT32_SELECT(63)
+
+
+TEST(Int64Select_registers) {
+ if (RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->num_allocatable_general_registers() < 2)
+ return;
+ if (kPointerSize < 8) return; // TODO(titzer): int64 on 32-bit platforms
+
+ int rarray[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableGeneralCode(0)};
+ ArgsBuffer<int64_t>::Sig sig(2);
+
+ RegisterPairs pairs;
+ Zone zone;
+ while (pairs.More()) {
+ int parray[2];
+ pairs.Next(&parray[0], &parray[1], false);
+ Allocator params(parray, 2, nullptr, 0);
+ Allocator rets(rarray, 1, nullptr, 0);
+ RegisterConfig config(params, rets);
+
+ CallDescriptor* desc = config.Create(&zone, &sig);
+ RunSelect<int64_t, 0>(desc);
+ RunSelect<int64_t, 1>(desc);
+ }
+}
+
+
+TEST(Float32Select_registers) {
+ if (RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->num_allocatable_double_registers() < 2) {
+ return;
+ }
+
+ int rarray[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableDoubleCode(0)};
+ ArgsBuffer<float32>::Sig sig(2);
+
+ Float32RegisterPairs pairs;
+ Zone zone;
+ while (pairs.More()) {
+ int parray[2];
+ pairs.Next(&parray[0], &parray[1], false);
+ Allocator params(nullptr, 0, parray, 2);
+ Allocator rets(nullptr, 0, rarray, 1);
+ RegisterConfig config(params, rets);
+
+ CallDescriptor* desc = config.Create(&zone, &sig);
+ RunSelect<float32, 0>(desc);
+ RunSelect<float32, 1>(desc);
+ }
+}
+
+
+TEST(Float64Select_registers) {
+ if (RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->num_allocatable_double_registers() < 2)
+ return;
+ if (RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->num_allocatable_general_registers() < 2)
+ return;
+ int rarray[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableDoubleCode(0)};
+ ArgsBuffer<float64>::Sig sig(2);
+
+ Float64RegisterPairs pairs;
+ Zone zone;
+ while (pairs.More()) {
+ int parray[2];
+ pairs.Next(&parray[0], &parray[1], false);
+ Allocator params(nullptr, 0, parray, 2);
+ Allocator rets(nullptr, 0, rarray, 1);
+ RegisterConfig config(params, rets);
+
+ CallDescriptor* desc = config.Create(&zone, &sig);
+ RunSelect<float64, 0>(desc);
+ RunSelect<float64, 1>(desc);
+ }
+}
+
+
+TEST(Float32Select_stack_params_return_reg) {
+ int rarray[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableDoubleCode(0)};
+ Allocator params(nullptr, 0, nullptr, 0);
+ Allocator rets(nullptr, 0, rarray, 1);
+ RegisterConfig config(params, rets);
+
+ Zone zone;
+ for (int count = 1; count < 6; count++) {
+ ArgsBuffer<float32>::Sig sig(count);
+ CallDescriptor* desc = config.Create(&zone, &sig);
+ RunSelect<float32, 0>(desc);
+ RunSelect<float32, 1>(desc);
+ RunSelect<float32, 2>(desc);
+ RunSelect<float32, 3>(desc);
+ RunSelect<float32, 4>(desc);
+ RunSelect<float32, 5>(desc);
+ }
+}
+
+
+TEST(Float64Select_stack_params_return_reg) {
+ int rarray[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableDoubleCode(0)};
+ Allocator params(nullptr, 0, nullptr, 0);
+ Allocator rets(nullptr, 0, rarray, 1);
+ RegisterConfig config(params, rets);
+
+ Zone zone;
+ for (int count = 1; count < 6; count++) {
+ ArgsBuffer<float64>::Sig sig(count);
+ CallDescriptor* desc = config.Create(&zone, &sig);
+ RunSelect<float64, 0>(desc);
+ RunSelect<float64, 1>(desc);
+ RunSelect<float64, 2>(desc);
+ RunSelect<float64, 3>(desc);
+ RunSelect<float64, 4>(desc);
+ RunSelect<float64, 5>(desc);
+ }
+}
+
+
+template <typename CType, int which>
+static void Build_Select_With_Call(CallDescriptor* desc,
+ RawMachineAssembler& raw) {
+ Handle<Code> inner = Handle<Code>::null();
+ int num_params = ParamCount(desc);
+ CHECK_LE(num_params, kMaxParamCount);
+ {
+ Isolate* isolate = CcTest::InitIsolateOnce();
+ // Build the actual select.
+ Zone zone;
+ Graph graph(&zone);
+ RawMachineAssembler raw(isolate, &graph, desc);
+ raw.Return(raw.Parameter(which));
+ inner = CompileGraph("Select-indirection", desc, &graph, raw.Export());
+ CHECK(!inner.is_null());
+ CHECK(inner->IsCode());
+ }
+
+ {
+ // Build a call to the function that does the select.
+ Node* target = raw.HeapConstant(inner);
+ Node** args = raw.zone()->NewArray<Node*>(num_params);
+ for (int i = 0; i < num_params; i++) {
+ args[i] = raw.Parameter(i);
+ }
+
+ Node* call = raw.CallN(desc, target, args);
+ raw.Return(call);
+ }
+}
+
+
+TEST(Float64StackParamsToStackParams) {
+ int rarray[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableDoubleCode(0)};
+ Allocator params(nullptr, 0, nullptr, 0);
+ Allocator rets(nullptr, 0, rarray, 1);
+
+ Zone zone;
+ ArgsBuffer<float64>::Sig sig(2);
+ RegisterConfig config(params, rets);
+ CallDescriptor* desc = config.Create(&zone, &sig);
+
+ Run_Computation<float64>(desc, Build_Select_With_Call<float64, 0>,
+ Compute_Select<float64, 0>, 1098);
+
+ Run_Computation<float64>(desc, Build_Select_With_Call<float64, 1>,
+ Compute_Select<float64, 1>, 1099);
+}
+
+
+void MixedParamTest(int start) {
+ if (RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->num_double_registers() < 2)
+ return;
+
+// TODO(titzer): mix in 64-bit types on all platforms when supported.
+#if V8_TARGET_ARCH_32_BIT
+ static MachineType types[] = {
+ MachineType::Int32(), MachineType::Float32(), MachineType::Float64(),
+ MachineType::Int32(), MachineType::Float64(), MachineType::Float32(),
+ MachineType::Float32(), MachineType::Float64(), MachineType::Int32(),
+ MachineType::Float32(), MachineType::Int32(), MachineType::Float64(),
+ MachineType::Float64(), MachineType::Float32(), MachineType::Int32(),
+ MachineType::Float64(), MachineType::Int32(), MachineType::Float32()};
+#else
+ static MachineType types[] = {
+ MachineType::Int32(), MachineType::Int64(), MachineType::Float32(),
+ MachineType::Float64(), MachineType::Int32(), MachineType::Float64(),
+ MachineType::Float32(), MachineType::Int64(), MachineType::Int64(),
+ MachineType::Float32(), MachineType::Float32(), MachineType::Int32(),
+ MachineType::Float64(), MachineType::Float64(), MachineType::Int64(),
+ MachineType::Int32(), MachineType::Float64(), MachineType::Int32(),
+ MachineType::Float32()};
+#endif
+
+ Isolate* isolate = CcTest::InitIsolateOnce();
+
+ // Build machine signature
+ MachineType* params = &types[start];
+ const int num_params = static_cast<int>(arraysize(types) - start);
+
+ // Build call descriptor
+ int parray_gp[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableGeneralCode(0),
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableGeneralCode(1)};
+ int rarray_gp[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableGeneralCode(0)};
+ int parray_fp[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableDoubleCode(0),
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableDoubleCode(1)};
+ int rarray_fp[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableDoubleCode(0)};
+ Allocator palloc(parray_gp, 2, parray_fp, 2);
+ Allocator ralloc(rarray_gp, 1, rarray_fp, 1);
+ RegisterConfig config(palloc, ralloc);
+
+ for (int which = 0; which < num_params; which++) {
+ Zone zone;
+ HandleScope scope(isolate);
+ MachineSignature::Builder builder(&zone, 1, num_params);
+ builder.AddReturn(params[which]);
+ for (int j = 0; j < num_params; j++) builder.AddParam(params[j]);
+ MachineSignature* sig = builder.Build();
+ CallDescriptor* desc = config.Create(&zone, sig);
+
+ Handle<Code> select;
+ {
+ // build the select.
+ Zone zone;
+ Graph graph(&zone);
+ RawMachineAssembler raw(isolate, &graph, desc);
+ raw.Return(raw.Parameter(which));
+ select = CompileGraph("Compute", desc, &graph, raw.Export());
+ }
+
+ {
+ // call the select.
+ Handle<Code> wrapper = Handle<Code>::null();
+ int32_t expected_ret;
+ char bytes[kDoubleSize];
+ V8_ALIGNED(8) char output[kDoubleSize];
+ int expected_size = 0;
+ CSignature0<int32_t> csig;
+ {
+ // Wrap the select code with a callable function that passes constants.
+ Zone zone;
+ Graph graph(&zone);
+ CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig);
+ RawMachineAssembler raw(isolate, &graph, cdesc);
+ Node* target = raw.HeapConstant(select);
+ Node** args = zone.NewArray<Node*>(num_params);
+ int64_t constant = 0x0102030405060708;
+ for (int i = 0; i < num_params; i++) {
+ MachineType param_type = sig->GetParam(i);
+ Node* konst = nullptr;
+ if (param_type == MachineType::Int32()) {
+ int32_t value[] = {static_cast<int32_t>(constant)};
+ konst = raw.Int32Constant(value[0]);
+ if (i == which) memcpy(bytes, value, expected_size = 4);
+ }
+ if (param_type == MachineType::Int64()) {
+ int64_t value[] = {static_cast<int64_t>(constant)};
+ konst = raw.Int64Constant(value[0]);
+ if (i == which) memcpy(bytes, value, expected_size = 8);
+ }
+ if (param_type == MachineType::Float32()) {
+ float32 value[] = {static_cast<float32>(constant)};
+ konst = raw.Float32Constant(value[0]);
+ if (i == which) memcpy(bytes, value, expected_size = 4);
+ }
+ if (param_type == MachineType::Float64()) {
+ float64 value[] = {static_cast<float64>(constant)};
+ konst = raw.Float64Constant(value[0]);
+ if (i == which) memcpy(bytes, value, expected_size = 8);
+ }
+ CHECK_NOT_NULL(konst);
+
+ args[i] = konst;
+ constant += 0x1010101010101010;
+ }
+
+ Node* call = raw.CallN(desc, target, args);
+ Node* store =
+ raw.StoreToPointer(output, sig->GetReturn().representation(), call);
+ USE(store);
+ expected_ret = static_cast<int32_t>(constant);
+ raw.Return(raw.Int32Constant(expected_ret));
+ wrapper = CompileGraph("Select-mixed-wrapper-const", cdesc, &graph,
+ raw.Export());
+ }
+
+ CodeRunner<int32_t> runnable(isolate, wrapper, &csig);
+ CHECK_EQ(expected_ret, runnable.Call());
+ for (int i = 0; i < expected_size; i++) {
+ CHECK_EQ(static_cast<int>(bytes[i]), static_cast<int>(output[i]));
+ }
+ }
+ }
+}
+
+
+TEST(MixedParams_0) { MixedParamTest(0); }
+TEST(MixedParams_1) { MixedParamTest(1); }
+TEST(MixedParams_2) { MixedParamTest(2); }
+TEST(MixedParams_3) { MixedParamTest(3); }
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-properties.cc b/test/cctest/compiler/test-run-properties.cc
index d4442f7..3c42102 100644
--- a/test/cctest/compiler/test-run-properties.cc
+++ b/test/cctest/compiler/test-run-properties.cc
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "test/cctest/compiler/function-tester.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
template <typename U>
static void TypedArrayLoadHelper(const char* array_type) {
@@ -21,16 +20,15 @@
values_builder.AddFormatted("a[%d] = 0x%08x;", i, kValues[i]);
}
- // Note that below source creates two different typed arrays with distinct
- // elements kind to get coverage for both access patterns:
- // - IsFixedTypedArrayElementsKind(x)
- // - IsExternalArrayElementsKind(y)
+ // Note that below source creates two different typed arrays with the same
+ // elements kind to get coverage for both (on heap / with external backing
+ // store) access patterns.
const char* source =
"(function(a) {"
" var x = (a = new %sArray(%d)); %s;"
" var y = (a = new %sArray(%d)); %s; %%TypedArrayGetBuffer(y);"
" if (!%%HasFixed%sElements(x)) %%AbortJS('x');"
- " if (!%%HasExternal%sElements(y)) %%AbortJS('y');"
+ " if (!%%HasFixed%sElements(y)) %%AbortJS('y');"
" function f(a,b) {"
" a = a | 0; b = b | 0;"
" return x[a] + y[b];"
@@ -42,9 +40,9 @@
values_buffer.start(), array_type, arraysize(kValues),
values_buffer.start(), array_type, array_type);
- FunctionTester T(
- source_buffer.start(),
- CompilationInfo::kContextSpecializing | CompilationInfo::kTypingEnabled);
+ FunctionTester T(source_buffer.start(),
+ CompilationInfo::kFunctionContextSpecializing |
+ CompilationInfo::kTypingEnabled);
for (size_t i = 0; i < arraysize(kValues); ++i) {
for (size_t j = 0; j < arraysize(kValues); ++j) {
volatile U value_a = static_cast<U>(kValues[i]);
@@ -84,16 +82,15 @@
values_builder.AddFormatted("a[%d] = 0x%08x;", i, kValues[i]);
}
- // Note that below source creates two different typed arrays with distinct
- // elements kind to get coverage for both access patterns:
- // - IsFixedTypedArrayElementsKind(x)
- // - IsExternalArrayElementsKind(y)
+ // Note that below source creates two different typed arrays with the same
+ // elements kind to get coverage for both (on heap/with external backing
+ // store) access patterns.
const char* source =
"(function(a) {"
" var x = (a = new %sArray(%d)); %s;"
" var y = (a = new %sArray(%d)); %s; %%TypedArrayGetBuffer(y);"
" if (!%%HasFixed%sElements(x)) %%AbortJS('x');"
- " if (!%%HasExternal%sElements(y)) %%AbortJS('y');"
+ " if (!%%HasFixed%sElements(y)) %%AbortJS('y');"
" function f(a,b) {"
" a = a | 0; b = b | 0;"
" var t = x[a];"
@@ -111,9 +108,9 @@
values_buffer.start(), array_type, arraysize(kValues),
values_buffer.start(), array_type, array_type);
- FunctionTester T(
- source_buffer.start(),
- CompilationInfo::kContextSpecializing | CompilationInfo::kTypingEnabled);
+ FunctionTester T(source_buffer.start(),
+ CompilationInfo::kFunctionContextSpecializing |
+ CompilationInfo::kTypingEnabled);
for (size_t i = 0; i < arraysize(kValues); ++i) {
for (size_t j = 0; j < arraysize(kValues); ++j) {
volatile U value_a = static_cast<U>(kValues[i]);
@@ -139,3 +136,7 @@
TypedArrayStoreHelper<double>("Float64");
// TODO(mstarzinger): Add tests for ClampedUint8.
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-stackcheck.cc b/test/cctest/compiler/test-run-stackcheck.cc
index 8c1664b..52556ac 100644
--- a/test/cctest/compiler/test-run-stackcheck.cc
+++ b/test/cctest/compiler/test-run-stackcheck.cc
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "test/cctest/compiler/function-tester.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
TEST(TerminateAtMethodEntry) {
FunctionTester T("(function(a,b) { return 23; })");
@@ -16,3 +15,7 @@
T.isolate->stack_guard()->RequestTerminateExecution();
T.CheckThrows(T.undefined(), T.undefined());
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-stubs.cc b/test/cctest/compiler/test-run-stubs.cc
new file mode 100644
index 0000000..7a2a094
--- /dev/null
+++ b/test/cctest/compiler/test-run-stubs.cc
@@ -0,0 +1,69 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/bootstrapper.h"
+#include "src/code-stubs.h"
+#include "src/compiler/common-operator.h"
+#include "src/compiler/graph.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/js-operator.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/machine-operator.h"
+#include "src/compiler/pipeline.h"
+#include "src/parsing/parser.h"
+#include "test/cctest/compiler/function-tester.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+
+TEST(RunStringLengthStub) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+
+ // Create code and an accompanying descriptor.
+ StringLengthStub stub(isolate);
+ Handle<Code> code = stub.GenerateCode();
+ CompilationInfo info(&stub, isolate, zone);
+ CallDescriptor* descriptor = Linkage::ComputeIncoming(zone, &info);
+
+ // Create a function to call the code using the descriptor.
+ Graph graph(zone);
+ CommonOperatorBuilder common(zone);
+ // FunctionTester (ab)uses a 4-argument function
+ Node* start = graph.NewNode(common.Start(6));
+ // Parameter 0 is the receiver
+ Node* receiverParam = graph.NewNode(common.Parameter(1), start);
+ Node* nameParam = graph.NewNode(common.Parameter(2), start);
+ Node* slotParam = graph.NewNode(common.Parameter(3), start);
+ Node* vectorParam = graph.NewNode(common.Parameter(4), start);
+ Node* theCode = graph.NewNode(common.HeapConstant(code));
+ Node* dummyContext = graph.NewNode(common.NumberConstant(0.0));
+ Node* call =
+ graph.NewNode(common.Call(descriptor), theCode, receiverParam, nameParam,
+ slotParam, vectorParam, dummyContext, start, start);
+ Node* ret = graph.NewNode(common.Return(), call, call, start);
+ Node* end = graph.NewNode(common.End(1), ret);
+ graph.SetStart(start);
+ graph.SetEnd(end);
+ FunctionTester ft(&graph, 4);
+
+ // Actuall call through to the stub, verifying its result.
+ const char* testString = "Und das Lamm schrie HURZ!";
+ Handle<JSReceiver> receiverArg =
+ Object::ToObject(isolate, ft.Val(testString)).ToHandleChecked();
+ Handle<String> nameArg = ft.Val("length");
+ Handle<Object> slot = ft.Val(0.0);
+ Handle<Object> vector = ft.Val(0.0);
+ Handle<Object> result =
+ ft.Call(receiverArg, nameArg, slot, vector).ToHandleChecked();
+ CHECK_EQ(static_cast<int>(strlen(testString)), Smi::cast(*result)->value());
+}
+
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-run-variables.cc b/test/cctest/compiler/test-run-variables.cc
index bf86e0d..f856368 100644
--- a/test/cctest/compiler/test-run-variables.cc
+++ b/test/cctest/compiler/test-run-variables.cc
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "test/cctest/compiler/function-tester.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
static const char* throws = NULL;
@@ -49,7 +48,7 @@
static void RunVariableTests(const char* source, const char* tests[]) {
- FLAG_harmony_scoping = true;
+ i::FLAG_legacy_const = true;
EmbeddedVector<char, 512> buffer;
for (int i = 0; tests[i] != NULL; i += 3) {
@@ -119,3 +118,7 @@
CompileRun("var self = 'not a function'");
T.CheckCall(T.function);
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-schedule.cc b/test/cctest/compiler/test-schedule.cc
deleted file mode 100644
index 1eb3547..0000000
--- a/test/cctest/compiler/test-schedule.cc
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-
-#include "src/compiler/common-operator.h"
-#include "src/compiler/graph.h"
-#include "src/compiler/machine-operator.h"
-#include "src/compiler/node.h"
-#include "src/compiler/operator.h"
-#include "src/compiler/schedule.h"
-#include "test/cctest/cctest.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
- "dummy", 0, 0, 0, 0, 0, 0);
-
-TEST(TestScheduleAllocation) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- CHECK_NE(NULL, schedule.start());
- CHECK_EQ(schedule.start(), schedule.GetBlockById(BasicBlock::Id::FromInt(0)));
-}
-
-
-TEST(TestScheduleAddNode) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Graph graph(scope.main_zone());
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
-
- BasicBlock* entry = schedule.start();
- schedule.AddNode(entry, n0);
- schedule.AddNode(entry, n1);
-
- CHECK_EQ(entry, schedule.block(n0));
- CHECK_EQ(entry, schedule.block(n1));
- CHECK(schedule.SameBasicBlock(n0, n1));
-
- Node* n2 = graph.NewNode(&dummy_operator);
- CHECK_EQ(NULL, schedule.block(n2));
-}
-
-
-TEST(TestScheduleAddGoto) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- BasicBlock* entry = schedule.start();
- BasicBlock* next = schedule.NewBasicBlock();
-
- schedule.AddGoto(entry, next);
-
- CHECK_EQ(0, static_cast<int>(entry->PredecessorCount()));
- CHECK_EQ(1, static_cast<int>(entry->SuccessorCount()));
- CHECK_EQ(next, entry->SuccessorAt(0));
-
- CHECK_EQ(1, static_cast<int>(next->PredecessorCount()));
- CHECK_EQ(entry, next->PredecessorAt(0));
- CHECK_EQ(0, static_cast<int>(next->SuccessorCount()));
-}
-
-
-TEST(TestScheduleAddBranch) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* b = graph.NewNode(common.Branch(), n0);
-
- BasicBlock* entry = schedule.start();
- BasicBlock* tblock = schedule.NewBasicBlock();
- BasicBlock* fblock = schedule.NewBasicBlock();
-
- schedule.AddBranch(entry, b, tblock, fblock);
-
- CHECK_EQ(0, static_cast<int>(entry->PredecessorCount()));
- CHECK_EQ(2, static_cast<int>(entry->SuccessorCount()));
- CHECK_EQ(tblock, entry->SuccessorAt(0));
- CHECK_EQ(fblock, entry->SuccessorAt(1));
-
- CHECK_EQ(1, static_cast<int>(tblock->PredecessorCount()));
- CHECK_EQ(entry, tblock->PredecessorAt(0));
- CHECK_EQ(0, static_cast<int>(tblock->SuccessorCount()));
-
- CHECK_EQ(1, static_cast<int>(fblock->PredecessorCount()));
- CHECK_EQ(entry, fblock->PredecessorAt(0));
- CHECK_EQ(0, static_cast<int>(fblock->SuccessorCount()));
-}
-
-
-TEST(TestScheduleAddReturn) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Graph graph(scope.main_zone());
- Node* n0 = graph.NewNode(&dummy_operator);
- BasicBlock* entry = schedule.start();
- schedule.AddReturn(entry, n0);
-
- CHECK_EQ(0, static_cast<int>(entry->PredecessorCount()));
- CHECK_EQ(1, static_cast<int>(entry->SuccessorCount()));
- CHECK_EQ(schedule.end(), entry->SuccessorAt(0));
-}
-
-
-TEST(TestScheduleAddThrow) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Graph graph(scope.main_zone());
- Node* n0 = graph.NewNode(&dummy_operator);
- BasicBlock* entry = schedule.start();
- schedule.AddThrow(entry, n0);
-
- CHECK_EQ(0, static_cast<int>(entry->PredecessorCount()));
- CHECK_EQ(1, static_cast<int>(entry->SuccessorCount()));
- CHECK_EQ(schedule.end(), entry->SuccessorAt(0));
-}
-
-
-TEST(TestScheduleInsertBranch) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* b = graph.NewNode(common.Branch(), n1);
-
- BasicBlock* entry = schedule.start();
- BasicBlock* tblock = schedule.NewBasicBlock();
- BasicBlock* fblock = schedule.NewBasicBlock();
- BasicBlock* merge = schedule.NewBasicBlock();
- schedule.AddReturn(entry, n0);
- schedule.AddGoto(tblock, merge);
- schedule.AddGoto(fblock, merge);
-
- schedule.InsertBranch(entry, merge, b, tblock, fblock);
-
- CHECK_EQ(0, static_cast<int>(entry->PredecessorCount()));
- CHECK_EQ(2, static_cast<int>(entry->SuccessorCount()));
- CHECK_EQ(tblock, entry->SuccessorAt(0));
- CHECK_EQ(fblock, entry->SuccessorAt(1));
-
- CHECK_EQ(2, static_cast<int>(merge->PredecessorCount()));
- CHECK_EQ(1, static_cast<int>(merge->SuccessorCount()));
- CHECK_EQ(schedule.end(), merge->SuccessorAt(0));
-
- CHECK_EQ(1, static_cast<int>(schedule.end()->PredecessorCount()));
- CHECK_EQ(0, static_cast<int>(schedule.end()->SuccessorCount()));
- CHECK_EQ(merge, schedule.end()->PredecessorAt(0));
-}
-
-
-TEST(BuildMulNodeGraph) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
- // TODO(titzer): use test operators.
- MachineOperatorBuilder machine(scope.main_zone());
-
- Node* start = graph.NewNode(common.Start(0));
- graph.SetStart(start);
- Node* param0 = graph.NewNode(common.Parameter(0), graph.start());
- Node* param1 = graph.NewNode(common.Parameter(1), graph.start());
-
- Node* mul = graph.NewNode(machine.Int32Mul(), param0, param1);
- Node* ret = graph.NewNode(common.Return(), mul, start);
-
- USE(ret);
-}
diff --git a/test/cctest/compiler/test-scheduler.cc b/test/cctest/compiler/test-scheduler.cc
deleted file mode 100644
index 1b79ed5..0000000
--- a/test/cctest/compiler/test-scheduler.cc
+++ /dev/null
@@ -1,2124 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-
-#include "src/compiler/access-builder.h"
-#include "src/compiler/common-operator.h"
-#include "src/compiler/graph.h"
-#include "src/compiler/graph-visualizer.h"
-#include "src/compiler/js-operator.h"
-#include "src/compiler/node.h"
-#include "src/compiler/opcodes.h"
-#include "src/compiler/operator.h"
-#include "src/compiler/schedule.h"
-#include "src/compiler/scheduler.h"
-#include "src/compiler/simplified-operator.h"
-#include "src/compiler/verifier.h"
-#include "test/cctest/cctest.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0, 0, 1,
- 0, 0);
-
-// TODO(titzer): pull RPO tests out to their own file.
-static void CheckRPONumbers(BasicBlockVector* order, size_t expected,
- bool loops_allowed) {
- CHECK(expected == order->size());
- for (int i = 0; i < static_cast<int>(order->size()); i++) {
- CHECK(order->at(i)->rpo_number() == i);
- if (!loops_allowed) {
- CHECK_EQ(NULL, order->at(i)->loop_end());
- CHECK_EQ(NULL, order->at(i)->loop_header());
- }
- }
-}
-
-
-static void CheckLoop(BasicBlockVector* order, BasicBlock** blocks,
- int body_size) {
- BasicBlock* header = blocks[0];
- BasicBlock* end = header->loop_end();
- CHECK_NE(NULL, end);
- CHECK_GT(end->rpo_number(), 0);
- CHECK_EQ(body_size, end->rpo_number() - header->rpo_number());
- for (int i = 0; i < body_size; i++) {
- CHECK_GE(blocks[i]->rpo_number(), header->rpo_number());
- CHECK_LT(blocks[i]->rpo_number(), end->rpo_number());
- CHECK(header->LoopContains(blocks[i]));
- CHECK(header->IsLoopHeader() || blocks[i]->loop_header() == header);
- }
- if (header->rpo_number() > 0) {
- CHECK_NE(order->at(header->rpo_number() - 1)->loop_header(), header);
- }
- if (end->rpo_number() < static_cast<int>(order->size())) {
- CHECK_NE(order->at(end->rpo_number())->loop_header(), header);
- }
-}
-
-
-struct TestLoop {
- int count;
- BasicBlock** nodes;
- BasicBlock* header() { return nodes[0]; }
- BasicBlock* last() { return nodes[count - 1]; }
- ~TestLoop() { delete[] nodes; }
-
- void Check(BasicBlockVector* order) { CheckLoop(order, nodes, count); }
-};
-
-
-static TestLoop* CreateLoop(Schedule* schedule, int count) {
- TestLoop* loop = new TestLoop();
- loop->count = count;
- loop->nodes = new BasicBlock* [count];
- for (int i = 0; i < count; i++) {
- loop->nodes[i] = schedule->NewBasicBlock();
- if (i > 0) {
- schedule->AddSuccessorForTesting(loop->nodes[i - 1], loop->nodes[i]);
- }
- }
- schedule->AddSuccessorForTesting(loop->nodes[count - 1], loop->nodes[0]);
- return loop;
-}
-
-
-static int GetScheduledNodeCount(Schedule* schedule) {
- int node_count = 0;
- for (BasicBlockVectorIter i = schedule->rpo_order()->begin();
- i != schedule->rpo_order()->end(); ++i) {
- BasicBlock* block = *i;
- for (BasicBlock::const_iterator j = block->begin(); j != block->end();
- ++j) {
- ++node_count;
- }
- BasicBlock::Control control = block->control();
- if (control != BasicBlock::kNone) {
- ++node_count;
- }
- }
- return node_count;
-}
-
-
-static Schedule* ComputeAndVerifySchedule(int expected, Graph* graph) {
- if (FLAG_trace_turbo) {
- OFStream os(stdout);
- os << AsDOT(*graph);
- }
-
- Schedule* schedule = Scheduler::ComputeSchedule(graph->zone(), graph);
-
- if (FLAG_trace_turbo_scheduler) {
- OFStream os(stdout);
- os << *schedule << std::endl;
- }
- ScheduleVerifier::Run(schedule);
- CHECK_EQ(expected, GetScheduledNodeCount(schedule));
- return schedule;
-}
-
-
-TEST(RPODegenerate1) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, 1, false);
- CHECK_EQ(schedule.start(), order->at(0));
-}
-
-
-TEST(RPODegenerate2) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- schedule.AddGoto(schedule.start(), schedule.end());
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, 2, false);
- CHECK_EQ(schedule.start(), order->at(0));
- CHECK_EQ(schedule.end(), order->at(1));
-}
-
-
-TEST(RPOLine) {
- HandleAndZoneScope scope;
-
- for (int i = 0; i < 10; i++) {
- Schedule schedule(scope.main_zone());
-
- BasicBlock* last = schedule.start();
- for (int j = 0; j < i; j++) {
- BasicBlock* block = schedule.NewBasicBlock();
- block->set_deferred(i & 1);
- schedule.AddGoto(last, block);
- last = block;
- }
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, 1 + i, false);
-
- for (size_t i = 0; i < schedule.BasicBlockCount(); i++) {
- BasicBlock* block = schedule.GetBlockById(BasicBlock::Id::FromSize(i));
- if (block->rpo_number() >= 0 && block->SuccessorCount() == 1) {
- CHECK(block->rpo_number() + 1 == block->SuccessorAt(0)->rpo_number());
- }
- }
- }
-}
-
-
-TEST(RPOSelfLoop) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- schedule.AddSuccessorForTesting(schedule.start(), schedule.start());
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, 1, true);
- BasicBlock* loop[] = {schedule.start()};
- CheckLoop(order, loop, 1);
-}
-
-
-TEST(RPOEntryLoop) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- BasicBlock* body = schedule.NewBasicBlock();
- schedule.AddSuccessorForTesting(schedule.start(), body);
- schedule.AddSuccessorForTesting(body, schedule.start());
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, 2, true);
- BasicBlock* loop[] = {schedule.start(), body};
- CheckLoop(order, loop, 2);
-}
-
-
-TEST(RPOEndLoop) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2));
- schedule.AddSuccessorForTesting(schedule.start(), loop1->header());
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, 3, true);
- loop1->Check(order);
-}
-
-
-TEST(RPOEndLoopNested) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2));
- schedule.AddSuccessorForTesting(schedule.start(), loop1->header());
- schedule.AddSuccessorForTesting(loop1->last(), schedule.start());
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, 3, true);
- loop1->Check(order);
-}
-
-
-TEST(RPODiamond) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.end();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(A, C);
- schedule.AddSuccessorForTesting(B, D);
- schedule.AddSuccessorForTesting(C, D);
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, 4, false);
-
- CHECK_EQ(0, A->rpo_number());
- CHECK((B->rpo_number() == 1 && C->rpo_number() == 2) ||
- (B->rpo_number() == 2 && C->rpo_number() == 1));
- CHECK_EQ(3, D->rpo_number());
-}
-
-
-TEST(RPOLoop1) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.end();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(B, C);
- schedule.AddSuccessorForTesting(C, B);
- schedule.AddSuccessorForTesting(C, D);
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, 4, true);
- BasicBlock* loop[] = {B, C};
- CheckLoop(order, loop, 2);
-}
-
-
-TEST(RPOLoop2) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.end();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(B, C);
- schedule.AddSuccessorForTesting(C, B);
- schedule.AddSuccessorForTesting(B, D);
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, 4, true);
- BasicBlock* loop[] = {B, C};
- CheckLoop(order, loop, 2);
-}
-
-
-TEST(RPOLoopN) {
- HandleAndZoneScope scope;
-
- for (int i = 0; i < 11; i++) {
- Schedule schedule(scope.main_zone());
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.NewBasicBlock();
- BasicBlock* E = schedule.NewBasicBlock();
- BasicBlock* F = schedule.NewBasicBlock();
- BasicBlock* G = schedule.end();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(B, C);
- schedule.AddSuccessorForTesting(C, D);
- schedule.AddSuccessorForTesting(D, E);
- schedule.AddSuccessorForTesting(E, F);
- schedule.AddSuccessorForTesting(F, B);
- schedule.AddSuccessorForTesting(B, G);
-
- // Throw in extra backedges from time to time.
- if (i == 1) schedule.AddSuccessorForTesting(B, B);
- if (i == 2) schedule.AddSuccessorForTesting(C, B);
- if (i == 3) schedule.AddSuccessorForTesting(D, B);
- if (i == 4) schedule.AddSuccessorForTesting(E, B);
- if (i == 5) schedule.AddSuccessorForTesting(F, B);
-
- // Throw in extra loop exits from time to time.
- if (i == 6) schedule.AddSuccessorForTesting(B, G);
- if (i == 7) schedule.AddSuccessorForTesting(C, G);
- if (i == 8) schedule.AddSuccessorForTesting(D, G);
- if (i == 9) schedule.AddSuccessorForTesting(E, G);
- if (i == 10) schedule.AddSuccessorForTesting(F, G);
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, 7, true);
- BasicBlock* loop[] = {B, C, D, E, F};
- CheckLoop(order, loop, 5);
- }
-}
-
-
-TEST(RPOLoopNest1) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.NewBasicBlock();
- BasicBlock* E = schedule.NewBasicBlock();
- BasicBlock* F = schedule.end();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(B, C);
- schedule.AddSuccessorForTesting(C, D);
- schedule.AddSuccessorForTesting(D, C);
- schedule.AddSuccessorForTesting(D, E);
- schedule.AddSuccessorForTesting(E, B);
- schedule.AddSuccessorForTesting(E, F);
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, 6, true);
- BasicBlock* loop1[] = {B, C, D, E};
- CheckLoop(order, loop1, 4);
-
- BasicBlock* loop2[] = {C, D};
- CheckLoop(order, loop2, 2);
-}
-
-
-TEST(RPOLoopNest2) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.NewBasicBlock();
- BasicBlock* E = schedule.NewBasicBlock();
- BasicBlock* F = schedule.NewBasicBlock();
- BasicBlock* G = schedule.NewBasicBlock();
- BasicBlock* H = schedule.end();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(B, C);
- schedule.AddSuccessorForTesting(C, D);
- schedule.AddSuccessorForTesting(D, E);
- schedule.AddSuccessorForTesting(E, F);
- schedule.AddSuccessorForTesting(F, G);
- schedule.AddSuccessorForTesting(G, H);
-
- schedule.AddSuccessorForTesting(E, D);
- schedule.AddSuccessorForTesting(F, C);
- schedule.AddSuccessorForTesting(G, B);
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, 8, true);
- BasicBlock* loop1[] = {B, C, D, E, F, G};
- CheckLoop(order, loop1, 6);
-
- BasicBlock* loop2[] = {C, D, E, F};
- CheckLoop(order, loop2, 4);
-
- BasicBlock* loop3[] = {D, E};
- CheckLoop(order, loop3, 2);
-}
-
-
-TEST(RPOLoopFollow1) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
- SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
-
- BasicBlock* A = schedule.start();
- BasicBlock* E = schedule.end();
-
- schedule.AddSuccessorForTesting(A, loop1->header());
- schedule.AddSuccessorForTesting(loop1->header(), loop2->header());
- schedule.AddSuccessorForTesting(loop2->last(), E);
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
-
- CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()),
- static_cast<int>(order->size()));
-
- loop1->Check(order);
- loop2->Check(order);
-}
-
-
-TEST(RPOLoopFollow2) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
- SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
-
- BasicBlock* A = schedule.start();
- BasicBlock* S = schedule.NewBasicBlock();
- BasicBlock* E = schedule.end();
-
- schedule.AddSuccessorForTesting(A, loop1->header());
- schedule.AddSuccessorForTesting(loop1->header(), S);
- schedule.AddSuccessorForTesting(S, loop2->header());
- schedule.AddSuccessorForTesting(loop2->last(), E);
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
-
- CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()),
- static_cast<int>(order->size()));
- loop1->Check(order);
- loop2->Check(order);
-}
-
-
-TEST(RPOLoopFollowN) {
- HandleAndZoneScope scope;
-
- for (int size = 1; size < 5; size++) {
- for (int exit = 0; exit < size; exit++) {
- Schedule schedule(scope.main_zone());
- SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
- SmartPointer<TestLoop> loop2(CreateLoop(&schedule, size));
- BasicBlock* A = schedule.start();
- BasicBlock* E = schedule.end();
-
- schedule.AddSuccessorForTesting(A, loop1->header());
- schedule.AddSuccessorForTesting(loop1->nodes[exit], loop2->header());
- schedule.AddSuccessorForTesting(loop2->nodes[exit], E);
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
-
- CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()),
- static_cast<int>(order->size()));
- loop1->Check(order);
- loop2->Check(order);
- }
- }
-}
-
-
-TEST(RPONestedLoopFollow1) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
- SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
-
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* E = schedule.end();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(B, loop1->header());
- schedule.AddSuccessorForTesting(loop1->header(), loop2->header());
- schedule.AddSuccessorForTesting(loop2->last(), C);
- schedule.AddSuccessorForTesting(C, E);
- schedule.AddSuccessorForTesting(C, B);
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
-
- CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()),
- static_cast<int>(order->size()));
- loop1->Check(order);
- loop2->Check(order);
-
- BasicBlock* loop3[] = {B, loop1->nodes[0], loop2->nodes[0], C};
- CheckLoop(order, loop3, 4);
-}
-
-
-TEST(RPOLoopBackedges1) {
- HandleAndZoneScope scope;
-
- int size = 8;
- for (int i = 0; i < size; i++) {
- for (int j = 0; j < size; j++) {
- Schedule schedule(scope.main_zone());
- BasicBlock* A = schedule.start();
- BasicBlock* E = schedule.end();
-
- SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
- schedule.AddSuccessorForTesting(A, loop1->header());
- schedule.AddSuccessorForTesting(loop1->last(), E);
-
- schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header());
- schedule.AddSuccessorForTesting(loop1->nodes[j], E);
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- loop1->Check(order);
- }
- }
-}
-
-
-TEST(RPOLoopOutedges1) {
- HandleAndZoneScope scope;
-
- int size = 8;
- for (int i = 0; i < size; i++) {
- for (int j = 0; j < size; j++) {
- Schedule schedule(scope.main_zone());
- BasicBlock* A = schedule.start();
- BasicBlock* D = schedule.NewBasicBlock();
- BasicBlock* E = schedule.end();
-
- SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
- schedule.AddSuccessorForTesting(A, loop1->header());
- schedule.AddSuccessorForTesting(loop1->last(), E);
-
- schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header());
- schedule.AddSuccessorForTesting(loop1->nodes[j], D);
- schedule.AddSuccessorForTesting(D, E);
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- loop1->Check(order);
- }
- }
-}
-
-
-TEST(RPOLoopOutedges2) {
- HandleAndZoneScope scope;
-
- int size = 8;
- for (int i = 0; i < size; i++) {
- Schedule schedule(scope.main_zone());
- BasicBlock* A = schedule.start();
- BasicBlock* E = schedule.end();
-
- SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
- schedule.AddSuccessorForTesting(A, loop1->header());
- schedule.AddSuccessorForTesting(loop1->last(), E);
-
- for (int j = 0; j < size; j++) {
- BasicBlock* O = schedule.NewBasicBlock();
- schedule.AddSuccessorForTesting(loop1->nodes[j], O);
- schedule.AddSuccessorForTesting(O, E);
- }
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- loop1->Check(order);
- }
-}
-
-
-TEST(RPOLoopOutloops1) {
- HandleAndZoneScope scope;
-
- int size = 8;
- for (int i = 0; i < size; i++) {
- Schedule schedule(scope.main_zone());
- BasicBlock* A = schedule.start();
- BasicBlock* E = schedule.end();
- SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
- schedule.AddSuccessorForTesting(A, loop1->header());
- schedule.AddSuccessorForTesting(loop1->last(), E);
-
- TestLoop** loopN = new TestLoop* [size];
- for (int j = 0; j < size; j++) {
- loopN[j] = CreateLoop(&schedule, 2);
- schedule.AddSuccessorForTesting(loop1->nodes[j], loopN[j]->header());
- schedule.AddSuccessorForTesting(loopN[j]->last(), E);
- }
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- loop1->Check(order);
-
- for (int j = 0; j < size; j++) {
- loopN[j]->Check(order);
- delete loopN[j];
- }
- delete[] loopN;
- }
-}
-
-
-TEST(RPOLoopMultibackedge) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- BasicBlock* A = schedule.start();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.NewBasicBlock();
- BasicBlock* E = schedule.NewBasicBlock();
-
- schedule.AddSuccessorForTesting(A, B);
- schedule.AddSuccessorForTesting(B, C);
- schedule.AddSuccessorForTesting(B, D);
- schedule.AddSuccessorForTesting(B, E);
- schedule.AddSuccessorForTesting(C, B);
- schedule.AddSuccessorForTesting(D, B);
- schedule.AddSuccessorForTesting(E, B);
-
- BasicBlockVector* order =
- Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule);
- CheckRPONumbers(order, 5, true);
-
- BasicBlock* loop1[] = {B, C, D, E};
- CheckLoop(order, loop1, 4);
-}
-
-
-TEST(BuildScheduleEmpty) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder builder(scope.main_zone());
- graph.SetStart(graph.NewNode(builder.Start(0)));
- graph.SetEnd(graph.NewNode(builder.End(), graph.start()));
-
- USE(Scheduler::ComputeSchedule(scope.main_zone(), &graph));
-}
-
-
-TEST(BuildScheduleOneParameter) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder builder(scope.main_zone());
- graph.SetStart(graph.NewNode(builder.Start(0)));
-
- Node* p1 = graph.NewNode(builder.Parameter(0), graph.start());
- Node* ret = graph.NewNode(builder.Return(), p1, graph.start(), graph.start());
-
- graph.SetEnd(graph.NewNode(builder.End(), ret));
-
- USE(Scheduler::ComputeSchedule(scope.main_zone(), &graph));
-}
-
-
-TEST(BuildScheduleIfSplit) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder builder(scope.main_zone());
- JSOperatorBuilder js_builder(scope.main_zone());
- graph.SetStart(graph.NewNode(builder.Start(3)));
-
- Node* p1 = graph.NewNode(builder.Parameter(0), graph.start());
- Node* p2 = graph.NewNode(builder.Parameter(1), graph.start());
- Node* p3 = graph.NewNode(builder.Parameter(2), graph.start());
- Node* p4 = graph.NewNode(builder.Parameter(3), graph.start());
- Node* p5 = graph.NewNode(builder.Parameter(4), graph.start());
- Node* cmp = graph.NewNode(js_builder.LessThanOrEqual(), p1, p2, p3,
- graph.start(), graph.start());
- Node* branch = graph.NewNode(builder.Branch(), cmp, graph.start());
- Node* true_branch = graph.NewNode(builder.IfTrue(), branch);
- Node* false_branch = graph.NewNode(builder.IfFalse(), branch);
-
- Node* ret1 = graph.NewNode(builder.Return(), p4, graph.start(), true_branch);
- Node* ret2 = graph.NewNode(builder.Return(), p5, graph.start(), false_branch);
- Node* merge = graph.NewNode(builder.Merge(2), ret1, ret2);
- graph.SetEnd(graph.NewNode(builder.End(), merge));
-
- ComputeAndVerifySchedule(13, &graph);
-}
-
-
-TEST(BuildScheduleIfSplitWithEffects) {
- HandleAndZoneScope scope;
- Isolate* isolate = scope.main_isolate();
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common_builder(scope.main_zone());
- JSOperatorBuilder js_builder(scope.main_zone());
- const Operator* op;
-
- Handle<HeapObject> object =
- Handle<HeapObject>(isolate->heap()->undefined_value(), isolate);
- Unique<HeapObject> unique_constant =
- Unique<HeapObject>::CreateUninitialized(object);
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b, c, y) {
- // if (a < b) {
- // return a + b - c * c - a + y;
- // } else {
- // return c * c - a;
- // }
- // }
- op = common_builder.Start(0);
- Node* n0 = graph.NewNode(op);
- USE(n0);
- Node* nil = graph.NewNode(common_builder.Dead());
- op = common_builder.End();
- Node* n23 = graph.NewNode(op, nil);
- USE(n23);
- op = common_builder.Merge(2);
- Node* n22 = graph.NewNode(op, nil, nil);
- USE(n22);
- op = common_builder.Return();
- Node* n16 = graph.NewNode(op, nil, nil, nil);
- USE(n16);
- op = js_builder.Add();
- Node* n15 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n15);
- op = js_builder.Subtract();
- Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n14);
- op = js_builder.Subtract();
- Node* n13 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n13);
- op = js_builder.Add();
- Node* n11 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n11);
- op = common_builder.Parameter(0);
- Node* n2 = graph.NewNode(op, n0);
- USE(n2);
- n11->ReplaceInput(0, n2);
- op = common_builder.Parameter(0);
- Node* n3 = graph.NewNode(op, n0);
- USE(n3);
- n11->ReplaceInput(1, n3);
- op = common_builder.HeapConstant(unique_constant);
- Node* n7 = graph.NewNode(op);
- USE(n7);
- n11->ReplaceInput(2, n7);
- op = js_builder.LessThan();
- Node* n8 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n8);
- n8->ReplaceInput(0, n2);
- n8->ReplaceInput(1, n3);
- n8->ReplaceInput(2, n7);
- n8->ReplaceInput(3, n0);
- n8->ReplaceInput(4, n0);
- n11->ReplaceInput(3, n8);
- op = common_builder.IfTrue();
- Node* n10 = graph.NewNode(op, nil);
- USE(n10);
- op = common_builder.Branch();
- Node* n9 = graph.NewNode(op, nil, nil);
- USE(n9);
- n9->ReplaceInput(0, n8);
- n9->ReplaceInput(1, n0);
- n10->ReplaceInput(0, n9);
- n11->ReplaceInput(4, n10);
- n13->ReplaceInput(0, n11);
- op = js_builder.Multiply();
- Node* n12 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n12);
- op = common_builder.Parameter(0);
- Node* n4 = graph.NewNode(op, n0);
- USE(n4);
- n12->ReplaceInput(0, n4);
- n12->ReplaceInput(1, n4);
- n12->ReplaceInput(2, n7);
- n12->ReplaceInput(3, n11);
- n12->ReplaceInput(4, n10);
- n13->ReplaceInput(1, n12);
- n13->ReplaceInput(2, n7);
- n13->ReplaceInput(3, n12);
- n13->ReplaceInput(4, n10);
- n14->ReplaceInput(0, n13);
- n14->ReplaceInput(1, n2);
- n14->ReplaceInput(2, n7);
- n14->ReplaceInput(3, n13);
- n14->ReplaceInput(4, n10);
- n15->ReplaceInput(0, n14);
- op = common_builder.Parameter(0);
- Node* n5 = graph.NewNode(op, n0);
- USE(n5);
- n15->ReplaceInput(1, n5);
- n15->ReplaceInput(2, n7);
- n15->ReplaceInput(3, n14);
- n15->ReplaceInput(4, n10);
- n16->ReplaceInput(0, n15);
- n16->ReplaceInput(1, n15);
- n16->ReplaceInput(2, n10);
- n22->ReplaceInput(0, n16);
- op = common_builder.Return();
- Node* n21 = graph.NewNode(op, nil, nil, nil);
- USE(n21);
- op = js_builder.Subtract();
- Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n20);
- op = js_builder.Multiply();
- Node* n19 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n19);
- n19->ReplaceInput(0, n4);
- n19->ReplaceInput(1, n4);
- n19->ReplaceInput(2, n7);
- n19->ReplaceInput(3, n8);
- op = common_builder.IfFalse();
- Node* n18 = graph.NewNode(op, nil);
- USE(n18);
- n18->ReplaceInput(0, n9);
- n19->ReplaceInput(4, n18);
- n20->ReplaceInput(0, n19);
- n20->ReplaceInput(1, n2);
- n20->ReplaceInput(2, n7);
- n20->ReplaceInput(3, n19);
- n20->ReplaceInput(4, n18);
- n21->ReplaceInput(0, n20);
- n21->ReplaceInput(1, n20);
- n21->ReplaceInput(2, n18);
- n22->ReplaceInput(1, n21);
- n23->ReplaceInput(0, n22);
-
- graph.SetStart(n0);
- graph.SetEnd(n23);
-
- ComputeAndVerifySchedule(20, &graph);
-}
-
-
-TEST(BuildScheduleSimpleLoop) {
- HandleAndZoneScope scope;
- Isolate* isolate = scope.main_isolate();
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common_builder(scope.main_zone());
- JSOperatorBuilder js_builder(scope.main_zone());
- const Operator* op;
-
- Handle<HeapObject> object =
- Handle<HeapObject>(isolate->heap()->undefined_value(), isolate);
- Unique<HeapObject> unique_constant =
- Unique<HeapObject>::CreateUninitialized(object);
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b) {
- // while (a < b) {
- // a++;
- // }
- // return a;
- // }
- op = common_builder.Start(0);
- Node* n0 = graph.NewNode(op);
- USE(n0);
- Node* nil = graph.NewNode(common_builder.Dead());
- op = common_builder.End();
- Node* n20 = graph.NewNode(op, nil);
- USE(n20);
- op = common_builder.Return();
- Node* n19 = graph.NewNode(op, nil, nil, nil);
- USE(n19);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n8 = graph.NewNode(op, nil, nil, nil);
- USE(n8);
- op = common_builder.Parameter(0);
- Node* n2 = graph.NewNode(op, n0);
- USE(n2);
- n8->ReplaceInput(0, n2);
- op = js_builder.Add();
- Node* n18 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n18);
- op = js_builder.ToNumber();
- Node* n16 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n16);
- n16->ReplaceInput(0, n8);
- op = common_builder.HeapConstant(unique_constant);
- Node* n5 = graph.NewNode(op);
- USE(n5);
- n16->ReplaceInput(1, n5);
- op = js_builder.LessThan();
- Node* n12 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n12);
- n12->ReplaceInput(0, n8);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n9 = graph.NewNode(op, nil, nil, nil);
- USE(n9);
- op = common_builder.Parameter(0);
- Node* n3 = graph.NewNode(op, n0);
- USE(n3);
- n9->ReplaceInput(0, n3);
- n9->ReplaceInput(1, n9);
- op = common_builder.Loop(2);
- Node* n6 = graph.NewNode(op, nil, nil);
- USE(n6);
- n6->ReplaceInput(0, n0);
- op = common_builder.IfTrue();
- Node* n14 = graph.NewNode(op, nil);
- USE(n14);
- op = common_builder.Branch();
- Node* n13 = graph.NewNode(op, nil, nil);
- USE(n13);
- n13->ReplaceInput(0, n12);
- n13->ReplaceInput(1, n6);
- n14->ReplaceInput(0, n13);
- n6->ReplaceInput(1, n14);
- n9->ReplaceInput(2, n6);
- n12->ReplaceInput(1, n9);
- n12->ReplaceInput(2, n5);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n10 = graph.NewNode(op, nil, nil, nil);
- USE(n10);
- n10->ReplaceInput(0, n0);
- n10->ReplaceInput(1, n18);
- n10->ReplaceInput(2, n6);
- n12->ReplaceInput(3, n10);
- n12->ReplaceInput(4, n6);
- n16->ReplaceInput(2, n12);
- n16->ReplaceInput(3, n14);
- n18->ReplaceInput(0, n16);
- op = common_builder.NumberConstant(0);
- Node* n17 = graph.NewNode(op);
- USE(n17);
- n18->ReplaceInput(1, n17);
- n18->ReplaceInput(2, n5);
- n18->ReplaceInput(3, n16);
- n18->ReplaceInput(4, n14);
- n8->ReplaceInput(1, n18);
- n8->ReplaceInput(2, n6);
- n19->ReplaceInput(0, n8);
- n19->ReplaceInput(1, n12);
- op = common_builder.IfFalse();
- Node* n15 = graph.NewNode(op, nil);
- USE(n15);
- n15->ReplaceInput(0, n13);
- n19->ReplaceInput(2, n15);
- n20->ReplaceInput(0, n19);
-
- graph.SetStart(n0);
- graph.SetEnd(n20);
-
- ComputeAndVerifySchedule(19, &graph);
-}
-
-
-TEST(BuildScheduleComplexLoops) {
- HandleAndZoneScope scope;
- Isolate* isolate = scope.main_isolate();
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common_builder(scope.main_zone());
- JSOperatorBuilder js_builder(scope.main_zone());
- const Operator* op;
-
- Handle<HeapObject> object =
- Handle<HeapObject>(isolate->heap()->undefined_value(), isolate);
- Unique<HeapObject> unique_constant =
- Unique<HeapObject>::CreateUninitialized(object);
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b, c) {
- // while (a < b) {
- // a++;
- // while (c < b) {
- // c++;
- // }
- // }
- // while (a < b) {
- // a += 2;
- // }
- // return a;
- // }
- op = common_builder.Start(0);
- Node* n0 = graph.NewNode(op);
- USE(n0);
- Node* nil = graph.NewNode(common_builder.Dead());
- op = common_builder.End();
- Node* n46 = graph.NewNode(op, nil);
- USE(n46);
- op = common_builder.Return();
- Node* n45 = graph.NewNode(op, nil, nil, nil);
- USE(n45);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n35 = graph.NewNode(op, nil, nil, nil);
- USE(n35);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n9 = graph.NewNode(op, nil, nil, nil);
- USE(n9);
- op = common_builder.Parameter(0);
- Node* n2 = graph.NewNode(op, n0);
- USE(n2);
- n9->ReplaceInput(0, n2);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n23 = graph.NewNode(op, nil, nil, nil);
- USE(n23);
- op = js_builder.Add();
- Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n20);
- op = js_builder.ToNumber();
- Node* n18 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n18);
- n18->ReplaceInput(0, n9);
- op = common_builder.HeapConstant(unique_constant);
- Node* n6 = graph.NewNode(op);
- USE(n6);
- n18->ReplaceInput(1, n6);
- op = js_builder.LessThan();
- Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n14);
- n14->ReplaceInput(0, n9);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n10 = graph.NewNode(op, nil, nil, nil);
- USE(n10);
- op = common_builder.Parameter(0);
- Node* n3 = graph.NewNode(op, n0);
- USE(n3);
- n10->ReplaceInput(0, n3);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n24 = graph.NewNode(op, nil, nil, nil);
- USE(n24);
- n24->ReplaceInput(0, n10);
- n24->ReplaceInput(1, n24);
- op = common_builder.Loop(2);
- Node* n21 = graph.NewNode(op, nil, nil);
- USE(n21);
- op = common_builder.IfTrue();
- Node* n16 = graph.NewNode(op, nil);
- USE(n16);
- op = common_builder.Branch();
- Node* n15 = graph.NewNode(op, nil, nil);
- USE(n15);
- n15->ReplaceInput(0, n14);
- op = common_builder.Loop(2);
- Node* n7 = graph.NewNode(op, nil, nil);
- USE(n7);
- n7->ReplaceInput(0, n0);
- op = common_builder.IfFalse();
- Node* n30 = graph.NewNode(op, nil);
- USE(n30);
- op = common_builder.Branch();
- Node* n28 = graph.NewNode(op, nil, nil);
- USE(n28);
- op = js_builder.LessThan();
- Node* n27 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n27);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n25 = graph.NewNode(op, nil, nil, nil);
- USE(n25);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n11 = graph.NewNode(op, nil, nil, nil);
- USE(n11);
- op = common_builder.Parameter(0);
- Node* n4 = graph.NewNode(op, n0);
- USE(n4);
- n11->ReplaceInput(0, n4);
- n11->ReplaceInput(1, n25);
- n11->ReplaceInput(2, n7);
- n25->ReplaceInput(0, n11);
- op = js_builder.Add();
- Node* n32 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n32);
- op = js_builder.ToNumber();
- Node* n31 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n31);
- n31->ReplaceInput(0, n25);
- n31->ReplaceInput(1, n6);
- n31->ReplaceInput(2, n27);
- op = common_builder.IfTrue();
- Node* n29 = graph.NewNode(op, nil);
- USE(n29);
- n29->ReplaceInput(0, n28);
- n31->ReplaceInput(3, n29);
- n32->ReplaceInput(0, n31);
- op = common_builder.NumberConstant(0);
- Node* n19 = graph.NewNode(op);
- USE(n19);
- n32->ReplaceInput(1, n19);
- n32->ReplaceInput(2, n6);
- n32->ReplaceInput(3, n31);
- n32->ReplaceInput(4, n29);
- n25->ReplaceInput(1, n32);
- n25->ReplaceInput(2, n21);
- n27->ReplaceInput(0, n25);
- n27->ReplaceInput(1, n24);
- n27->ReplaceInput(2, n6);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n26 = graph.NewNode(op, nil, nil, nil);
- USE(n26);
- n26->ReplaceInput(0, n20);
- n26->ReplaceInput(1, n32);
- n26->ReplaceInput(2, n21);
- n27->ReplaceInput(3, n26);
- n27->ReplaceInput(4, n21);
- n28->ReplaceInput(0, n27);
- n28->ReplaceInput(1, n21);
- n30->ReplaceInput(0, n28);
- n7->ReplaceInput(1, n30);
- n15->ReplaceInput(1, n7);
- n16->ReplaceInput(0, n15);
- n21->ReplaceInput(0, n16);
- n21->ReplaceInput(1, n29);
- n24->ReplaceInput(2, n21);
- n10->ReplaceInput(1, n24);
- n10->ReplaceInput(2, n7);
- n14->ReplaceInput(1, n10);
- n14->ReplaceInput(2, n6);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n12 = graph.NewNode(op, nil, nil, nil);
- USE(n12);
- n12->ReplaceInput(0, n0);
- n12->ReplaceInput(1, n27);
- n12->ReplaceInput(2, n7);
- n14->ReplaceInput(3, n12);
- n14->ReplaceInput(4, n7);
- n18->ReplaceInput(2, n14);
- n18->ReplaceInput(3, n16);
- n20->ReplaceInput(0, n18);
- n20->ReplaceInput(1, n19);
- n20->ReplaceInput(2, n6);
- n20->ReplaceInput(3, n18);
- n20->ReplaceInput(4, n16);
- n23->ReplaceInput(0, n20);
- n23->ReplaceInput(1, n23);
- n23->ReplaceInput(2, n21);
- n9->ReplaceInput(1, n23);
- n9->ReplaceInput(2, n7);
- n35->ReplaceInput(0, n9);
- op = js_builder.Add();
- Node* n44 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n44);
- n44->ReplaceInput(0, n35);
- op = common_builder.NumberConstant(0);
- Node* n43 = graph.NewNode(op);
- USE(n43);
- n44->ReplaceInput(1, n43);
- n44->ReplaceInput(2, n6);
- op = js_builder.LessThan();
- Node* n39 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n39);
- n39->ReplaceInput(0, n35);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n36 = graph.NewNode(op, nil, nil, nil);
- USE(n36);
- n36->ReplaceInput(0, n10);
- n36->ReplaceInput(1, n36);
- op = common_builder.Loop(2);
- Node* n33 = graph.NewNode(op, nil, nil);
- USE(n33);
- op = common_builder.IfFalse();
- Node* n17 = graph.NewNode(op, nil);
- USE(n17);
- n17->ReplaceInput(0, n15);
- n33->ReplaceInput(0, n17);
- op = common_builder.IfTrue();
- Node* n41 = graph.NewNode(op, nil);
- USE(n41);
- op = common_builder.Branch();
- Node* n40 = graph.NewNode(op, nil, nil);
- USE(n40);
- n40->ReplaceInput(0, n39);
- n40->ReplaceInput(1, n33);
- n41->ReplaceInput(0, n40);
- n33->ReplaceInput(1, n41);
- n36->ReplaceInput(2, n33);
- n39->ReplaceInput(1, n36);
- n39->ReplaceInput(2, n6);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n38 = graph.NewNode(op, nil, nil, nil);
- USE(n38);
- n38->ReplaceInput(0, n14);
- n38->ReplaceInput(1, n44);
- n38->ReplaceInput(2, n33);
- n39->ReplaceInput(3, n38);
- n39->ReplaceInput(4, n33);
- n44->ReplaceInput(3, n39);
- n44->ReplaceInput(4, n41);
- n35->ReplaceInput(1, n44);
- n35->ReplaceInput(2, n33);
- n45->ReplaceInput(0, n35);
- n45->ReplaceInput(1, n39);
- op = common_builder.IfFalse();
- Node* n42 = graph.NewNode(op, nil);
- USE(n42);
- n42->ReplaceInput(0, n40);
- n45->ReplaceInput(2, n42);
- n46->ReplaceInput(0, n45);
-
- graph.SetStart(n0);
- graph.SetEnd(n46);
-
- ComputeAndVerifySchedule(46, &graph);
-}
-
-
-TEST(BuildScheduleBreakAndContinue) {
- HandleAndZoneScope scope;
- Isolate* isolate = scope.main_isolate();
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common_builder(scope.main_zone());
- JSOperatorBuilder js_builder(scope.main_zone());
- const Operator* op;
-
- Handle<HeapObject> object =
- Handle<HeapObject>(isolate->heap()->undefined_value(), isolate);
- Unique<HeapObject> unique_constant =
- Unique<HeapObject>::CreateUninitialized(object);
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b, c) {
- // var d = 0;
- // while (a < b) {
- // a++;
- // while (c < b) {
- // c++;
- // if (d == 0) break;
- // a++;
- // }
- // if (a == 1) continue;
- // d++;
- // }
- // return a + d;
- // }
- op = common_builder.Start(0);
- Node* n0 = graph.NewNode(op);
- USE(n0);
- Node* nil = graph.NewNode(common_builder.Dead());
- op = common_builder.End();
- Node* n58 = graph.NewNode(op, nil);
- USE(n58);
- op = common_builder.Return();
- Node* n57 = graph.NewNode(op, nil, nil, nil);
- USE(n57);
- op = js_builder.Add();
- Node* n56 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n56);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n10 = graph.NewNode(op, nil, nil, nil);
- USE(n10);
- op = common_builder.Parameter(0);
- Node* n2 = graph.NewNode(op, n0);
- USE(n2);
- n10->ReplaceInput(0, n2);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n25 = graph.NewNode(op, nil, nil, nil);
- USE(n25);
- op = js_builder.Add();
- Node* n22 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n22);
- op = js_builder.ToNumber();
- Node* n20 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n20);
- n20->ReplaceInput(0, n10);
- op = common_builder.HeapConstant(unique_constant);
- Node* n6 = graph.NewNode(op);
- USE(n6);
- n20->ReplaceInput(1, n6);
- op = js_builder.LessThan();
- Node* n16 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n16);
- n16->ReplaceInput(0, n10);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n11 = graph.NewNode(op, nil, nil, nil);
- USE(n11);
- op = common_builder.Parameter(0);
- Node* n3 = graph.NewNode(op, n0);
- USE(n3);
- n11->ReplaceInput(0, n3);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n26 = graph.NewNode(op, nil, nil, nil);
- USE(n26);
- n26->ReplaceInput(0, n11);
- n26->ReplaceInput(1, n26);
- op = common_builder.Loop(2);
- Node* n23 = graph.NewNode(op, nil, nil);
- USE(n23);
- op = common_builder.IfTrue();
- Node* n18 = graph.NewNode(op, nil);
- USE(n18);
- op = common_builder.Branch();
- Node* n17 = graph.NewNode(op, nil, nil);
- USE(n17);
- n17->ReplaceInput(0, n16);
- op = common_builder.Loop(2);
- Node* n8 = graph.NewNode(op, nil, nil);
- USE(n8);
- n8->ReplaceInput(0, n0);
- op = common_builder.Merge(2);
- Node* n53 = graph.NewNode(op, nil, nil);
- USE(n53);
- op = common_builder.IfTrue();
- Node* n49 = graph.NewNode(op, nil);
- USE(n49);
- op = common_builder.Branch();
- Node* n48 = graph.NewNode(op, nil, nil);
- USE(n48);
- op = js_builder.Equal();
- Node* n47 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n47);
- n47->ReplaceInput(0, n25);
- op = common_builder.NumberConstant(0);
- Node* n46 = graph.NewNode(op);
- USE(n46);
- n47->ReplaceInput(1, n46);
- n47->ReplaceInput(2, n6);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n42 = graph.NewNode(op, nil, nil, nil);
- USE(n42);
- op = js_builder.LessThan();
- Node* n30 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n30);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n27 = graph.NewNode(op, nil, nil, nil);
- USE(n27);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n12 = graph.NewNode(op, nil, nil, nil);
- USE(n12);
- op = common_builder.Parameter(0);
- Node* n4 = graph.NewNode(op, n0);
- USE(n4);
- n12->ReplaceInput(0, n4);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n41 = graph.NewNode(op, nil, nil, nil);
- USE(n41);
- n41->ReplaceInput(0, n27);
- op = js_builder.Add();
- Node* n35 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n35);
- op = js_builder.ToNumber();
- Node* n34 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n34);
- n34->ReplaceInput(0, n27);
- n34->ReplaceInput(1, n6);
- n34->ReplaceInput(2, n30);
- op = common_builder.IfTrue();
- Node* n32 = graph.NewNode(op, nil);
- USE(n32);
- op = common_builder.Branch();
- Node* n31 = graph.NewNode(op, nil, nil);
- USE(n31);
- n31->ReplaceInput(0, n30);
- n31->ReplaceInput(1, n23);
- n32->ReplaceInput(0, n31);
- n34->ReplaceInput(3, n32);
- n35->ReplaceInput(0, n34);
- op = common_builder.NumberConstant(0);
- Node* n21 = graph.NewNode(op);
- USE(n21);
- n35->ReplaceInput(1, n21);
- n35->ReplaceInput(2, n6);
- n35->ReplaceInput(3, n34);
- n35->ReplaceInput(4, n32);
- n41->ReplaceInput(1, n35);
- op = common_builder.Merge(2);
- Node* n40 = graph.NewNode(op, nil, nil);
- USE(n40);
- op = common_builder.IfFalse();
- Node* n33 = graph.NewNode(op, nil);
- USE(n33);
- n33->ReplaceInput(0, n31);
- n40->ReplaceInput(0, n33);
- op = common_builder.IfTrue();
- Node* n39 = graph.NewNode(op, nil);
- USE(n39);
- op = common_builder.Branch();
- Node* n38 = graph.NewNode(op, nil, nil);
- USE(n38);
- op = js_builder.Equal();
- Node* n37 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n37);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n28 = graph.NewNode(op, nil, nil, nil);
- USE(n28);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n13 = graph.NewNode(op, nil, nil, nil);
- USE(n13);
- op = common_builder.NumberConstant(0);
- Node* n7 = graph.NewNode(op);
- USE(n7);
- n13->ReplaceInput(0, n7);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n54 = graph.NewNode(op, nil, nil, nil);
- USE(n54);
- n54->ReplaceInput(0, n28);
- op = js_builder.Add();
- Node* n52 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n52);
- op = js_builder.ToNumber();
- Node* n51 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n51);
- n51->ReplaceInput(0, n28);
- n51->ReplaceInput(1, n6);
- n51->ReplaceInput(2, n47);
- op = common_builder.IfFalse();
- Node* n50 = graph.NewNode(op, nil);
- USE(n50);
- n50->ReplaceInput(0, n48);
- n51->ReplaceInput(3, n50);
- n52->ReplaceInput(0, n51);
- n52->ReplaceInput(1, n21);
- n52->ReplaceInput(2, n6);
- n52->ReplaceInput(3, n51);
- n52->ReplaceInput(4, n50);
- n54->ReplaceInput(1, n52);
- n54->ReplaceInput(2, n53);
- n13->ReplaceInput(1, n54);
- n13->ReplaceInput(2, n8);
- n28->ReplaceInput(0, n13);
- n28->ReplaceInput(1, n28);
- n28->ReplaceInput(2, n23);
- n37->ReplaceInput(0, n28);
- op = common_builder.NumberConstant(0);
- Node* n36 = graph.NewNode(op);
- USE(n36);
- n37->ReplaceInput(1, n36);
- n37->ReplaceInput(2, n6);
- n37->ReplaceInput(3, n35);
- n37->ReplaceInput(4, n32);
- n38->ReplaceInput(0, n37);
- n38->ReplaceInput(1, n32);
- n39->ReplaceInput(0, n38);
- n40->ReplaceInput(1, n39);
- n41->ReplaceInput(2, n40);
- n12->ReplaceInput(1, n41);
- n12->ReplaceInput(2, n8);
- n27->ReplaceInput(0, n12);
- n27->ReplaceInput(1, n35);
- n27->ReplaceInput(2, n23);
- n30->ReplaceInput(0, n27);
- n30->ReplaceInput(1, n26);
- n30->ReplaceInput(2, n6);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n29 = graph.NewNode(op, nil, nil, nil);
- USE(n29);
- n29->ReplaceInput(0, n22);
- op = js_builder.Add();
- Node* n45 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n45);
- op = js_builder.ToNumber();
- Node* n44 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n44);
- n44->ReplaceInput(0, n25);
- n44->ReplaceInput(1, n6);
- n44->ReplaceInput(2, n37);
- op = common_builder.IfFalse();
- Node* n43 = graph.NewNode(op, nil);
- USE(n43);
- n43->ReplaceInput(0, n38);
- n44->ReplaceInput(3, n43);
- n45->ReplaceInput(0, n44);
- n45->ReplaceInput(1, n21);
- n45->ReplaceInput(2, n6);
- n45->ReplaceInput(3, n44);
- n45->ReplaceInput(4, n43);
- n29->ReplaceInput(1, n45);
- n29->ReplaceInput(2, n23);
- n30->ReplaceInput(3, n29);
- n30->ReplaceInput(4, n23);
- n42->ReplaceInput(0, n30);
- n42->ReplaceInput(1, n37);
- n42->ReplaceInput(2, n40);
- n47->ReplaceInput(3, n42);
- n47->ReplaceInput(4, n40);
- n48->ReplaceInput(0, n47);
- n48->ReplaceInput(1, n40);
- n49->ReplaceInput(0, n48);
- n53->ReplaceInput(0, n49);
- n53->ReplaceInput(1, n50);
- n8->ReplaceInput(1, n53);
- n17->ReplaceInput(1, n8);
- n18->ReplaceInput(0, n17);
- n23->ReplaceInput(0, n18);
- n23->ReplaceInput(1, n43);
- n26->ReplaceInput(2, n23);
- n11->ReplaceInput(1, n26);
- n11->ReplaceInput(2, n8);
- n16->ReplaceInput(1, n11);
- n16->ReplaceInput(2, n6);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n14 = graph.NewNode(op, nil, nil, nil);
- USE(n14);
- n14->ReplaceInput(0, n0);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n55 = graph.NewNode(op, nil, nil, nil);
- USE(n55);
- n55->ReplaceInput(0, n47);
- n55->ReplaceInput(1, n52);
- n55->ReplaceInput(2, n53);
- n14->ReplaceInput(1, n55);
- n14->ReplaceInput(2, n8);
- n16->ReplaceInput(3, n14);
- n16->ReplaceInput(4, n8);
- n20->ReplaceInput(2, n16);
- n20->ReplaceInput(3, n18);
- n22->ReplaceInput(0, n20);
- n22->ReplaceInput(1, n21);
- n22->ReplaceInput(2, n6);
- n22->ReplaceInput(3, n20);
- n22->ReplaceInput(4, n18);
- n25->ReplaceInput(0, n22);
- n25->ReplaceInput(1, n45);
- n25->ReplaceInput(2, n23);
- n10->ReplaceInput(1, n25);
- n10->ReplaceInput(2, n8);
- n56->ReplaceInput(0, n10);
- n56->ReplaceInput(1, n13);
- n56->ReplaceInput(2, n6);
- n56->ReplaceInput(3, n16);
- op = common_builder.IfFalse();
- Node* n19 = graph.NewNode(op, nil);
- USE(n19);
- n19->ReplaceInput(0, n17);
- n56->ReplaceInput(4, n19);
- n57->ReplaceInput(0, n56);
- n57->ReplaceInput(1, n56);
- n57->ReplaceInput(2, n19);
- n58->ReplaceInput(0, n57);
-
- graph.SetStart(n0);
- graph.SetEnd(n58);
-
- ComputeAndVerifySchedule(62, &graph);
-}
-
-
-TEST(BuildScheduleSimpleLoopWithCodeMotion) {
- HandleAndZoneScope scope;
- Isolate* isolate = scope.main_isolate();
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common_builder(scope.main_zone());
- JSOperatorBuilder js_builder(scope.main_zone());
- const Operator* op;
-
- Handle<HeapObject> object =
- Handle<HeapObject>(isolate->heap()->undefined_value(), isolate);
- Unique<HeapObject> unique_constant =
- Unique<HeapObject>::CreateUninitialized(object);
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b, c) {
- // while (a < b) {
- // a += b + c;
- // }
- // return a;
- // }
- op = common_builder.Start(0);
- Node* n0 = graph.NewNode(op);
- USE(n0);
- Node* nil = graph.NewNode(common_builder.Dead());
- op = common_builder.End();
- Node* n22 = graph.NewNode(op, nil);
- USE(n22);
- op = common_builder.Return();
- Node* n21 = graph.NewNode(op, nil, nil, nil);
- USE(n21);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n9 = graph.NewNode(op, nil, nil, nil);
- USE(n9);
- op = common_builder.Parameter(0);
- Node* n2 = graph.NewNode(op, n0);
- USE(n2);
- n9->ReplaceInput(0, n2);
- op = js_builder.Add();
- Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n20);
- n20->ReplaceInput(0, n9);
- op = &kIntAdd;
- Node* n19 = graph.NewNode(op, nil, nil);
- USE(n19);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n10 = graph.NewNode(op, nil, nil, nil);
- USE(n10);
- op = common_builder.Parameter(0);
- Node* n3 = graph.NewNode(op, n0);
- USE(n3);
- n10->ReplaceInput(0, n3);
- n10->ReplaceInput(1, n10);
- op = common_builder.Loop(2);
- Node* n7 = graph.NewNode(op, nil, nil);
- USE(n7);
- n7->ReplaceInput(0, n0);
- op = common_builder.IfTrue();
- Node* n17 = graph.NewNode(op, nil);
- USE(n17);
- op = common_builder.Branch();
- Node* n16 = graph.NewNode(op, nil, nil);
- USE(n16);
- op = js_builder.ToBoolean();
- Node* n15 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n15);
- op = js_builder.LessThan();
- Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n14);
- n14->ReplaceInput(0, n9);
- n14->ReplaceInput(1, n10);
- op = common_builder.HeapConstant(unique_constant);
- Node* n6 = graph.NewNode(op);
- USE(n6);
- n14->ReplaceInput(2, n6);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n12 = graph.NewNode(op, nil, nil, nil);
- USE(n12);
- n12->ReplaceInput(0, n0);
- n12->ReplaceInput(1, n20);
- n12->ReplaceInput(2, n7);
- n14->ReplaceInput(3, n12);
- n14->ReplaceInput(4, n7);
- n15->ReplaceInput(0, n14);
- n15->ReplaceInput(1, n6);
- n15->ReplaceInput(2, n14);
- n15->ReplaceInput(3, n7);
- n16->ReplaceInput(0, n15);
- n16->ReplaceInput(1, n7);
- n17->ReplaceInput(0, n16);
- n7->ReplaceInput(1, n17);
- n10->ReplaceInput(2, n7);
- n19->ReplaceInput(0, n2);
- op = common_builder.Phi(kMachAnyTagged, 2);
- Node* n11 = graph.NewNode(op, nil, nil, nil);
- USE(n11);
- op = common_builder.Parameter(0);
- Node* n4 = graph.NewNode(op, n0);
- USE(n4);
- n11->ReplaceInput(0, n4);
- n11->ReplaceInput(1, n11);
- n11->ReplaceInput(2, n7);
- n19->ReplaceInput(1, n3);
- n20->ReplaceInput(1, n19);
- n20->ReplaceInput(2, n6);
- n20->ReplaceInput(3, n19);
- n20->ReplaceInput(4, n17);
- n9->ReplaceInput(1, n20);
- n9->ReplaceInput(2, n7);
- n21->ReplaceInput(0, n9);
- n21->ReplaceInput(1, n15);
- op = common_builder.IfFalse();
- Node* n18 = graph.NewNode(op, nil);
- USE(n18);
- n18->ReplaceInput(0, n16);
- n21->ReplaceInput(2, n18);
- n22->ReplaceInput(0, n21);
-
- graph.SetStart(n0);
- graph.SetEnd(n22);
-
- Schedule* schedule = ComputeAndVerifySchedule(19, &graph);
- // Make sure the integer-only add gets hoisted to a different block that the
- // JSAdd.
- CHECK(schedule->block(n19) != schedule->block(n20));
-}
-
-
-#if V8_TURBOFAN_TARGET
-
-static Node* CreateDiamond(Graph* graph, CommonOperatorBuilder* common,
- Node* cond) {
- Node* tv = graph->NewNode(common->Int32Constant(6));
- Node* fv = graph->NewNode(common->Int32Constant(7));
- Node* br = graph->NewNode(common->Branch(), cond, graph->start());
- Node* t = graph->NewNode(common->IfTrue(), br);
- Node* f = graph->NewNode(common->IfFalse(), br);
- Node* m = graph->NewNode(common->Merge(2), t, f);
- Node* phi = graph->NewNode(common->Phi(kMachAnyTagged, 2), tv, fv, m);
- return phi;
-}
-
-
-TEST(FloatingDiamond1) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
-
- Node* start = graph.NewNode(common.Start(1));
- graph.SetStart(start);
-
- Node* p0 = graph.NewNode(common.Parameter(0), start);
- Node* d1 = CreateDiamond(&graph, &common, p0);
- Node* ret = graph.NewNode(common.Return(), d1, start, start);
- Node* end = graph.NewNode(common.End(), ret, start);
-
- graph.SetEnd(end);
-
- ComputeAndVerifySchedule(13, &graph);
-}
-
-
-TEST(FloatingDiamond2) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
-
- Node* start = graph.NewNode(common.Start(2));
- graph.SetStart(start);
-
- Node* p0 = graph.NewNode(common.Parameter(0), start);
- Node* p1 = graph.NewNode(common.Parameter(1), start);
- Node* d1 = CreateDiamond(&graph, &common, p0);
- Node* d2 = CreateDiamond(&graph, &common, p1);
- Node* add = graph.NewNode(&kIntAdd, d1, d2);
- Node* ret = graph.NewNode(common.Return(), add, start, start);
- Node* end = graph.NewNode(common.End(), ret, start);
-
- graph.SetEnd(end);
-
- ComputeAndVerifySchedule(24, &graph);
-}
-
-
-TEST(FloatingDiamond3) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
-
- Node* start = graph.NewNode(common.Start(2));
- graph.SetStart(start);
-
- Node* p0 = graph.NewNode(common.Parameter(0), start);
- Node* p1 = graph.NewNode(common.Parameter(1), start);
- Node* d1 = CreateDiamond(&graph, &common, p0);
- Node* d2 = CreateDiamond(&graph, &common, p1);
- Node* add = graph.NewNode(&kIntAdd, d1, d2);
- Node* d3 = CreateDiamond(&graph, &common, add);
- Node* ret = graph.NewNode(common.Return(), d3, start, start);
- Node* end = graph.NewNode(common.End(), ret, start);
-
- graph.SetEnd(end);
-
- ComputeAndVerifySchedule(33, &graph);
-}
-
-
-TEST(NestedFloatingDiamonds) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
- SimplifiedOperatorBuilder simplified(scope.main_zone());
-
- Node* start = graph.NewNode(common.Start(2));
- graph.SetStart(start);
-
- Node* p0 = graph.NewNode(common.Parameter(0), start);
-
- Node* fv = graph.NewNode(common.Int32Constant(7));
- Node* br = graph.NewNode(common.Branch(), p0, graph.start());
- Node* t = graph.NewNode(common.IfTrue(), br);
- Node* f = graph.NewNode(common.IfFalse(), br);
-
- Node* map = graph.NewNode(
- simplified.LoadElement(AccessBuilder::ForFixedArrayElement()), p0, p0, p0,
- start, f);
- Node* br1 = graph.NewNode(common.Branch(), map, graph.start());
- Node* t1 = graph.NewNode(common.IfTrue(), br1);
- Node* f1 = graph.NewNode(common.IfFalse(), br1);
- Node* m1 = graph.NewNode(common.Merge(2), t1, f1);
- Node* ttrue = graph.NewNode(common.Int32Constant(1));
- Node* ffalse = graph.NewNode(common.Int32Constant(0));
- Node* phi1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), ttrue, ffalse, m1);
-
-
- Node* m = graph.NewNode(common.Merge(2), t, f);
- Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), fv, phi1, m);
- Node* ephi1 = graph.NewNode(common.EffectPhi(2), start, map, m);
-
- Node* ret = graph.NewNode(common.Return(), phi, ephi1, start);
- Node* end = graph.NewNode(common.End(), ret, start);
-
- graph.SetEnd(end);
-
- ComputeAndVerifySchedule(23, &graph);
-}
-
-
-TEST(NestedFloatingDiamondWithChain) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
-
- Node* start = graph.NewNode(common.Start(2));
- graph.SetStart(start);
-
- Node* p0 = graph.NewNode(common.Parameter(0), start);
- Node* p1 = graph.NewNode(common.Parameter(1), start);
- Node* c = graph.NewNode(common.Int32Constant(7));
-
- Node* brA1 = graph.NewNode(common.Branch(), p0, graph.start());
- Node* tA1 = graph.NewNode(common.IfTrue(), brA1);
- Node* fA1 = graph.NewNode(common.IfFalse(), brA1);
- Node* mA1 = graph.NewNode(common.Merge(2), tA1, fA1);
- Node* phiA1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p1, mA1);
-
- Node* brB1 = graph.NewNode(common.Branch(), p1, graph.start());
- Node* tB1 = graph.NewNode(common.IfTrue(), brB1);
- Node* fB1 = graph.NewNode(common.IfFalse(), brB1);
- Node* mB1 = graph.NewNode(common.Merge(2), tB1, fB1);
- Node* phiB1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p1, mB1);
-
- Node* brA2 = graph.NewNode(common.Branch(), phiB1, mA1);
- Node* tA2 = graph.NewNode(common.IfTrue(), brA2);
- Node* fA2 = graph.NewNode(common.IfFalse(), brA2);
- Node* mA2 = graph.NewNode(common.Merge(2), tA2, fA2);
- Node* phiA2 = graph.NewNode(common.Phi(kMachAnyTagged, 2), phiB1, c, mA2);
-
- Node* brB2 = graph.NewNode(common.Branch(), phiA1, mB1);
- Node* tB2 = graph.NewNode(common.IfTrue(), brB2);
- Node* fB2 = graph.NewNode(common.IfFalse(), brB2);
- Node* mB2 = graph.NewNode(common.Merge(2), tB2, fB2);
- Node* phiB2 = graph.NewNode(common.Phi(kMachAnyTagged, 2), phiA1, c, mB2);
-
- Node* add = graph.NewNode(&kIntAdd, phiA2, phiB2);
- Node* ret = graph.NewNode(common.Return(), add, start, start);
- Node* end = graph.NewNode(common.End(), ret, start);
-
- graph.SetEnd(end);
-
- ComputeAndVerifySchedule(35, &graph);
-}
-
-
-TEST(NestedFloatingDiamondWithLoop) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
-
- Node* start = graph.NewNode(common.Start(2));
- graph.SetStart(start);
-
- Node* p0 = graph.NewNode(common.Parameter(0), start);
-
- Node* fv = graph.NewNode(common.Int32Constant(7));
- Node* br = graph.NewNode(common.Branch(), p0, graph.start());
- Node* t = graph.NewNode(common.IfTrue(), br);
- Node* f = graph.NewNode(common.IfFalse(), br);
-
- Node* loop = graph.NewNode(common.Loop(2), f, start);
- Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop);
-
- Node* add = graph.NewNode(&kIntAdd, ind, fv);
- Node* br1 = graph.NewNode(common.Branch(), add, loop);
- Node* t1 = graph.NewNode(common.IfTrue(), br1);
- Node* f1 = graph.NewNode(common.IfFalse(), br1);
-
- loop->ReplaceInput(1, t1); // close loop.
- ind->ReplaceInput(1, ind); // close induction variable.
-
- Node* m = graph.NewNode(common.Merge(2), t, f1);
- Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), fv, ind, m);
-
- Node* ret = graph.NewNode(common.Return(), phi, start, start);
- Node* end = graph.NewNode(common.End(), ret, start);
-
- graph.SetEnd(end);
-
- ComputeAndVerifySchedule(20, &graph);
-}
-
-
-TEST(LoopedFloatingDiamond1) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
-
- Node* start = graph.NewNode(common.Start(2));
- graph.SetStart(start);
-
- Node* p0 = graph.NewNode(common.Parameter(0), start);
-
- Node* c = graph.NewNode(common.Int32Constant(7));
- Node* loop = graph.NewNode(common.Loop(2), start, start);
- Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop);
- Node* add = graph.NewNode(&kIntAdd, ind, c);
-
- Node* br = graph.NewNode(common.Branch(), add, loop);
- Node* t = graph.NewNode(common.IfTrue(), br);
- Node* f = graph.NewNode(common.IfFalse(), br);
-
- Node* br1 = graph.NewNode(common.Branch(), p0, graph.start());
- Node* t1 = graph.NewNode(common.IfTrue(), br1);
- Node* f1 = graph.NewNode(common.IfFalse(), br1);
- Node* m1 = graph.NewNode(common.Merge(2), t1, f1);
- Node* phi1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), add, p0, m1);
-
- loop->ReplaceInput(1, t); // close loop.
- ind->ReplaceInput(1, phi1); // close induction variable.
-
- Node* ret = graph.NewNode(common.Return(), ind, start, f);
- Node* end = graph.NewNode(common.End(), ret, f);
-
- graph.SetEnd(end);
-
- ComputeAndVerifySchedule(20, &graph);
-}
-
-
-TEST(LoopedFloatingDiamond2) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
-
- Node* start = graph.NewNode(common.Start(2));
- graph.SetStart(start);
-
- Node* p0 = graph.NewNode(common.Parameter(0), start);
-
- Node* c = graph.NewNode(common.Int32Constant(7));
- Node* loop = graph.NewNode(common.Loop(2), start, start);
- Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop);
-
- Node* br1 = graph.NewNode(common.Branch(), p0, graph.start());
- Node* t1 = graph.NewNode(common.IfTrue(), br1);
- Node* f1 = graph.NewNode(common.IfFalse(), br1);
- Node* m1 = graph.NewNode(common.Merge(2), t1, f1);
- Node* phi1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), c, ind, m1);
-
- Node* add = graph.NewNode(&kIntAdd, ind, phi1);
-
- Node* br = graph.NewNode(common.Branch(), add, loop);
- Node* t = graph.NewNode(common.IfTrue(), br);
- Node* f = graph.NewNode(common.IfFalse(), br);
-
- loop->ReplaceInput(1, t); // close loop.
- ind->ReplaceInput(1, add); // close induction variable.
-
- Node* ret = graph.NewNode(common.Return(), ind, start, f);
- Node* end = graph.NewNode(common.End(), ret, f);
-
- graph.SetEnd(end);
-
- ComputeAndVerifySchedule(20, &graph);
-}
-
-
-TEST(LoopedFloatingDiamond3) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
-
- Node* start = graph.NewNode(common.Start(2));
- graph.SetStart(start);
-
- Node* p0 = graph.NewNode(common.Parameter(0), start);
-
- Node* c = graph.NewNode(common.Int32Constant(7));
- Node* loop = graph.NewNode(common.Loop(2), start, start);
- Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop);
-
- Node* br1 = graph.NewNode(common.Branch(), p0, graph.start());
- Node* t1 = graph.NewNode(common.IfTrue(), br1);
- Node* f1 = graph.NewNode(common.IfFalse(), br1);
-
- Node* loop1 = graph.NewNode(common.Loop(2), t1, start);
- Node* ind1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop);
-
- Node* add1 = graph.NewNode(&kIntAdd, ind1, c);
- Node* br2 = graph.NewNode(common.Branch(), add1, loop1);
- Node* t2 = graph.NewNode(common.IfTrue(), br2);
- Node* f2 = graph.NewNode(common.IfFalse(), br2);
-
- loop1->ReplaceInput(1, t2); // close inner loop.
- ind1->ReplaceInput(1, ind1); // close inner induction variable.
-
- Node* m1 = graph.NewNode(common.Merge(2), f1, f2);
- Node* phi1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), c, ind1, m1);
-
- Node* add = graph.NewNode(&kIntAdd, ind, phi1);
-
- Node* br = graph.NewNode(common.Branch(), add, loop);
- Node* t = graph.NewNode(common.IfTrue(), br);
- Node* f = graph.NewNode(common.IfFalse(), br);
-
- loop->ReplaceInput(1, t); // close loop.
- ind->ReplaceInput(1, add); // close induction variable.
-
- Node* ret = graph.NewNode(common.Return(), ind, start, f);
- Node* end = graph.NewNode(common.End(), ret, f);
-
- graph.SetEnd(end);
-
- ComputeAndVerifySchedule(28, &graph);
-}
-
-
-TEST(PhisPushedDownToDifferentBranches) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
-
- Node* start = graph.NewNode(common.Start(2));
- graph.SetStart(start);
-
- Node* p0 = graph.NewNode(common.Parameter(0), start);
- Node* p1 = graph.NewNode(common.Parameter(1), start);
-
- Node* v1 = graph.NewNode(common.Int32Constant(1));
- Node* v2 = graph.NewNode(common.Int32Constant(2));
- Node* v3 = graph.NewNode(common.Int32Constant(3));
- Node* v4 = graph.NewNode(common.Int32Constant(4));
- Node* br = graph.NewNode(common.Branch(), p0, graph.start());
- Node* t = graph.NewNode(common.IfTrue(), br);
- Node* f = graph.NewNode(common.IfFalse(), br);
- Node* m = graph.NewNode(common.Merge(2), t, f);
- Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), v1, v2, m);
- Node* phi2 = graph.NewNode(common.Phi(kMachAnyTagged, 2), v3, v4, m);
-
- Node* br2 = graph.NewNode(common.Branch(), p1, graph.start());
- Node* t2 = graph.NewNode(common.IfTrue(), br2);
- Node* f2 = graph.NewNode(common.IfFalse(), br2);
- Node* m2 = graph.NewNode(common.Merge(2), t2, f2);
- Node* phi3 = graph.NewNode(common.Phi(kMachAnyTagged, 2), phi, phi2, m2);
-
- Node* ret = graph.NewNode(common.Return(), phi3, start, start);
- Node* end = graph.NewNode(common.End(), ret, start);
-
- graph.SetEnd(end);
-
- ComputeAndVerifySchedule(24, &graph);
-}
-
-
-TEST(BranchHintTrue) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
-
- Node* start = graph.NewNode(common.Start(1));
- graph.SetStart(start);
-
- Node* p0 = graph.NewNode(common.Parameter(0), start);
- Node* tv = graph.NewNode(common.Int32Constant(6));
- Node* fv = graph.NewNode(common.Int32Constant(7));
- Node* br = graph.NewNode(common.Branch(BranchHint::kTrue), p0, start);
- Node* t = graph.NewNode(common.IfTrue(), br);
- Node* f = graph.NewNode(common.IfFalse(), br);
- Node* m = graph.NewNode(common.Merge(2), t, f);
- Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), tv, fv, m);
- Node* ret = graph.NewNode(common.Return(), phi, start, start);
- Node* end = graph.NewNode(common.End(), ret, start);
-
- graph.SetEnd(end);
-
- Schedule* schedule = ComputeAndVerifySchedule(13, &graph);
- // Make sure the false block is marked as deferred.
- CHECK(!schedule->block(t)->deferred());
- CHECK(schedule->block(f)->deferred());
-}
-
-
-TEST(BranchHintFalse) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
-
- Node* start = graph.NewNode(common.Start(1));
- graph.SetStart(start);
-
- Node* p0 = graph.NewNode(common.Parameter(0), start);
- Node* tv = graph.NewNode(common.Int32Constant(6));
- Node* fv = graph.NewNode(common.Int32Constant(7));
- Node* br = graph.NewNode(common.Branch(BranchHint::kFalse), p0, start);
- Node* t = graph.NewNode(common.IfTrue(), br);
- Node* f = graph.NewNode(common.IfFalse(), br);
- Node* m = graph.NewNode(common.Merge(2), t, f);
- Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), tv, fv, m);
- Node* ret = graph.NewNode(common.Return(), phi, start, start);
- Node* end = graph.NewNode(common.End(), ret, start);
-
- graph.SetEnd(end);
-
- Schedule* schedule = ComputeAndVerifySchedule(13, &graph);
- // Make sure the true block is marked as deferred.
- CHECK(schedule->block(t)->deferred());
- CHECK(!schedule->block(f)->deferred());
-}
-
-
-TEST(ScheduleTerminate) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
-
- Node* start = graph.NewNode(common.Start(1));
- graph.SetStart(start);
-
- Node* loop = graph.NewNode(common.Loop(2), start, start);
- loop->ReplaceInput(1, loop); // self loop, NTL.
-
- Node* effect = graph.NewNode(common.EffectPhi(1), start, loop);
- effect->ReplaceInput(0, effect);
-
- Node* terminate = graph.NewNode(common.Terminate(1), effect, loop);
- Node* end = graph.NewNode(common.End(), terminate);
-
- graph.SetEnd(end);
-
- Schedule* schedule = ComputeAndVerifySchedule(6, &graph);
- BasicBlock* block = schedule->block(loop);
- CHECK_NE(NULL, loop);
- CHECK_EQ(block, schedule->block(effect));
- CHECK_GE(block->rpo_number(), 0);
-}
-
-#endif
diff --git a/test/cctest/compiler/test-simplified-lowering.cc b/test/cctest/compiler/test-simplified-lowering.cc
index 147aa32..1b752ed 100644
--- a/test/cctest/compiler/test-simplified-lowering.cc
+++ b/test/cctest/compiler/test-simplified-lowering.cc
@@ -4,46 +4,49 @@
#include <limits>
+#include "src/ast/scopes.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/change-lowering.h"
#include "src/compiler/control-builders.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/graph-visualizer.h"
-#include "src/compiler/node-properties-inl.h"
+#include "src/compiler/node-properties.h"
#include "src/compiler/pipeline.h"
#include "src/compiler/representation-change.h"
#include "src/compiler/simplified-lowering.h"
+#include "src/compiler/source-position.h"
#include "src/compiler/typer.h"
#include "src/compiler/verifier.h"
#include "src/execution.h"
-#include "src/parser.h"
-#include "src/rewriter.h"
-#include "src/scopes.h"
+#include "src/parsing/parser.h"
+#include "src/parsing/rewriter.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
+#include "test/cctest/compiler/function-tester.h"
#include "test/cctest/compiler/graph-builder-tester.h"
#include "test/cctest/compiler/value-helper.h"
-using namespace v8::internal;
-using namespace v8::internal::compiler;
+namespace v8 {
+namespace internal {
+namespace compiler {
template <typename ReturnType>
class SimplifiedLoweringTester : public GraphBuilderTester<ReturnType> {
public:
- SimplifiedLoweringTester(MachineType p0 = kMachNone,
- MachineType p1 = kMachNone,
- MachineType p2 = kMachNone,
- MachineType p3 = kMachNone,
- MachineType p4 = kMachNone)
- : GraphBuilderTester<ReturnType>(p0, p1, p2, p3, p4),
- typer(this->graph(), MaybeHandle<Context>()),
+ SimplifiedLoweringTester(MachineType p0 = MachineType::None(),
+ MachineType p1 = MachineType::None())
+ : GraphBuilderTester<ReturnType>(p0, p1),
+ typer(this->isolate(), this->graph()),
javascript(this->zone()),
- jsgraph(this->graph(), this->common(), &javascript, this->machine()),
- lowering(&jsgraph, this->zone()) {}
+ jsgraph(this->isolate(), this->graph(), this->common(), &javascript,
+ this->simplified(), this->machine()),
+ source_positions(jsgraph.graph()),
+ lowering(&jsgraph, this->zone(), &source_positions) {}
Typer typer;
JSOperatorBuilder javascript;
JSGraph jsgraph;
+ SourcePositionTable source_positions;
SimplifiedLowering lowering;
void LowerAllNodes() {
@@ -57,12 +60,8 @@
typer.Run();
lowering.LowerAllNodes();
- Zone* zone = this->zone();
- CompilationInfo info(zone->isolate(), zone);
- Linkage linkage(
- zone, Linkage::GetSimplifiedCDescriptor(zone, this->machine_sig_));
- ChangeLowering lowering(&jsgraph, &linkage);
- GraphReducer reducer(this->graph(), this->zone());
+ ChangeLowering lowering(&jsgraph);
+ GraphReducer reducer(this->zone(), this->graph());
reducer.AddReducer(&lowering);
reducer.ReduceGraph();
Verifier::Run(this->graph());
@@ -77,6 +76,17 @@
CHECK(factory()->NewNumber(expected)->SameValue(result));
}
+ template <typename T>
+ T* CallWithPotentialGC() {
+ // TODO(titzer): we wrap the code in a JSFunction here to reuse the
+ // JSEntryStub; that could be done with a special prologue or other stub.
+ Handle<JSFunction> fun = FunctionTester::ForMachineGraph(this->graph(), 0);
+ Handle<Object>* args = NULL;
+ MaybeHandle<Object> result = Execution::Call(
+ this->isolate(), fun, factory()->undefined_value(), 0, args);
+ return T::cast(*result.ToHandleChecked());
+ }
+
Factory* factory() { return this->isolate()->factory(); }
Heap* heap() { return this->isolate()->heap(); }
};
@@ -90,25 +100,23 @@
int32_t result;
SimplifiedLoweringTester<Object*> t;
FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(),
- kMachFloat64};
+ MachineType::Float64()};
Node* loaded = t.LoadField(load, t.PointerConstant(&input));
- NodeProperties::SetBounds(loaded, Bounds(Type::Number()));
+ NodeProperties::SetType(loaded, Type::Number());
Node* convert = t.NumberToInt32(loaded);
FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Signed32(),
- kMachInt32};
+ MachineType::Int32()};
t.StoreField(store, t.PointerConstant(&result), convert);
t.Return(t.jsgraph.TrueConstant());
- t.LowerAllNodes();
+ t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
- if (Pipeline::SupportedTarget()) {
FOR_FLOAT64_INPUTS(i) {
input = *i;
int32_t expected = DoubleToInt32(*i);
t.Call();
CHECK_EQ(expected, result);
}
- }
}
@@ -119,18 +127,17 @@
uint32_t result;
SimplifiedLoweringTester<Object*> t;
FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(),
- kMachFloat64};
+ MachineType::Float64()};
Node* loaded = t.LoadField(load, t.PointerConstant(&input));
- NodeProperties::SetBounds(loaded, Bounds(Type::Number()));
+ NodeProperties::SetType(loaded, Type::Number());
Node* convert = t.NumberToUint32(loaded);
FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), Type::Unsigned32(),
- kMachUint32};
+ MachineType::Uint32()};
t.StoreField(store, t.PointerConstant(&result), convert);
t.Return(t.jsgraph.TrueConstant());
- t.LowerAllNodes();
+ t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
- if (Pipeline::SupportedTarget()) {
FOR_FLOAT64_INPUTS(i) {
input = *i;
uint32_t expected = DoubleToUint32(*i);
@@ -138,7 +145,6 @@
CHECK_EQ(static_cast<int32_t>(expected), static_cast<int32_t>(result));
}
}
-}
// Create a simple JSObject with a unique map.
@@ -151,33 +157,31 @@
TEST(RunLoadMap) {
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
FieldAccess access = AccessBuilder::ForMap();
Node* load = t.LoadField(access, t.Parameter(0));
t.Return(load);
- t.LowerAllNodes();
+ t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
- if (Pipeline::SupportedTarget()) {
- Handle<JSObject> src = TestObject();
- Handle<Map> src_map(src->map());
- Object* result = t.Call(*src); // TODO(titzer): raw pointers in call
- CHECK_EQ(*src_map, result);
- }
+ Handle<JSObject> src = TestObject();
+ Handle<Map> src_map(src->map());
+ Object* result = t.Call(*src); // TODO(titzer): raw pointers in call
+ CHECK_EQ(*src_map, result);
}
TEST(RunStoreMap) {
- SimplifiedLoweringTester<int32_t> t(kMachAnyTagged, kMachAnyTagged);
+ SimplifiedLoweringTester<int32_t> t(MachineType::AnyTagged(),
+ MachineType::AnyTagged());
FieldAccess access = AccessBuilder::ForMap();
t.StoreField(access, t.Parameter(1), t.Parameter(0));
t.Return(t.jsgraph.TrueConstant());
- t.LowerAllNodes();
+ t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
- if (Pipeline::SupportedTarget()) {
Handle<JSObject> src = TestObject();
Handle<Map> src_map(src->map());
Handle<JSObject> dst = TestObject();
@@ -185,38 +189,35 @@
t.Call(*src_map, *dst); // TODO(titzer): raw pointers in call
CHECK(*src_map == dst->map());
}
-}
TEST(RunLoadProperties) {
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
FieldAccess access = AccessBuilder::ForJSObjectProperties();
Node* load = t.LoadField(access, t.Parameter(0));
t.Return(load);
- t.LowerAllNodes();
+ t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
- if (Pipeline::SupportedTarget()) {
Handle<JSObject> src = TestObject();
Handle<FixedArray> src_props(src->properties());
Object* result = t.Call(*src); // TODO(titzer): raw pointers in call
CHECK_EQ(*src_props, result);
- }
}
TEST(RunLoadStoreMap) {
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged, kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged(),
+ MachineType::AnyTagged());
FieldAccess access = AccessBuilder::ForMap();
Node* load = t.LoadField(access, t.Parameter(0));
t.StoreField(access, t.Parameter(1), load);
t.Return(load);
- t.LowerAllNodes();
+ t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
- if (Pipeline::SupportedTarget()) {
Handle<JSObject> src = TestObject();
Handle<Map> src_map(src->map());
Handle<JSObject> dst = TestObject();
@@ -225,21 +226,19 @@
CHECK(result->IsMap());
CHECK_EQ(*src_map, result);
CHECK(*src_map == dst->map());
- }
}
TEST(RunLoadStoreFixedArrayIndex) {
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
ElementAccess access = AccessBuilder::ForFixedArrayElement();
Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0));
t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), load);
t.Return(load);
- t.LowerAllNodes();
+ t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
- if (Pipeline::SupportedTarget()) {
Handle<FixedArray> array = t.factory()->NewFixedArray(2);
Handle<JSObject> src = TestObject();
Handle<JSObject> dst = TestObject();
@@ -249,16 +248,15 @@
CHECK_EQ(*src, result);
CHECK_EQ(*src, array->get(0));
CHECK_EQ(*src, array->get(1));
- }
}
TEST(RunLoadStoreArrayBuffer) {
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
const int index = 12;
const int array_length = 2 * index;
ElementAccess buffer_access =
- AccessBuilder::ForTypedArrayElement(v8::kExternalInt8Array, true);
+ AccessBuilder::ForTypedArrayElement(kExternalInt8Array, true);
Node* backing_store = t.LoadField(
AccessBuilder::ForJSArrayBufferBackingStore(), t.Parameter(0));
Node* load =
@@ -267,12 +265,11 @@
load);
t.Return(t.jsgraph.TrueConstant());
- t.LowerAllNodes();
+ t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
- if (Pipeline::SupportedTarget()) {
Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer();
- Runtime::SetupArrayBufferAllocatingData(t.isolate(), array, array_length);
+ JSArrayBuffer::SetupAllocatingData(array, t.isolate(), array_length);
uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store());
for (int i = 0; i < array_length; i++) {
data[i] = i;
@@ -287,7 +284,6 @@
CHECK_EQ(data[i], expected);
}
}
-}
TEST(RunLoadFieldFromUntaggedBase) {
@@ -296,14 +292,12 @@
for (size_t i = 0; i < arraysize(smis); i++) {
int offset = static_cast<int>(i * sizeof(Smi*));
FieldAccess access = {kUntaggedBase, offset, Handle<Name>(),
- Type::Integral32(), kMachAnyTagged};
+ Type::Integral32(), MachineType::AnyTagged()};
SimplifiedLoweringTester<Object*> t;
Node* load = t.LoadField(access, t.PointerConstant(smis));
t.Return(load);
- t.LowerAllNodes();
-
- if (!Pipeline::SupportedTarget()) continue;
+ t.LowerAllNodesAndLowerChanges();
for (int j = -5; j <= 5; j++) {
Smi* expected = Smi::FromInt(j);
@@ -320,15 +314,13 @@
for (size_t i = 0; i < arraysize(smis); i++) {
int offset = static_cast<int>(i * sizeof(Smi*));
FieldAccess access = {kUntaggedBase, offset, Handle<Name>(),
- Type::Integral32(), kMachAnyTagged};
+ Type::Integral32(), MachineType::AnyTagged()};
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Node* p0 = t.Parameter(0);
t.StoreField(access, t.PointerConstant(smis), p0);
t.Return(p0);
- t.LowerAllNodes();
-
- if (!Pipeline::SupportedTarget()) continue;
+ t.LowerAllNodesAndLowerChanges();
for (int j = -5; j <= 5; j++) {
Smi* expected = Smi::FromInt(j);
@@ -348,15 +340,13 @@
for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index
int offset = static_cast<int>(i * sizeof(Smi*));
ElementAccess access = {kUntaggedBase, offset, Type::Integral32(),
- kMachAnyTagged};
+ MachineType::AnyTagged()};
SimplifiedLoweringTester<Object*> t;
Node* load = t.LoadElement(access, t.PointerConstant(smis),
t.Int32Constant(static_cast<int>(j)));
t.Return(load);
- t.LowerAllNodes();
-
- if (!Pipeline::SupportedTarget()) continue;
+ t.LowerAllNodesAndLowerChanges();
for (int k = -5; k <= 5; k++) {
Smi* expected = Smi::FromInt(k);
@@ -376,16 +366,14 @@
for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index
int offset = static_cast<int>(i * sizeof(Smi*));
ElementAccess access = {kUntaggedBase, offset, Type::Integral32(),
- kMachAnyTagged};
+ MachineType::AnyTagged()};
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Node* p0 = t.Parameter(0);
t.StoreElement(access, t.PointerConstant(smis),
t.Int32Constant(static_cast<int>(j)), p0);
t.Return(p0);
- t.LowerAllNodes();
-
- if (!Pipeline::SupportedTarget()) continue;
+ t.LowerAllNodesAndLowerChanges();
for (int k = -5; k <= 5; k++) {
Smi* expected = Smi::FromInt(k);
@@ -450,13 +438,11 @@
Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index));
t.StoreElement(access, ptr, t.Int32Constant(to_index), load);
t.Return(t.jsgraph.TrueConstant());
- t.LowerAllNodes();
+ t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
- if (Pipeline::SupportedTarget()) {
Object* result = t.Call();
CHECK_EQ(t.isolate()->heap()->true_value(), result);
- }
}
// Create and run code that copies the field in either {untagged_array}
@@ -472,13 +458,11 @@
Node* load = t.LoadField(from_access, ptr);
t.StoreField(to_access, ptr, load);
t.Return(t.jsgraph.TrueConstant());
- t.LowerAllNodes();
+ t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
- if (Pipeline::SupportedTarget()) {
Object* result = t.Call();
CHECK_EQ(t.isolate()->heap()->true_value(), result);
- }
}
// Create and run code that copies the elements from {this} to {that}.
@@ -516,18 +500,15 @@
t.LowerAllNodes();
t.GenerateCode();
- if (Pipeline::SupportedTarget()) {
Object* result = t.Call();
CHECK_EQ(t.isolate()->heap()->true_value(), result);
- }
#endif
}
E GetElement(int index) {
BoundsCheck(index);
if (tagged) {
- E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress());
- return raw[index];
+ return GetTaggedElement(index);
} else {
return untagged_array[index];
}
@@ -560,8 +541,19 @@
CHECK_LT(index, static_cast<int>(num_elements));
CHECK_EQ(static_cast<int>(ByteSize()), tagged_array->length());
}
+
+ E GetTaggedElement(int index) {
+ E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress());
+ return raw[index];
+ }
};
+template <>
+double AccessTester<double>::GetTaggedElement(int index) {
+ return ReadDoubleValue(tagged_array->GetDataStartAddress() +
+ index * sizeof(double));
+}
+
template <typename E>
static void RunAccessTest(MachineType rep, E* original_elements, size_t num) {
@@ -577,13 +569,11 @@
} else {
a.RunCopyElement(i, i + 1); // Test element read/write.
}
- if (Pipeline::SupportedTarget()) { // verify.
for (int j = 0; j < num_elements; j++) {
E expect =
j == (i + 1) ? original_elements[i] : original_elements[j];
CHECK_EQ(expect, a.GetElement(j));
}
- }
}
}
}
@@ -593,10 +583,8 @@
AccessTester<E> a(tf == 1, rep, original_elements, num);
AccessTester<E> b(tt == 1, rep, original_elements, num);
a.RunCopyElements(&b);
- if (Pipeline::SupportedTarget()) { // verify.
for (int i = 0; i < num_elements; i++) {
CHECK_EQ(a.GetElement(i), b.GetElement(i));
- }
}
}
}
@@ -606,19 +594,19 @@
TEST(RunAccessTests_uint8) {
uint8_t data[] = {0x07, 0x16, 0x25, 0x34, 0x43, 0x99,
0xab, 0x78, 0x89, 0x19, 0x2b, 0x38};
- RunAccessTest<uint8_t>(kMachInt8, data, arraysize(data));
+ RunAccessTest<uint8_t>(MachineType::Int8(), data, arraysize(data));
}
TEST(RunAccessTests_uint16) {
uint16_t data[] = {0x071a, 0x162b, 0x253c, 0x344d, 0x435e, 0x7777};
- RunAccessTest<uint16_t>(kMachInt16, data, arraysize(data));
+ RunAccessTest<uint16_t>(MachineType::Int16(), data, arraysize(data));
}
TEST(RunAccessTests_int32) {
int32_t data[] = {-211, 211, 628347, 2000000000, -2000000000, -1, -100000034};
- RunAccessTest<int32_t>(kMachInt32, data, arraysize(data));
+ RunAccessTest<int32_t>(MachineType::Int32(), data, arraysize(data));
}
@@ -632,13 +620,13 @@
V8_2PART_INT64(0x30313233, 34353637),
V8_2PART_INT64(0xa0a1a2a3, a4a5a6a7),
V8_2PART_INT64(0xf0f1f2f3, f4f5f6f7)};
- RunAccessTest<int64_t>(kMachInt64, data, arraysize(data));
+ RunAccessTest<int64_t>(MachineType::Int64(), data, arraysize(data));
}
TEST(RunAccessTests_float64) {
double data[] = {1.25, -1.25, 2.75, 11.0, 11100.8};
- RunAccessTest<double>(kMachFloat64, data, arraysize(data));
+ RunAccessTest<double>(MachineType::Float64(), data, arraysize(data));
}
@@ -646,7 +634,30 @@
Smi* data[] = {Smi::FromInt(-1), Smi::FromInt(-9),
Smi::FromInt(0), Smi::FromInt(666),
Smi::FromInt(77777), Smi::FromInt(Smi::kMaxValue)};
- RunAccessTest<Smi*>(kMachAnyTagged, data, arraysize(data));
+ RunAccessTest<Smi*>(MachineType::AnyTagged(), data, arraysize(data));
+}
+
+
+TEST(RunAllocate) {
+ PretenureFlag flag[] = {NOT_TENURED, TENURED};
+
+ for (size_t i = 0; i < arraysize(flag); i++) {
+ SimplifiedLoweringTester<HeapObject*> t;
+ FieldAccess access = AccessBuilder::ForMap();
+ Node* size = t.jsgraph.Constant(HeapNumber::kSize);
+ Node* alloc = t.NewNode(t.simplified()->Allocate(flag[i]), size);
+ Node* map = t.jsgraph.Constant(t.factory()->heap_number_map());
+ t.StoreField(access, alloc, map);
+ t.Return(alloc);
+
+ t.LowerAllNodesAndLowerChanges();
+ t.GenerateCode();
+
+ HeapObject* result = t.CallWithPotentialGC<HeapObject>();
+ CHECK(t.heap()->new_space()->Contains(result) || flag[i] == TENURED);
+ CHECK(t.heap()->old_space()->Contains(result) || flag[i] == NOT_TENURED);
+ CHECK(result->IsHeapNumber());
+ }
}
@@ -666,22 +677,23 @@
explicit TestingGraph(Type* p0_type, Type* p1_type = Type::None(),
Type* p2_type = Type::None())
: GraphAndBuilders(main_zone()),
- typer(graph(), MaybeHandle<Context>()),
+ typer(main_isolate(), graph()),
javascript(main_zone()),
- jsgraph(graph(), common(), &javascript, machine()) {
- start = graph()->NewNode(common()->Start(2));
+ jsgraph(main_isolate(), graph(), common(), &javascript, simplified(),
+ machine()) {
+ start = graph()->NewNode(common()->Start(4));
graph()->SetStart(start);
ret =
graph()->NewNode(common()->Return(), jsgraph.Constant(0), start, start);
- end = graph()->NewNode(common()->End(), ret);
+ end = graph()->NewNode(common()->End(1), ret);
graph()->SetEnd(end);
p0 = graph()->NewNode(common()->Parameter(0), start);
p1 = graph()->NewNode(common()->Parameter(1), start);
p2 = graph()->NewNode(common()->Parameter(2), start);
typer.Run();
- NodeProperties::SetBounds(p0, Bounds(p0_type));
- NodeProperties::SetBounds(p1, Bounds(p1_type));
- NodeProperties::SetBounds(p2, Bounds(p2_type));
+ NodeProperties::SetType(p0, p0_type);
+ NodeProperties::SetType(p1, p1_type);
+ NodeProperties::SetType(p2, p2_type);
}
void CheckLoweringBinop(IrOpcode::Value expected, const Operator* op) {
@@ -690,6 +702,13 @@
CHECK_EQ(expected, node->opcode());
}
+ void CheckLoweringStringBinop(IrOpcode::Value expected, const Operator* op) {
+ Node* node = Return(
+ graph()->NewNode(op, p0, p1, graph()->start(), graph()->start()));
+ Lower();
+ CHECK_EQ(expected, node->opcode());
+ }
+
void CheckLoweringTruncatedBinop(IrOpcode::Value expected, const Operator* op,
const Operator* trunc) {
Node* node = graph()->NewNode(op, p0, p1);
@@ -698,7 +717,21 @@
CHECK_EQ(expected, node->opcode());
}
- void Lower() { SimplifiedLowering(&jsgraph, jsgraph.zone()).LowerAllNodes(); }
+ void Lower() {
+ SourcePositionTable table(jsgraph.graph());
+ SimplifiedLowering(&jsgraph, jsgraph.zone(), &table).LowerAllNodes();
+ }
+
+ void LowerAllNodesAndLowerChanges() {
+ SourcePositionTable table(jsgraph.graph());
+ SimplifiedLowering(&jsgraph, jsgraph.zone(), &table).LowerAllNodes();
+
+ ChangeLowering lowering(&jsgraph);
+ GraphReducer reducer(this->zone(), this->graph());
+ reducer.AddReducer(&lowering);
+ reducer.ReduceGraph();
+ Verifier::Run(this->graph());
+ }
// Inserts the node as the return value of the graph.
Node* Return(Node* node) {
@@ -710,55 +743,43 @@
void Effect(Node* node) { ret->ReplaceInput(1, node); }
Node* ExampleWithOutput(MachineType type) {
- // TODO(titzer): use parameters with guaranteed representations.
- if (type & kTypeInt32) {
+ if (type.semantic() == MachineSemantic::kInt32) {
return graph()->NewNode(machine()->Int32Add(), jsgraph.Int32Constant(1),
jsgraph.Int32Constant(1));
- } else if (type & kTypeUint32) {
+ } else if (type.semantic() == MachineSemantic::kUint32) {
return graph()->NewNode(machine()->Word32Shr(), jsgraph.Int32Constant(1),
jsgraph.Int32Constant(1));
- } else if (type & kRepFloat64) {
+ } else if (type.representation() == MachineRepresentation::kFloat64) {
return graph()->NewNode(machine()->Float64Add(),
jsgraph.Float64Constant(1),
jsgraph.Float64Constant(1));
- } else if (type & kRepBit) {
+ } else if (type.representation() == MachineRepresentation::kBit) {
return graph()->NewNode(machine()->Word32Equal(),
jsgraph.Int32Constant(1),
jsgraph.Int32Constant(1));
- } else if (type & kRepWord64) {
+ } else if (type.representation() == MachineRepresentation::kWord64) {
return graph()->NewNode(machine()->Int64Add(), Int64Constant(1),
Int64Constant(1));
} else {
- CHECK(type & kRepTagged);
+ CHECK(type.representation() == MachineRepresentation::kTagged);
return p0;
}
}
- Node* ExampleWithTypeAndRep(Type* type, MachineType mach_type) {
- FieldAccess access = {kUntaggedBase, 0, Handle<Name>::null(), type,
- mach_type};
- // TODO(titzer): using loads here just to force the representation is ugly.
- Node* node = graph()->NewNode(simplified()->LoadField(access),
- jsgraph.IntPtrConstant(0), graph()->start(),
- graph()->start());
- NodeProperties::SetBounds(node, Bounds(type));
- return node;
- }
-
Node* Use(Node* node, MachineType type) {
- if (type & kTypeInt32) {
+ if (type.semantic() == MachineSemantic::kInt32) {
return graph()->NewNode(machine()->Int32LessThan(), node,
jsgraph.Int32Constant(1));
- } else if (type & kTypeUint32) {
+ } else if (type.semantic() == MachineSemantic::kUint32) {
return graph()->NewNode(machine()->Uint32LessThan(), node,
jsgraph.Int32Constant(1));
- } else if (type & kRepFloat64) {
+ } else if (type.representation() == MachineRepresentation::kFloat64) {
return graph()->NewNode(machine()->Float64Add(), node,
jsgraph.Float64Constant(1));
- } else if (type & kRepWord64) {
+ } else if (type.representation() == MachineRepresentation::kWord64) {
return graph()->NewNode(machine()->Int64LessThan(), node,
Int64Constant(1));
- } else if (type & kRepWord32) {
+ } else if (type.representation() == MachineRepresentation::kWord32) {
return graph()->NewNode(machine()->Word32Equal(), node,
jsgraph.Int32Constant(1));
} else {
@@ -787,54 +808,10 @@
};
-TEST(LowerAnyToBoolean_bit_bit) {
- // AnyToBoolean(x: kRepBit) used as kRepBit
- HandleAndZoneScope scope;
- Factory* f = scope.main_zone()->isolate()->factory();
- Handle<Object> zero = f->NewNumber(0);
- Handle<Object> one = f->NewNumber(1);
- Type* singleton_zero = Type::Constant(zero, scope.main_zone());
- Type* singleton_one = Type::Constant(one, scope.main_zone());
- Type* zero_one_range = Type::Range(zero, one, scope.main_zone());
- static Type* kTypes[] = {
- singleton_zero, singleton_one, zero_one_range, Type::Boolean(),
- Type::Union(Type::Boolean(), singleton_zero, scope.main_zone()),
- Type::Union(Type::Boolean(), singleton_one, scope.main_zone()),
- Type::Union(Type::Boolean(), zero_one_range, scope.main_zone())};
- for (Type* type : kTypes) {
- TestingGraph t(type);
- Node* x = t.ExampleWithTypeAndRep(type, kRepBit);
- Node* cnv = t.graph()->NewNode(t.simplified()->AnyToBoolean(), x);
- Node* use = t.Branch(cnv);
- t.Lower();
- CHECK_EQ(x, use->InputAt(0));
- }
-}
-
-
-#if V8_TURBOFAN_TARGET
-
-TEST(LowerAnyToBoolean_tagged_tagged) {
- // AnyToBoolean(x: kRepTagged) used as kRepTagged
- TestingGraph t(Type::Any());
- Node* x = t.p0;
- Node* cnv = t.graph()->NewNode(t.simplified()->AnyToBoolean(), x);
- Node* use = t.Use(cnv, kRepTagged);
- t.Return(use);
- t.Lower();
- CHECK_EQ(IrOpcode::kCall, cnv->opcode());
- CHECK_EQ(IrOpcode::kHeapConstant, cnv->InputAt(0)->opcode());
- CHECK_EQ(x, cnv->InputAt(1));
- CHECK_EQ(t.jsgraph.NoContextConstant(), cnv->InputAt(2));
-}
-
-#endif
-
-
TEST(LowerBooleanNot_bit_bit) {
// BooleanNot(x: kRepBit) used as kRepBit
TestingGraph t(Type::Boolean());
- Node* b = t.ExampleWithOutput(kRepBit);
+ Node* b = t.ExampleWithOutput(MachineType::Bool());
Node* inv = t.graph()->NewNode(t.simplified()->BooleanNot(), b);
Node* use = t.Branch(inv);
t.Lower();
@@ -849,9 +826,9 @@
TEST(LowerBooleanNot_bit_tagged) {
// BooleanNot(x: kRepBit) used as kRepTagged
TestingGraph t(Type::Boolean());
- Node* b = t.ExampleWithOutput(kRepBit);
+ Node* b = t.ExampleWithOutput(MachineType::Bool());
Node* inv = t.graph()->NewNode(t.simplified()->BooleanNot(), b);
- Node* use = t.Use(inv, kRepTagged);
+ Node* use = t.Use(inv, MachineType::AnyTagged());
t.Return(use);
t.Lower();
CHECK_EQ(IrOpcode::kChangeBitToBool, use->InputAt(0)->opcode());
@@ -883,7 +860,7 @@
TestingGraph t(Type::Boolean());
Node* b = t.p0;
Node* inv = t.graph()->NewNode(t.simplified()->BooleanNot(), b);
- Node* use = t.Use(inv, kRepTagged);
+ Node* use = t.Use(inv, MachineType::AnyTagged());
t.Return(use);
t.Lower();
CHECK_EQ(IrOpcode::kChangeBitToBool, use->InputAt(0)->opcode());
@@ -896,11 +873,11 @@
TEST(LowerBooleanToNumber_bit_int32) {
- // BooleanToNumber(x: kRepBit) used as kMachInt32
+ // BooleanToNumber(x: kRepBit) used as MachineType::Int32()
TestingGraph t(Type::Boolean());
- Node* b = t.ExampleWithOutput(kRepBit);
+ Node* b = t.ExampleWithOutput(MachineType::Bool());
Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
- Node* use = t.Use(cnv, kMachInt32);
+ Node* use = t.Use(cnv, MachineType::Int32());
t.Return(use);
t.Lower();
CHECK_EQ(b, use->InputAt(0));
@@ -908,11 +885,11 @@
TEST(LowerBooleanToNumber_tagged_int32) {
- // BooleanToNumber(x: kRepTagged) used as kMachInt32
+ // BooleanToNumber(x: kRepTagged) used as MachineType::Int32()
TestingGraph t(Type::Boolean());
Node* b = t.p0;
Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
- Node* use = t.Use(cnv, kMachInt32);
+ Node* use = t.Use(cnv, MachineType::Int32());
t.Return(use);
t.Lower();
CHECK_EQ(t.machine()->WordEqual()->opcode(), cnv->opcode());
@@ -923,28 +900,28 @@
TEST(LowerBooleanToNumber_bit_tagged) {
- // BooleanToNumber(x: kRepBit) used as kMachAnyTagged
+ // BooleanToNumber(x: kRepBit) used as MachineType::AnyTagged()
TestingGraph t(Type::Boolean());
- Node* b = t.ExampleWithOutput(kRepBit);
+ Node* b = t.ExampleWithOutput(MachineType::Bool());
Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
- Node* use = t.Use(cnv, kMachAnyTagged);
+ Node* use = t.Use(cnv, MachineType::AnyTagged());
t.Return(use);
t.Lower();
CHECK_EQ(b, use->InputAt(0)->InputAt(0));
- CHECK_EQ(IrOpcode::kChangeInt32ToTagged, use->InputAt(0)->opcode());
+ CHECK_EQ(IrOpcode::kChangeUint32ToTagged, use->InputAt(0)->opcode());
}
TEST(LowerBooleanToNumber_tagged_tagged) {
- // BooleanToNumber(x: kRepTagged) used as kMachAnyTagged
+ // BooleanToNumber(x: kRepTagged) used as MachineType::AnyTagged()
TestingGraph t(Type::Boolean());
Node* b = t.p0;
Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
- Node* use = t.Use(cnv, kMachAnyTagged);
+ Node* use = t.Use(cnv, MachineType::AnyTagged());
t.Return(use);
t.Lower();
CHECK_EQ(cnv, use->InputAt(0)->InputAt(0));
- CHECK_EQ(IrOpcode::kChangeInt32ToTagged, use->InputAt(0)->opcode());
+ CHECK_EQ(IrOpcode::kChangeUint32ToTagged, use->InputAt(0)->opcode());
CHECK_EQ(t.machine()->WordEqual()->opcode(), cnv->opcode());
CHECK(b == cnv->InputAt(0) || b == cnv->InputAt(1));
Node* c = t.jsgraph.TrueConstant();
@@ -996,11 +973,8 @@
TEST(LowerNumberAddSub_to_int32) {
HandleAndZoneScope scope;
- Factory* f = scope.main_zone()->isolate()->factory();
- Type* small_range =
- Type::Range(f->NewNumber(1), f->NewNumber(10), scope.main_zone());
- Type* large_range =
- Type::Range(f->NewNumber(-1e+13), f->NewNumber(1e+14), scope.main_zone());
+ Type* small_range = Type::Range(1, 10, scope.main_zone());
+ Type* large_range = Type::Range(-1e+13, 1e+14, scope.main_zone());
static Type* types[] = {Type::Signed32(), Type::Integral32(), small_range,
large_range};
@@ -1020,11 +994,8 @@
TEST(LowerNumberAddSub_to_uint32) {
HandleAndZoneScope scope;
- Factory* f = scope.main_zone()->isolate()->factory();
- Type* small_range =
- Type::Range(f->NewNumber(1), f->NewNumber(10), scope.main_zone());
- Type* large_range =
- Type::Range(f->NewNumber(-1e+13), f->NewNumber(1e+14), scope.main_zone());
+ Type* small_range = Type::Range(1, 10, scope.main_zone());
+ Type* large_range = Type::Range(-1e+13, 1e+14, scope.main_zone());
static Type* types[] = {Type::Signed32(), Type::Integral32(), small_range,
large_range};
@@ -1072,33 +1043,11 @@
}
-TEST(LowerNumberToInt32_to_nop) {
- // NumberToInt32(x: kRepTagged | kTypeInt32) used as kRepTagged
- TestingGraph t(Type::Signed32());
- Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), t.p0);
- Node* use = t.Use(trunc, kRepTagged);
- t.Return(use);
- t.Lower();
- CHECK_EQ(t.p0, use->InputAt(0));
-}
-
-
-TEST(LowerNumberToInt32_to_ChangeTaggedToFloat64) {
- // NumberToInt32(x: kRepTagged | kTypeInt32) used as kRepFloat64
- TestingGraph t(Type::Signed32());
- Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), t.p0);
- Node* use = t.Use(trunc, kRepFloat64);
- t.Return(use);
- t.Lower();
- CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p0, use->InputAt(0));
-}
-
-
TEST(LowerNumberToInt32_to_ChangeTaggedToInt32) {
// NumberToInt32(x: kRepTagged | kTypeInt32) used as kRepWord32
TestingGraph t(Type::Signed32());
Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), t.p0);
- Node* use = t.Use(trunc, kTypeInt32);
+ Node* use = t.Use(trunc, MachineType::Int32());
t.Return(use);
t.Lower();
CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p0, use->InputAt(0));
@@ -1106,11 +1055,11 @@
TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) {
- // NumberToInt32(x: kRepFloat64) used as kMachInt32
+ // NumberToInt32(x: kRepFloat64) used as MachineType::Int32()
TestingGraph t(Type::Number());
- Node* p0 = t.ExampleWithTypeAndRep(Type::Number(), kMachFloat64);
+ Node* p0 = t.ExampleWithOutput(MachineType::Float64());
Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), p0);
- Node* use = t.Use(trunc, kMachInt32);
+ Node* use = t.Use(trunc, MachineType::Int32());
t.Return(use);
t.Lower();
CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0));
@@ -1118,10 +1067,10 @@
TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32_with_change) {
- // NumberToInt32(x: kTypeNumber | kRepTagged) used as kMachInt32
+ // NumberToInt32(x: kTypeNumber | kRepTagged) used as MachineType::Int32()
TestingGraph t(Type::Number());
Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), t.p0);
- Node* use = t.Use(trunc, kMachInt32);
+ Node* use = t.Use(trunc, MachineType::Int32());
t.Return(use);
t.Lower();
Node* node = use->InputAt(0);
@@ -1132,33 +1081,11 @@
}
-TEST(LowerNumberToUint32_to_nop) {
- // NumberToUint32(x: kRepTagged | kTypeUint32) used as kRepTagged
- TestingGraph t(Type::Unsigned32());
- Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), t.p0);
- Node* use = t.Use(trunc, kRepTagged);
- t.Return(use);
- t.Lower();
- CHECK_EQ(t.p0, use->InputAt(0));
-}
-
-
-TEST(LowerNumberToUint32_to_ChangeTaggedToFloat64) {
- // NumberToUint32(x: kRepTagged | kTypeUint32) used as kRepWord32
- TestingGraph t(Type::Unsigned32());
- Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), t.p0);
- Node* use = t.Use(trunc, kRepFloat64);
- t.Return(use);
- t.Lower();
- CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p0, use->InputAt(0));
-}
-
-
TEST(LowerNumberToUint32_to_ChangeTaggedToUint32) {
// NumberToUint32(x: kRepTagged | kTypeUint32) used as kRepWord32
TestingGraph t(Type::Unsigned32());
Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), t.p0);
- Node* use = t.Use(trunc, kTypeUint32);
+ Node* use = t.Use(trunc, MachineType::Uint32());
t.Return(use);
t.Lower();
CheckChangeOf(IrOpcode::kChangeTaggedToUint32, t.p0, use->InputAt(0));
@@ -1166,13 +1093,13 @@
TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32) {
- // NumberToUint32(x: kRepFloat64) used as kMachUint32
+ // NumberToUint32(x: kRepFloat64) used as MachineType::Uint32()
TestingGraph t(Type::Number());
- Node* p0 = t.ExampleWithOutput(kMachFloat64);
+ Node* p0 = t.ExampleWithOutput(MachineType::Float64());
// TODO(titzer): run the typer here, or attach machine type to param.
- NodeProperties::SetBounds(p0, Bounds(Type::Number()));
+ NodeProperties::SetType(p0, Type::Number());
Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), p0);
- Node* use = t.Use(trunc, kMachUint32);
+ Node* use = t.Use(trunc, MachineType::Uint32());
t.Return(use);
t.Lower();
CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0));
@@ -1180,10 +1107,10 @@
TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_with_change) {
- // NumberToInt32(x: kTypeNumber | kRepTagged) used as kMachUint32
+ // NumberToInt32(x: kTypeNumber | kRepTagged) used as MachineType::Uint32()
TestingGraph t(Type::Number());
Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), t.p0);
- Node* use = t.Use(trunc, kMachUint32);
+ Node* use = t.Use(trunc, MachineType::Uint32());
t.Return(use);
t.Lower();
Node* node = use->InputAt(0);
@@ -1197,67 +1124,15 @@
TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_uint32) {
// NumberToUint32(x: kRepFloat64) used as kRepWord32
TestingGraph t(Type::Unsigned32());
- Node* input = t.ExampleWithTypeAndRep(Type::Number(), kMachFloat64);
+ Node* input = t.ExampleWithOutput(MachineType::Float64());
Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), input);
- Node* use = t.Use(trunc, kRepWord32);
+ Node* use = t.Use(trunc, MachineType::RepWord32());
t.Return(use);
t.Lower();
CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, input, use->InputAt(0));
}
-TEST(LowerNumberToUI32_of_Float64_used_as_word32) {
- // NumberTo(Int,Uint)32(x: kRepFloat64 | kType(Int,Uint)32) used as
- // kType(Int,Uint)32 | kRepWord32
- Type* types[] = {Type::Signed32(), Type::Unsigned32()};
- MachineType mach[] = {kTypeInt32, kTypeUint32, kMachNone};
-
- for (int i = 0; i < 2; i++) {
- for (int u = 0; u < 3; u++) {
- TestingGraph t(types[i]);
- Node* input = t.ExampleWithTypeAndRep(
- types[i], static_cast<MachineType>(kRepFloat64 | mach[i]));
- const Operator* op = i == 0 ? t.simplified()->NumberToInt32()
- : t.simplified()->NumberToUint32();
- Node* trunc = t.graph()->NewNode(op, input);
- Node* use = t.Use(trunc, static_cast<MachineType>(kRepWord32 | mach[u]));
- t.Return(use);
- t.Lower();
- IrOpcode::Value opcode = i == 0 ? IrOpcode::kChangeFloat64ToInt32
- : IrOpcode::kChangeFloat64ToUint32;
- CheckChangeOf(opcode, input, use->InputAt(0));
- }
- }
-}
-
-
-TEST(LowerNumberToUI32_of_Float64_used_as_tagged) {
- // NumberTo(Int,Uint)32(x: kRepFloat64 | kType(Int,Uint)32) used as
- // kType(Int,Uint)32 | kRepTagged
- Type* types[] = {Type::Signed32(), Type::Unsigned32(), Type::Any()};
- MachineType mach[] = {kTypeInt32, kTypeUint32, kMachNone};
-
- for (int i = 0; i < 2; i++) {
- for (int u = 0; u < 3; u++) {
- TestingGraph t(types[i]);
- Node* input = t.ExampleWithTypeAndRep(
- types[i], static_cast<MachineType>(kRepFloat64 | mach[i]));
- const Operator* op = i == 0 ? t.simplified()->NumberToInt32()
- : t.simplified()->NumberToUint32();
- Node* trunc = t.graph()->NewNode(op, input);
- // TODO(titzer): we use the store here to force the representation.
- FieldAccess access = {kTaggedBase, 0, Handle<Name>(), types[u],
- static_cast<MachineType>(mach[u] | kRepTagged)};
- Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
- trunc, t.start, t.start);
- t.Effect(store);
- t.Lower();
- CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, input, store->InputAt(2));
- }
- }
-}
-
-
TEST(LowerReferenceEqual_to_wordeq) {
TestingGraph t(Type::Any(), Type::Any());
IrOpcode::Value opcode =
@@ -1267,7 +1142,6 @@
TEST(LowerStringOps_to_call_and_compare) {
- if (Pipeline::SupportedTarget()) {
// These tests need linkage for the calls.
TestingGraph t(Type::String(), Type::String());
IrOpcode::Value compare_eq =
@@ -1276,18 +1150,18 @@
static_cast<IrOpcode::Value>(t.machine()->IntLessThan()->opcode());
IrOpcode::Value compare_le = static_cast<IrOpcode::Value>(
t.machine()->IntLessThanOrEqual()->opcode());
- t.CheckLoweringBinop(compare_eq, t.simplified()->StringEqual());
- t.CheckLoweringBinop(compare_lt, t.simplified()->StringLessThan());
- t.CheckLoweringBinop(compare_le, t.simplified()->StringLessThanOrEqual());
- t.CheckLoweringBinop(IrOpcode::kCall, t.simplified()->StringAdd());
+ t.CheckLoweringStringBinop(compare_eq, t.simplified()->StringEqual());
+ t.CheckLoweringStringBinop(compare_lt, t.simplified()->StringLessThan());
+ t.CheckLoweringStringBinop(compare_le,
+ t.simplified()->StringLessThanOrEqual());
}
-}
-void CheckChangeInsertion(IrOpcode::Value expected, MachineType from,
- MachineType to) {
+ void CheckChangeInsertion(IrOpcode::Value expected, MachineType from,
+ MachineType to, Type* type = Type::Any()) {
TestingGraph t(Type::Any());
Node* in = t.ExampleWithOutput(from);
+ NodeProperties::SetType(in, type);
Node* use = t.Use(in, to);
t.Return(use);
t.Lower();
@@ -1297,34 +1171,43 @@
TEST(InsertBasicChanges) {
- CheckChangeInsertion(IrOpcode::kChangeFloat64ToInt32, kRepFloat64,
- kTypeInt32);
- CheckChangeInsertion(IrOpcode::kChangeFloat64ToUint32, kRepFloat64,
- kTypeUint32);
- CheckChangeInsertion(IrOpcode::kChangeTaggedToInt32, kRepTagged, kTypeInt32);
- CheckChangeInsertion(IrOpcode::kChangeTaggedToUint32, kRepTagged,
- kTypeUint32);
+ CheckChangeInsertion(IrOpcode::kChangeFloat64ToInt32, MachineType::Float64(),
+ MachineType::Int32(), Type::Signed32());
+ CheckChangeInsertion(IrOpcode::kChangeFloat64ToUint32, MachineType::Float64(),
+ MachineType::Uint32(), Type::Unsigned32());
+ CheckChangeInsertion(IrOpcode::kTruncateFloat64ToInt32,
+ MachineType::Float64(), MachineType::Uint32(),
+ Type::Integral32());
+ CheckChangeInsertion(IrOpcode::kChangeTaggedToInt32, MachineType::AnyTagged(),
+ MachineType::Int32(), Type::Signed32());
+ CheckChangeInsertion(IrOpcode::kChangeTaggedToUint32,
+ MachineType::AnyTagged(), MachineType::Uint32(),
+ Type::Unsigned32());
- CheckChangeInsertion(IrOpcode::kChangeFloat64ToTagged, kRepFloat64,
- kRepTagged);
- CheckChangeInsertion(IrOpcode::kChangeTaggedToFloat64, kRepTagged,
- kRepFloat64);
+ CheckChangeInsertion(IrOpcode::kChangeFloat64ToTagged, MachineType::Float64(),
+ MachineType::AnyTagged());
+ CheckChangeInsertion(IrOpcode::kChangeTaggedToFloat64,
+ MachineType::AnyTagged(), MachineType::Float64());
- CheckChangeInsertion(IrOpcode::kChangeInt32ToFloat64, kTypeInt32,
- kRepFloat64);
- CheckChangeInsertion(IrOpcode::kChangeInt32ToTagged, kTypeInt32, kRepTagged);
+ CheckChangeInsertion(IrOpcode::kChangeInt32ToFloat64, MachineType::Int32(),
+ MachineType::Float64());
+ CheckChangeInsertion(IrOpcode::kChangeInt32ToTagged, MachineType::Int32(),
+ MachineType::AnyTagged());
- CheckChangeInsertion(IrOpcode::kChangeUint32ToFloat64, kTypeUint32,
- kRepFloat64);
- CheckChangeInsertion(IrOpcode::kChangeUint32ToTagged, kTypeUint32,
- kRepTagged);
+ CheckChangeInsertion(IrOpcode::kChangeUint32ToFloat64, MachineType::Uint32(),
+ MachineType::Float64());
+ CheckChangeInsertion(IrOpcode::kChangeUint32ToTagged, MachineType::Uint32(),
+ MachineType::AnyTagged());
}
static void CheckChangesAroundBinop(TestingGraph* t, const Operator* op,
IrOpcode::Value input_change,
IrOpcode::Value output_change) {
- Node* binop = t->graph()->NewNode(op, t->p0, t->p1);
+ Node* binop =
+ op->ControlInputCount() == 0
+ ? t->graph()->NewNode(op, t->p0, t->p1)
+ : t->graph()->NewNode(op, t->p0, t->p1, t->graph()->start());
t->Return(binop);
t->Lower();
CHECK_EQ(input_change, binop->InputAt(0)->opcode());
@@ -1427,7 +1310,8 @@
CHECK_EQ(IrOpcode::kInt32Add, mindex.node()->opcode());
CHECK(mindex.right().Is(access.header_size - access.tag()));
- const int element_size_shift = ElementSizeLog2Of(access.machine_type);
+ const int element_size_shift =
+ ElementSizeLog2Of(access.machine_type.representation());
if (element_size_shift) {
Int32BinopMatcher shl(mindex.left().node());
CHECK_EQ(IrOpcode::kWord32Shl, shl.node()->opcode());
@@ -1439,9 +1323,10 @@
}
-const MachineType kMachineReps[] = {kRepBit, kMachInt8, kMachInt16,
- kMachInt32, kMachInt64, kMachFloat64,
- kMachAnyTagged};
+const MachineType kMachineReps[] = {
+ MachineType::Int8(), MachineType::Int16(), MachineType::Int32(),
+ MachineType::Uint32(), MachineType::Int64(), MachineType::Float64(),
+ MachineType::AnyTagged()};
} // namespace
@@ -1453,43 +1338,62 @@
FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
Handle<Name>::null(), Type::Any(), kMachineReps[i]};
- Node* load =
- t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, t.start);
+ Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0,
+ t.start, t.start);
Node* use = t.Use(load, kMachineReps[i]);
t.Return(use);
- t.Lower();
+ t.LowerAllNodesAndLowerChanges();
CHECK_EQ(IrOpcode::kLoad, load->opcode());
CHECK_EQ(t.p0, load->InputAt(0));
CheckFieldAccessArithmetic(access, load);
- MachineType rep = OpParameter<MachineType>(load);
+ MachineType rep = LoadRepresentationOf(load->op());
CHECK_EQ(kMachineReps[i], rep);
}
}
TEST(LowerStoreField_to_store) {
- TestingGraph t(Type::Any(), Type::Signed32());
+ {
+ TestingGraph t(Type::Any(), Type::Signed32());
- for (size_t i = 0; i < arraysize(kMachineReps); i++) {
- FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
- Handle<Name>::null(), Type::Any(), kMachineReps[i]};
+ for (size_t i = 0; i < arraysize(kMachineReps); i++) {
+ FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
+ Handle<Name>::null(), Type::Any(), kMachineReps[i]};
- Node* val = t.ExampleWithOutput(kMachineReps[i]);
- Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
- val, t.start, t.start);
- t.Effect(store);
- t.Lower();
- CHECK_EQ(IrOpcode::kStore, store->opcode());
- CHECK_EQ(val, store->InputAt(2));
- CheckFieldAccessArithmetic(access, store);
+ Node* val = t.ExampleWithOutput(kMachineReps[i]);
+ Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
+ val, t.start, t.start);
+ t.Effect(store);
+ t.LowerAllNodesAndLowerChanges();
+ CHECK_EQ(IrOpcode::kStore, store->opcode());
+ CHECK_EQ(val, store->InputAt(2));
+ CheckFieldAccessArithmetic(access, store);
- StoreRepresentation rep = OpParameter<StoreRepresentation>(store);
- if (kMachineReps[i] & kRepTagged) {
- CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind());
+ StoreRepresentation rep = StoreRepresentationOf(store->op());
+ if (kMachineReps[i].representation() == MachineRepresentation::kTagged) {
+ CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind());
+ }
+ CHECK_EQ(kMachineReps[i].representation(), rep.representation());
}
- CHECK_EQ(kMachineReps[i], rep.machine_type());
+ }
+ {
+ HandleAndZoneScope scope;
+ Zone* z = scope.main_zone();
+ TestingGraph t(Type::Any(), Type::Intersect(Type::SignedSmall(),
+ Type::TaggedSigned(), z));
+ FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
+ Handle<Name>::null(), Type::Any(),
+ MachineType::AnyTagged()};
+ Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
+ t.p1, t.start, t.start);
+ t.Effect(store);
+ t.LowerAllNodesAndLowerChanges();
+ CHECK_EQ(IrOpcode::kStore, store->opcode());
+ CHECK_EQ(t.p1, store->InputAt(2));
+ StoreRepresentation rep = StoreRepresentationOf(store->op());
+ CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
}
}
@@ -1505,38 +1409,57 @@
t.p1, t.start, t.start);
Node* use = t.Use(load, kMachineReps[i]);
t.Return(use);
- t.Lower();
+ t.LowerAllNodesAndLowerChanges();
CHECK_EQ(IrOpcode::kLoad, load->opcode());
CHECK_EQ(t.p0, load->InputAt(0));
CheckElementAccessArithmetic(access, load);
- MachineType rep = OpParameter<MachineType>(load);
+ MachineType rep = LoadRepresentationOf(load->op());
CHECK_EQ(kMachineReps[i], rep);
}
}
TEST(LowerStoreElement_to_store) {
- TestingGraph t(Type::Any(), Type::Signed32());
+ {
+ TestingGraph t(Type::Any(), Type::Signed32());
- for (size_t i = 0; i < arraysize(kMachineReps); i++) {
- ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
- Type::Any(), kMachineReps[i]};
+ for (size_t i = 0; i < arraysize(kMachineReps); i++) {
+ ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
+ Type::Any(), kMachineReps[i]};
- Node* val = t.ExampleWithOutput(kMachineReps[i]);
- Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0,
- t.p1, val, t.start, t.start);
- t.Effect(store);
- t.Lower();
- CHECK_EQ(IrOpcode::kStore, store->opcode());
- CHECK_EQ(val, store->InputAt(2));
- CheckElementAccessArithmetic(access, store);
+ Node* val = t.ExampleWithOutput(kMachineReps[i]);
+ Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access),
+ t.p0, t.p1, val, t.start, t.start);
+ t.Effect(store);
+ t.LowerAllNodesAndLowerChanges();
+ CHECK_EQ(IrOpcode::kStore, store->opcode());
+ CHECK_EQ(val, store->InputAt(2));
+ CheckElementAccessArithmetic(access, store);
- StoreRepresentation rep = OpParameter<StoreRepresentation>(store);
- if (kMachineReps[i] & kRepTagged) {
- CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind());
+ StoreRepresentation rep = StoreRepresentationOf(store->op());
+ if (kMachineReps[i].representation() == MachineRepresentation::kTagged) {
+ CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind());
+ }
+ CHECK_EQ(kMachineReps[i].representation(), rep.representation());
}
- CHECK_EQ(kMachineReps[i], rep.machine_type());
+ }
+ {
+ HandleAndZoneScope scope;
+ Zone* z = scope.main_zone();
+ TestingGraph t(
+ Type::Any(), Type::Signed32(),
+ Type::Intersect(Type::SignedSmall(), Type::TaggedSigned(), z));
+ ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
+ Type::Any(), MachineType::AnyTagged()};
+ Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0,
+ t.p1, t.p2, t.start, t.start);
+ t.Effect(store);
+ t.LowerAllNodesAndLowerChanges();
+ CHECK_EQ(IrOpcode::kStore, store->opcode());
+ CHECK_EQ(t.p2, store->InputAt(2));
+ StoreRepresentation rep = StoreRepresentationOf(store->op());
+ CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
}
}
@@ -1546,17 +1469,15 @@
// Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k))
TestingGraph t(Type::Any(), Type::Signed32());
ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
- kMachAnyTagged};
+ MachineType::AnyTagged()};
Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0,
t.p1, t.start, t.start);
t.Return(load);
t.Lower();
- CHECK_EQ(IrOpcode::kLoad, load->opcode());
+ CHECK_EQ(IrOpcode::kLoadElement, load->opcode());
CHECK_EQ(t.p0, load->InputAt(0));
-
- Node* index = CheckElementAccessArithmetic(access, load);
- CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index);
+ CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, load->InputAt(1));
}
@@ -1565,18 +1486,16 @@
// Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val)
TestingGraph t(Type::Any(), Type::Signed32());
ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
- kMachAnyTagged};
+ MachineType::AnyTagged()};
Node* store =
t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1,
t.jsgraph.TrueConstant(), t.start, t.start);
t.Effect(store);
t.Lower();
- CHECK_EQ(IrOpcode::kStore, store->opcode());
+ CHECK_EQ(IrOpcode::kStoreElement, store->opcode());
CHECK_EQ(t.p0, store->InputAt(0));
-
- Node* index = CheckElementAccessArithmetic(access, store);
- CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, index);
+ CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, store->InputAt(1));
}
@@ -1584,13 +1503,13 @@
// TODO(titzer): test all load/store representation change insertions.
TestingGraph t(Type::Any(), Type::Signed32(), Type::Any());
ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
- kMachFloat64};
+ MachineType::Float64()};
Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0,
t.p1, t.start, t.start);
t.Return(load);
t.Lower();
- CHECK_EQ(IrOpcode::kLoad, load->opcode());
+ CHECK_EQ(IrOpcode::kLoadElement, load->opcode());
CHECK_EQ(t.p0, load->InputAt(0));
CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0));
}
@@ -1600,13 +1519,14 @@
// TODO(titzer): test all load/store representation change insertions.
TestingGraph t(Type::Any(), Type::Signed32());
FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
- Handle<Name>::null(), Type::Any(), kMachFloat64};
+ Handle<Name>::null(), Type::Any(),
+ MachineType::Float64()};
- Node* load =
- t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, t.start);
+ Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0,
+ t.start, t.start);
t.Return(load);
t.Lower();
- CHECK_EQ(IrOpcode::kLoad, load->opcode());
+ CHECK_EQ(IrOpcode::kLoadField, load->opcode());
CHECK_EQ(t.p0, load->InputAt(0));
CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0));
}
@@ -1616,7 +1536,7 @@
// TODO(titzer): test all load/store representation change insertions.
TestingGraph t(Type::Any(), Type::Signed32());
ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
- kMachFloat64};
+ MachineType::Float64()};
Node* store =
t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0,
@@ -1624,7 +1544,7 @@
t.Effect(store);
t.Lower();
- CHECK_EQ(IrOpcode::kStore, store->opcode());
+ CHECK_EQ(IrOpcode::kStoreElement, store->opcode());
CHECK_EQ(t.p0, store->InputAt(0));
CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2));
}
@@ -1634,76 +1554,59 @@
// TODO(titzer): test all load/store representation change insertions.
TestingGraph t(Type::Any(), Type::Signed32());
FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
- Handle<Name>::null(), Type::Any(), kMachFloat64};
+ Handle<Name>::null(), Type::Any(),
+ MachineType::Float64()};
Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
t.p1, t.start, t.start);
t.Effect(store);
t.Lower();
- CHECK_EQ(IrOpcode::kStore, store->opcode());
+ CHECK_EQ(IrOpcode::kStoreField, store->opcode());
CHECK_EQ(t.p0, store->InputAt(0));
- CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2));
+ CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(1));
}
TEST(UpdatePhi) {
TestingGraph t(Type::Any(), Type::Signed32());
- static const MachineType kMachineTypes[] = {kMachInt32, kMachUint32,
- kMachFloat64};
+ static const MachineType kMachineTypes[] = {
+ MachineType::Int32(), MachineType::Uint32(), MachineType::Float64()};
Type* kTypes[] = {Type::Signed32(), Type::Unsigned32(), Type::Number()};
for (size_t i = 0; i < arraysize(kMachineTypes); i++) {
FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
Handle<Name>::null(), kTypes[i], kMachineTypes[i]};
- Node* load0 =
- t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, t.start);
- Node* load1 =
- t.graph()->NewNode(t.simplified()->LoadField(access), t.p1, t.start);
- Node* phi = t.graph()->NewNode(t.common()->Phi(kMachAnyTagged, 2), load0,
- load1, t.start);
+ Node* load0 = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0,
+ t.start, t.start);
+ Node* load1 = t.graph()->NewNode(t.simplified()->LoadField(access), t.p1,
+ t.start, t.start);
+ Node* phi =
+ t.graph()->NewNode(t.common()->Phi(MachineRepresentation::kTagged, 2),
+ load0, load1, t.start);
t.Return(t.Use(phi, kMachineTypes[i]));
t.Lower();
CHECK_EQ(IrOpcode::kPhi, phi->opcode());
- CHECK_EQ(RepresentationOf(kMachineTypes[i]),
- RepresentationOf(OpParameter<MachineType>(phi)));
+ CHECK_EQ(kMachineTypes[i].representation(), PhiRepresentationOf(phi->op()));
}
}
TEST(RunNumberDivide_minus_1_TruncatingToInt32) {
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Node* num = t.NumberToInt32(t.Parameter(0));
Node* div = t.NumberDivide(num, t.jsgraph.Constant(-1));
Node* trunc = t.NumberToInt32(div);
t.Return(trunc);
- if (Pipeline::SupportedTarget()) {
- t.LowerAllNodesAndLowerChanges();
- t.GenerateCode();
+ t.LowerAllNodesAndLowerChanges();
+ t.GenerateCode();
- FOR_INT32_INPUTS(i) {
- int32_t x = 0 - *i;
- t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
- }
- }
-}
-
-
-TEST(NumberMultiply_TruncatingToInt32) {
- int32_t constants[] = {-100, -10, -1, 0, 1, 100, 1000};
-
- for (size_t i = 0; i < arraysize(constants); i++) {
- TestingGraph t(Type::Signed32());
- Node* k = t.jsgraph.Constant(constants[i]);
- Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k);
- Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mul);
- t.Return(trunc);
- t.Lower();
-
- CHECK_EQ(IrOpcode::kInt32Mul, mul->opcode());
+ FOR_INT32_INPUTS(i) {
+ int32_t x = 0 - *i;
+ t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
}
}
@@ -1713,13 +1616,12 @@
for (size_t i = 0; i < arraysize(constants); i++) {
double k = static_cast<double>(constants[i]);
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Node* num = t.NumberToInt32(t.Parameter(0));
Node* mul = t.NumberMultiply(num, t.jsgraph.Constant(k));
Node* trunc = t.NumberToInt32(mul);
t.Return(trunc);
- if (Pipeline::SupportedTarget()) {
t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
@@ -1728,7 +1630,6 @@
t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
}
}
- }
}
@@ -1737,33 +1638,30 @@
for (size_t i = 0; i < arraysize(constants); i++) {
double k = static_cast<double>(constants[i]);
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Node* num = t.NumberToUint32(t.Parameter(0));
Node* mul = t.NumberMultiply(num, t.jsgraph.Constant(k));
Node* trunc = t.NumberToUint32(mul);
t.Return(trunc);
- if (Pipeline::SupportedTarget()) {
t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
FOR_UINT32_INPUTS(i) {
uint32_t x = DoubleToUint32(static_cast<double>(*i) * k);
t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
- }
}
}
}
TEST(RunNumberDivide_2_TruncatingToUint32) {
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Node* num = t.NumberToUint32(t.Parameter(0));
Node* div = t.NumberDivide(num, t.jsgraph.Constant(2));
Node* trunc = t.NumberToUint32(div);
t.Return(trunc);
- if (Pipeline::SupportedTarget()) {
t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
@@ -1771,7 +1669,6 @@
uint32_t x = DoubleToUint32(static_cast<double>(*i / 2.0));
t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
}
- }
}
@@ -1805,7 +1702,7 @@
TestingGraph t(Type::Signed32());
Node* k = t.jsgraph.Constant(constants[i]);
Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
- Node* use = t.Use(div, kMachInt32);
+ Node* use = t.Use(div, MachineType::Int32());
t.Return(use);
t.Lower();
@@ -1819,13 +1716,12 @@
for (size_t i = 0; i < arraysize(constants); i++) {
int32_t k = constants[i];
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Node* num = t.NumberToInt32(t.Parameter(0));
Node* div = t.NumberDivide(num, t.jsgraph.Constant(k));
Node* trunc = t.NumberToInt32(div);
t.Return(trunc);
- if (Pipeline::SupportedTarget()) {
t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
@@ -1833,7 +1729,6 @@
if (*i == INT_MAX) continue; // exclude max int.
int32_t x = DoubleToInt32(static_cast<double>(*i) / k);
t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
- }
}
}
}
@@ -1846,7 +1741,7 @@
TestingGraph t(Type::Unsigned32());
Node* k = t.jsgraph.Constant(constants[i]);
Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
- Node* use = t.Use(div, kMachUint32);
+ Node* use = t.Use(div, MachineType::Uint32());
t.Return(use);
t.Lower();
@@ -1860,20 +1755,18 @@
for (size_t i = 0; i < arraysize(constants); i++) {
uint32_t k = constants[i];
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Node* num = t.NumberToUint32(t.Parameter(0));
Node* div = t.NumberDivide(num, t.jsgraph.Constant(static_cast<double>(k)));
Node* trunc = t.NumberToUint32(div);
t.Return(trunc);
- if (Pipeline::SupportedTarget()) {
t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
FOR_UINT32_INPUTS(i) {
uint32_t x = *i / k;
t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
- }
}
}
}
@@ -1884,7 +1777,7 @@
TestingGraph t(Type::Signed32());
Node* k = t.jsgraph.Constant(-1);
Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
- Node* use = t.Use(div, kMachInt32);
+ Node* use = t.Use(div, MachineType::Int32());
t.Return(use);
t.Lower();
@@ -1895,7 +1788,7 @@
TestingGraph t(Type::Signed32());
Node* k = t.jsgraph.Constant(0);
Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
- Node* use = t.Use(div, kMachInt32);
+ Node* use = t.Use(div, MachineType::Int32());
t.Return(use);
t.Lower();
@@ -1907,7 +1800,7 @@
TestingGraph t(Type::Unsigned32());
Node* k = t.jsgraph.Constant(0);
Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
- Node* use = t.Use(div, kMachUint32);
+ Node* use = t.Use(div, MachineType::Uint32());
t.Return(use);
t.Lower();
@@ -1924,7 +1817,7 @@
TestingGraph t(Type::Signed32());
Node* k = t.jsgraph.Constant(constants[i]);
Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k);
- Node* use = t.Use(mod, kMachInt32);
+ Node* use = t.Use(mod, MachineType::Int32());
t.Return(use);
t.Lower();
@@ -1938,13 +1831,12 @@
for (size_t i = 0; i < arraysize(constants); i++) {
int32_t k = constants[i];
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Node* num = t.NumberToInt32(t.Parameter(0));
Node* mod = t.NumberModulus(num, t.jsgraph.Constant(k));
Node* trunc = t.NumberToInt32(mod);
t.Return(trunc);
- if (Pipeline::SupportedTarget()) {
t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
@@ -1952,7 +1844,6 @@
if (*i == INT_MAX) continue; // exclude max int.
int32_t x = DoubleToInt32(std::fmod(static_cast<double>(*i), k));
t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
- }
}
}
}
@@ -1966,10 +1857,10 @@
Node* k = t.jsgraph.Constant(constants[i]);
Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k);
Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), mod);
- Node* ret = t.Return(trunc);
+ t.Return(trunc);
t.Lower();
- CHECK_EQ(IrOpcode::kUint32Mod, ret->InputAt(0)->opcode());
+ CHECK_EQ(IrOpcode::kUint32Mod, t.ret->InputAt(0)->InputAt(0)->opcode());
}
}
@@ -1979,21 +1870,19 @@
for (size_t i = 0; i < arraysize(constants); i++) {
uint32_t k = constants[i];
- SimplifiedLoweringTester<Object*> t(kMachAnyTagged);
+ SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Node* num = t.NumberToUint32(t.Parameter(0));
Node* mod =
t.NumberModulus(num, t.jsgraph.Constant(static_cast<double>(k)));
Node* trunc = t.NumberToUint32(mod);
t.Return(trunc);
- if (Pipeline::SupportedTarget()) {
t.LowerAllNodesAndLowerChanges();
t.GenerateCode();
FOR_UINT32_INPUTS(i) {
uint32_t x = *i % k;
t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
- }
}
}
}
@@ -2016,7 +1905,7 @@
TEST(NumberModulus_Uint32) {
const double kConstants[] = {2, 100, 1000, 1024, 2048};
- const MachineType kTypes[] = {kMachInt32, kMachUint32};
+ const MachineType kTypes[] = {MachineType::Int32(), MachineType::Uint32()};
for (auto const type : kTypes) {
for (auto const c : kConstants) {
@@ -2041,18 +1930,20 @@
Type* arg1;
Type* arg2;
MachineType use;
- MachineTypeUnion expected;
+ MachineRepresentation expected;
};
TestData test_data[] = {
- {Type::Signed32(), Type::Unsigned32(), kMachInt32,
- kRepWord32 | kTypeNumber},
- {Type::Signed32(), Type::Unsigned32(), kMachUint32,
- kRepWord32 | kTypeNumber},
- {Type::Signed32(), Type::Signed32(), kMachInt32, kMachInt32},
- {Type::Unsigned32(), Type::Unsigned32(), kMachInt32, kMachUint32},
- {Type::Number(), Type::Signed32(), kMachInt32, kMachFloat64},
- {Type::Signed32(), Type::String(), kMachInt32, kMachAnyTagged}};
+ {Type::Signed32(), Type::Unsigned32(), MachineType::Int32(),
+ MachineRepresentation::kWord32},
+ {Type::Signed32(), Type::Unsigned32(), MachineType::Uint32(),
+ MachineRepresentation::kWord32},
+ {Type::Signed32(), Type::Signed32(), MachineType::Int32(),
+ MachineRepresentation::kWord32},
+ {Type::Unsigned32(), Type::Unsigned32(), MachineType::Int32(),
+ MachineRepresentation::kWord32},
+ {Type::Number(), Type::Signed32(), MachineType::Int32(),
+ MachineRepresentation::kWord32}};
for (auto const d : test_data) {
TestingGraph t(d.arg1, d.arg2, Type::Boolean());
@@ -2062,16 +1953,20 @@
Node* fb = t.graph()->NewNode(t.common()->IfFalse(), br);
Node* m = t.graph()->NewNode(t.common()->Merge(2), tb, fb);
- Node* phi =
- t.graph()->NewNode(t.common()->Phi(kMachAnyTagged, 2), t.p0, t.p1, m);
+ Node* phi = t.graph()->NewNode(
+ t.common()->Phi(MachineRepresentation::kTagged, 2), t.p0, t.p1, m);
- Bounds phi_bounds = Bounds::Either(Bounds(d.arg1), Bounds(d.arg2), z);
- NodeProperties::SetBounds(phi, phi_bounds);
+ Type* phi_type = Type::Union(d.arg1, d.arg2, z);
+ NodeProperties::SetType(phi, phi_type);
Node* use = t.Use(phi, d.use);
t.Return(use);
t.Lower();
- CHECK_EQ(d.expected, OpParameter<MachineType>(phi));
+ CHECK_EQ(d.expected, PhiRepresentationOf(phi->op()));
}
}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/compiler/test-typer.cc b/test/cctest/compiler/test-typer.cc
deleted file mode 100644
index 5f7f55a..0000000
--- a/test/cctest/compiler/test-typer.cc
+++ /dev/null
@@ -1,380 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <functional>
-
-#include "src/codegen.h"
-#include "src/compiler/js-operator.h"
-#include "src/compiler/node-properties-inl.h"
-#include "src/compiler/typer.h"
-#include "test/cctest/cctest.h"
-#include "test/cctest/compiler/graph-builder-tester.h"
-#include "test/cctest/types-fuzz.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-
-// TODO(titzer): generate a large set of deterministic inputs for these tests.
-class TyperTester : public HandleAndZoneScope, public GraphAndBuilders {
- public:
- TyperTester()
- : GraphAndBuilders(main_zone()),
- types_(main_zone(), isolate()),
- typer_(graph(), MaybeHandle<Context>()),
- javascript_(main_zone()) {
- Node* s = graph()->NewNode(common()->Start(3));
- graph()->SetStart(s);
- context_node_ = graph()->NewNode(common()->Parameter(2), graph()->start());
- rng_ = isolate()->random_number_generator();
-
- integers.push_back(0);
- integers.push_back(0);
- integers.push_back(-1);
- integers.push_back(+1);
- integers.push_back(-V8_INFINITY);
- integers.push_back(+V8_INFINITY);
- for (int i = 0; i < 5; ++i) {
- double x = rng_->NextInt();
- integers.push_back(x);
- x *= rng_->NextInt();
- if (!IsMinusZero(x)) integers.push_back(x);
- }
-
- int32s.push_back(0);
- int32s.push_back(0);
- int32s.push_back(-1);
- int32s.push_back(+1);
- int32s.push_back(kMinInt);
- int32s.push_back(kMaxInt);
- for (int i = 0; i < 10; ++i) {
- int32s.push_back(rng_->NextInt());
- }
- }
-
- Types<Type, Type*, Zone> types_;
- Typer typer_;
- JSOperatorBuilder javascript_;
- Node* context_node_;
- v8::base::RandomNumberGenerator* rng_;
- std::vector<double> integers;
- std::vector<double> int32s;
-
- Isolate* isolate() { return main_isolate(); }
- Graph* graph() { return main_graph_; }
- CommonOperatorBuilder* common() { return &main_common_; }
-
- Node* Parameter(int index = 0) {
- return graph()->NewNode(common()->Parameter(index), graph()->start());
- }
-
- Type* TypeBinaryOp(const Operator* op, Type* lhs, Type* rhs) {
- Node* p0 = Parameter(0);
- Node* p1 = Parameter(1);
- NodeProperties::SetBounds(p0, Bounds(lhs));
- NodeProperties::SetBounds(p1, Bounds(rhs));
- Node* n = graph()->NewNode(
- op, p0, p1, context_node_, graph()->start(), graph()->start());
- return NodeProperties::GetBounds(n).upper;
- }
-
- Type* RandomRange(bool int32 = false) {
- std::vector<double>& numbers = int32 ? int32s : integers;
- double i = numbers[rng_->NextInt(static_cast<int>(numbers.size()))];
- double j = numbers[rng_->NextInt(static_cast<int>(numbers.size()))];
- return NewRange(i, j);
- }
-
- Type* NewRange(double i, double j) {
- Factory* f = isolate()->factory();
- i::Handle<i::Object> min = f->NewNumber(i);
- i::Handle<i::Object> max = f->NewNumber(j);
- if (min->Number() > max->Number()) std::swap(min, max);
- return Type::Range(min, max, main_zone());
- }
-
- double RandomInt(double min, double max) {
- switch (rng_->NextInt(4)) {
- case 0: return min;
- case 1: return max;
- default: break;
- }
- if (min == +V8_INFINITY) return +V8_INFINITY;
- if (max == -V8_INFINITY) return -V8_INFINITY;
- if (min == -V8_INFINITY && max == +V8_INFINITY) {
- return rng_->NextInt() * static_cast<double>(rng_->NextInt());
- }
- double result = nearbyint(min + (max - min) * rng_->NextDouble());
- if (IsMinusZero(result)) return 0;
- if (std::isnan(result)) return rng_->NextInt(2) ? min : max;
- DCHECK(min <= result && result <= max);
- return result;
- }
-
- double RandomInt(Type::RangeType* range) {
- return RandomInt(range->Min()->Number(), range->Max()->Number());
- }
-
- // Careful, this function runs O(max_width^5) trials.
- template <class BinaryFunction>
- void TestBinaryArithOpCloseToZero(const Operator* op, BinaryFunction opfun,
- int max_width) {
- const int min_min = -2 - max_width / 2;
- const int max_min = 2 + max_width / 2;
- for (int width = 0; width < max_width; width++) {
- for (int lmin = min_min; lmin <= max_min; lmin++) {
- for (int rmin = min_min; rmin <= max_min; rmin++) {
- Type* r1 = NewRange(lmin, lmin + width);
- Type* r2 = NewRange(rmin, rmin + width);
- Type* expected_type = TypeBinaryOp(op, r1, r2);
-
- for (int x1 = lmin; x1 < lmin + width; x1++) {
- for (int x2 = rmin; x2 < rmin + width; x2++) {
- double result_value = opfun(x1, x2);
- Type* result_type = Type::Constant(
- isolate()->factory()->NewNumber(result_value), main_zone());
- CHECK(result_type->Is(expected_type));
- }
- }
- }
- }
- }
- }
-
- template <class BinaryFunction>
- void TestBinaryArithOp(const Operator* op, BinaryFunction opfun) {
- TestBinaryArithOpCloseToZero(op, opfun, 8);
- for (int i = 0; i < 100; ++i) {
- Type::RangeType* r1 = RandomRange()->AsRange();
- Type::RangeType* r2 = RandomRange()->AsRange();
- Type* expected_type = TypeBinaryOp(op, r1, r2);
- for (int i = 0; i < 10; i++) {
- double x1 = RandomInt(r1);
- double x2 = RandomInt(r2);
- double result_value = opfun(x1, x2);
- Type* result_type = Type::Constant(
- isolate()->factory()->NewNumber(result_value), main_zone());
- CHECK(result_type->Is(expected_type));
- }
- }
- }
-
- template <class BinaryFunction>
- void TestBinaryCompareOp(const Operator* op, BinaryFunction opfun) {
- for (int i = 0; i < 100; ++i) {
- Type::RangeType* r1 = RandomRange()->AsRange();
- Type::RangeType* r2 = RandomRange()->AsRange();
- Type* expected_type = TypeBinaryOp(op, r1, r2);
- for (int i = 0; i < 10; i++) {
- double x1 = RandomInt(r1);
- double x2 = RandomInt(r2);
- bool result_value = opfun(x1, x2);
- Type* result_type =
- Type::Constant(result_value ? isolate()->factory()->true_value()
- : isolate()->factory()->false_value(),
- main_zone());
- CHECK(result_type->Is(expected_type));
- }
- }
- }
-
- template <class BinaryFunction>
- void TestBinaryBitOp(const Operator* op, BinaryFunction opfun) {
- for (int i = 0; i < 100; ++i) {
- Type::RangeType* r1 = RandomRange(true)->AsRange();
- Type::RangeType* r2 = RandomRange(true)->AsRange();
- Type* expected_type = TypeBinaryOp(op, r1, r2);
- for (int i = 0; i < 10; i++) {
- int32_t x1 = static_cast<int32_t>(RandomInt(r1));
- int32_t x2 = static_cast<int32_t>(RandomInt(r2));
- double result_value = opfun(x1, x2);
- Type* result_type = Type::Constant(
- isolate()->factory()->NewNumber(result_value), main_zone());
- CHECK(result_type->Is(expected_type));
- }
- }
- }
-
- Type* RandomSubtype(Type* type) {
- Type* subtype;
- do {
- subtype = types_.Fuzz();
- } while (!subtype->Is(type));
- return subtype;
- }
-
- void TestBinaryMonotonicity(const Operator* op) {
- for (int i = 0; i < 50; ++i) {
- Type* type1 = types_.Fuzz();
- Type* type2 = types_.Fuzz();
- Type* type = TypeBinaryOp(op, type1, type2);
- Type* subtype1 = RandomSubtype(type1);;
- Type* subtype2 = RandomSubtype(type2);;
- Type* subtype = TypeBinaryOp(op, subtype1, subtype2);
- CHECK(subtype->Is(type));
- }
- }
-};
-
-
-static int32_t shift_left(int32_t x, int32_t y) { return x << y; }
-static int32_t shift_right(int32_t x, int32_t y) { return x >> y; }
-static int32_t bit_or(int32_t x, int32_t y) { return x | y; }
-static int32_t bit_and(int32_t x, int32_t y) { return x & y; }
-static int32_t bit_xor(int32_t x, int32_t y) { return x ^ y; }
-
-
-//------------------------------------------------------------------------------
-// Soundness
-// For simplicity, we currently only test soundness on expression operators
-// that have a direct equivalent in C++. Also, testing is currently limited
-// to ranges as input types.
-
-
-TEST(TypeJSAdd) {
- TyperTester t;
- t.TestBinaryArithOp(t.javascript_.Add(), std::plus<double>());
-}
-
-
-TEST(TypeJSSubtract) {
- TyperTester t;
- t.TestBinaryArithOp(t.javascript_.Subtract(), std::minus<double>());
-}
-
-
-TEST(TypeJSMultiply) {
- TyperTester t;
- t.TestBinaryArithOp(t.javascript_.Multiply(), std::multiplies<double>());
-}
-
-
-TEST(TypeJSDivide) {
- TyperTester t;
- t.TestBinaryArithOp(t.javascript_.Divide(), std::divides<double>());
-}
-
-
-TEST(TypeJSModulus) {
- TyperTester t;
- t.TestBinaryArithOp(t.javascript_.Modulus(), modulo);
-}
-
-
-TEST(TypeJSBitwiseOr) {
- TyperTester t;
- t.TestBinaryBitOp(t.javascript_.BitwiseOr(), bit_or);
-}
-
-
-TEST(TypeJSBitwiseAnd) {
- TyperTester t;
- t.TestBinaryBitOp(t.javascript_.BitwiseAnd(), bit_and);
-}
-
-
-TEST(TypeJSBitwiseXor) {
- TyperTester t;
- t.TestBinaryBitOp(t.javascript_.BitwiseXor(), bit_xor);
-}
-
-
-TEST(TypeJSShiftLeft) {
- TyperTester t;
- t.TestBinaryBitOp(t.javascript_.ShiftLeft(), shift_left);
-}
-
-
-TEST(TypeJSShiftRight) {
- TyperTester t;
- t.TestBinaryBitOp(t.javascript_.ShiftRight(), shift_right);
-}
-
-
-TEST(TypeJSLessThan) {
- TyperTester t;
- t.TestBinaryCompareOp(t.javascript_.LessThan(), std::less<double>());
-}
-
-
-TEST(TypeJSLessThanOrEqual) {
- TyperTester t;
- t.TestBinaryCompareOp(
- t.javascript_.LessThanOrEqual(), std::less_equal<double>());
-}
-
-
-TEST(TypeJSGreaterThan) {
- TyperTester t;
- t.TestBinaryCompareOp(t.javascript_.GreaterThan(), std::greater<double>());
-}
-
-
-TEST(TypeJSGreaterThanOrEqual) {
- TyperTester t;
- t.TestBinaryCompareOp(
- t.javascript_.GreaterThanOrEqual(), std::greater_equal<double>());
-}
-
-
-TEST(TypeJSEqual) {
- TyperTester t;
- t.TestBinaryCompareOp(t.javascript_.Equal(), std::equal_to<double>());
-}
-
-
-TEST(TypeJSNotEqual) {
- TyperTester t;
- t.TestBinaryCompareOp(t.javascript_.NotEqual(), std::not_equal_to<double>());
-}
-
-
-// For numbers there's no difference between strict and non-strict equality.
-TEST(TypeJSStrictEqual) {
- TyperTester t;
- t.TestBinaryCompareOp(t.javascript_.StrictEqual(), std::equal_to<double>());
-}
-
-
-TEST(TypeJSStrictNotEqual) {
- TyperTester t;
- t.TestBinaryCompareOp(
- t.javascript_.StrictNotEqual(), std::not_equal_to<double>());
-}
-
-
-//------------------------------------------------------------------------------
-// Monotonicity
-
-
-// List should be in sync with JS_SIMPLE_BINOP_LIST.
-#define JSBINOP_LIST(V) \
- V(Equal) \
- V(NotEqual) \
- V(StrictEqual) \
- V(StrictNotEqual) \
- V(LessThan) \
- V(GreaterThan) \
- V(LessThanOrEqual) \
- V(GreaterThanOrEqual) \
- V(BitwiseOr) \
- V(BitwiseXor) \
- V(BitwiseAnd) \
- V(ShiftLeft) \
- V(ShiftRight) \
- V(ShiftRightLogical) \
- V(Add) \
- V(Subtract) \
- V(Multiply) \
- V(Divide) \
- V(Modulus)
-
-
-#define TEST_FUNC(name) \
- TEST(Monotonicity_##name) { \
- TyperTester t; \
- t.TestBinaryMonotonicity(t.javascript_.name()); \
- }
-JSBINOP_LIST(TEST_FUNC)
-#undef TEST_FUNC
diff --git a/test/cctest/compiler/value-helper.h b/test/cctest/compiler/value-helper.h
index 218a773..cbde9a7 100644
--- a/test/cctest/compiler/value-helper.h
+++ b/test/cctest/compiler/value-helper.h
@@ -5,7 +5,7 @@
#ifndef V8_CCTEST_COMPILER_VALUE_HELPER_H_
#define V8_CCTEST_COMPILER_VALUE_HELPER_H_
-#include "src/v8.h"
+#include <stdint.h>
#include "src/compiler/common-operator.h"
#include "src/compiler/node.h"
@@ -44,12 +44,12 @@
void CheckUint32Constant(int32_t expected, Node* node) {
CHECK_EQ(IrOpcode::kInt32Constant, node->opcode());
- CHECK_EQ(expected, OpParameter<uint32_t>(node));
+ CHECK_EQ(expected, OpParameter<int32_t>(node));
}
- void CheckHeapConstant(Object* expected, Node* node) {
+ void CheckHeapConstant(HeapObject* expected, Node* node) {
CHECK_EQ(IrOpcode::kHeapConstant, node->opcode());
- CHECK_EQ(expected, *OpParameter<Unique<Object> >(node).handle());
+ CHECK_EQ(expected, *OpParameter<Handle<HeapObject>>(node));
}
void CheckTrue(Node* node) {
@@ -61,55 +61,164 @@
}
static std::vector<float> float32_vector() {
+ static const float nan = std::numeric_limits<float>::quiet_NaN();
static const float kValues[] = {
- -std::numeric_limits<float>::infinity(), -2.70497e+38f, -1.4698e+37f,
- -1.22813e+35f, -1.20555e+35f, -1.34584e+34f,
- -1.0079e+32f, -6.49364e+26f, -3.06077e+25f,
- -1.46821e+25f, -1.17658e+23f, -1.9617e+22f,
- -2.7357e+20f, -1.48708e+13f, -1.89633e+12f,
- -4.66622e+11f, -2.22581e+11f, -1.45381e+10f,
- -1.3956e+09f, -1.32951e+09f, -1.30721e+09f,
- -1.19756e+09f, -9.26822e+08f, -6.35647e+08f,
- -4.00037e+08f, -1.81227e+08f, -5.09256e+07f,
- -964300.0f, -192446.0f, -28455.0f,
- -27194.0f, -26401.0f, -20575.0f,
- -17069.0f, -9167.0f, -960.178f,
- -113.0f, -62.0f, -15.0f,
- -7.0f, -0.0256635f, -4.60374e-07f,
- -3.63759e-10f, -4.30175e-14f, -5.27385e-15f,
- -1.48084e-15f, -1.05755e-19f, -3.2995e-21f,
- -1.67354e-23f, -1.11885e-23f, -1.78506e-30f,
- -5.07594e-31f, -3.65799e-31f, -1.43718e-34f,
- -1.27126e-38f, -0.0f, 0.0f,
- 1.17549e-38f, 1.56657e-37f, 4.08512e-29f,
- 3.31357e-28f, 6.25073e-22f, 4.1723e-13f,
- 1.44343e-09f, 5.27004e-08f, 9.48298e-08f,
- 5.57888e-07f, 4.89988e-05f, 0.244326f,
- 12.4895f, 19.0f, 47.0f,
- 106.0f, 538.324f, 564.536f,
- 819.124f, 7048.0f, 12611.0f,
- 19878.0f, 20309.0f, 797056.0f,
- 1.77219e+09f, 1.51116e+11f, 4.18193e+13f,
- 3.59167e+16f, 3.38211e+19f, 2.67488e+20f,
- 1.78831e+21f, 9.20914e+21f, 8.35654e+23f,
- 1.4495e+24f, 5.94015e+25f, 4.43608e+30f,
- 2.44502e+33f, 2.61152e+33f, 1.38178e+37f,
- 1.71306e+37f, 3.31899e+38f, 3.40282e+38f,
- std::numeric_limits<float>::infinity()};
+ -std::numeric_limits<float>::infinity(),
+ -2.70497e+38f,
+ -1.4698e+37f,
+ -1.22813e+35f,
+ -1.20555e+35f,
+ -1.34584e+34f,
+ -1.0079e+32f,
+ -6.49364e+26f,
+ -3.06077e+25f,
+ -1.46821e+25f,
+ -1.17658e+23f,
+ -1.9617e+22f,
+ -2.7357e+20f,
+ -9223372036854775808.0f, // INT64_MIN
+ -1.48708e+13f,
+ -1.89633e+12f,
+ -4.66622e+11f,
+ -2.22581e+11f,
+ -1.45381e+10f,
+ -1.3956e+09f,
+ -1.32951e+09f,
+ -1.30721e+09f,
+ -1.19756e+09f,
+ -9.26822e+08f,
+ -6.35647e+08f,
+ -4.00037e+08f,
+ -1.81227e+08f,
+ -5.09256e+07f,
+ -964300.0f,
+ -192446.0f,
+ -28455.0f,
+ -27194.0f,
+ -26401.0f,
+ -20575.0f,
+ -17069.0f,
+ -9167.0f,
+ -960.178f,
+ -113.0f,
+ -62.0f,
+ -15.0f,
+ -7.0f,
+ -1.0f,
+ -0.0256635f,
+ -4.60374e-07f,
+ -3.63759e-10f,
+ -4.30175e-14f,
+ -5.27385e-15f,
+ -1.48084e-15f,
+ -1.05755e-19f,
+ -3.2995e-21f,
+ -1.67354e-23f,
+ -1.11885e-23f,
+ -1.78506e-30f,
+ -5.07594e-31f,
+ -3.65799e-31f,
+ -1.43718e-34f,
+ -1.27126e-38f,
+ -0.0f,
+ 0.0f,
+ 1.17549e-38f,
+ 1.56657e-37f,
+ 4.08512e-29f,
+ 3.31357e-28f,
+ 6.25073e-22f,
+ 4.1723e-13f,
+ 1.44343e-09f,
+ 5.27004e-08f,
+ 9.48298e-08f,
+ 5.57888e-07f,
+ 4.89988e-05f,
+ 0.244326f,
+ 1.0f,
+ 12.4895f,
+ 19.0f,
+ 47.0f,
+ 106.0f,
+ 538.324f,
+ 564.536f,
+ 819.124f,
+ 7048.0f,
+ 12611.0f,
+ 19878.0f,
+ 20309.0f,
+ 797056.0f,
+ 1.77219e+09f,
+ 1.51116e+11f,
+ 4.18193e+13f,
+ 3.59167e+16f,
+ 9223372036854775807.0f, // INT64_MAX
+ 18446744073709551615.0f, // UINT64_MAX
+ 3.38211e+19f,
+ 2.67488e+20f,
+ 1.78831e+21f,
+ 9.20914e+21f,
+ 8.35654e+23f,
+ 1.4495e+24f,
+ 5.94015e+25f,
+ 4.43608e+30f,
+ 2.44502e+33f,
+ 2.61152e+33f,
+ 1.38178e+37f,
+ 1.71306e+37f,
+ 3.31899e+38f,
+ 3.40282e+38f,
+ std::numeric_limits<float>::infinity(),
+ nan,
+ -nan,
+ };
return std::vector<float>(&kValues[0], &kValues[arraysize(kValues)]);
}
static std::vector<double> float64_vector() {
- static const double nan = v8::base::OS::nan_value();
- static const double values[] = {
- 0.125, 0.25, 0.375, 0.5,
- 1.25, -1.75, 2, 5.125,
- 6.25, 0.0, -0.0, 982983.25,
- 888, 2147483647.0, -999.75, 3.1e7,
- -2e66, 3e-88, -2147483648.0, V8_INFINITY,
- -V8_INFINITY, nan, 2147483647.375, 2147483647.75,
- 2147483648.0, 2147483648.25, 2147483649.25, -2147483647.0,
- -2147483647.125, -2147483647.875, -2147483648.25, -2147483649.5};
+ static const double nan = std::numeric_limits<double>::quiet_NaN();
+ static const double values[] = {-2e66,
+ -9223373136366403584.0,
+ -9223372036854775808.0, // INT64_MIN
+ -2147483649.5,
+ -2147483648.25,
+ -2147483648.0,
+ -2147483647.875,
+ -2147483647.125,
+ -2147483647.0,
+ -999.75,
+ -2e66,
+ -1.75,
+ -1.0,
+ -0.5,
+ -0.0,
+ 0.0,
+ 3e-88,
+ 0.125,
+ 0.25,
+ 0.375,
+ 0.5,
+ 1.0,
+ 1.25,
+ 2,
+ 3.1e7,
+ 5.125,
+ 6.25,
+ 888,
+ 982983.25,
+ 2147483647.0,
+ 2147483647.375,
+ 2147483647.75,
+ 2147483648.0,
+ 2147483648.25,
+ 2147483649.25,
+ 9223372036854775807.0, // INT64_MAX
+ 9223373136366403584.0,
+ 18446744073709551615.0, // UINT64_MAX
+ 2e66,
+ V8_INFINITY,
+ -V8_INFINITY,
+ -nan,
+ nan};
return std::vector<double>(&values[0], &values[arraysize(values)]);
}
@@ -133,8 +242,44 @@
return std::vector<uint32_t>(&kValues[0], &kValues[arraysize(kValues)]);
}
+ static const std::vector<int64_t> int64_vector() {
+ std::vector<uint64_t> values = uint64_vector();
+ return std::vector<int64_t>(values.begin(), values.end());
+ }
+
+ static const std::vector<uint64_t> uint64_vector() {
+ static const uint64_t kValues[] = {
+ 0x00000000, 0x00000001, 0xffffffff,
+ 0x1b09788b, 0x04c5fce8, 0xcc0de5bf,
+ 0x00000002, 0x00000003, 0x00000004,
+ 0x00000005, 0x00000008, 0x00000009,
+ 0xffffffffffffffff, 0xfffffffffffffffe, 0xfffffffffffffffd,
+ 0x0000000000000000, 0x0000000100000000, 0xffffffff00000000,
+ 0x1b09788b00000000, 0x04c5fce800000000, 0xcc0de5bf00000000,
+ 0x0000000200000000, 0x0000000300000000, 0x0000000400000000,
+ 0x0000000500000000, 0x0000000800000000, 0x0000000900000000,
+ 0x273a798e187937a3, 0xece3af835495a16b, 0x0b668ecc11223344,
+ 0x0000009e, 0x00000043, 0x0000af73,
+ 0x0000116b, 0x00658ecc, 0x002b3b4c,
+ 0x88776655, 0x70000000, 0x07200000,
+ 0x7fffffff, 0x56123761, 0x7fffff00,
+ 0x761c4761eeeeeeee, 0x80000000eeeeeeee, 0x88888888dddddddd,
+ 0xa0000000dddddddd, 0xddddddddaaaaaaaa, 0xe0000000aaaaaaaa,
+ 0xeeeeeeeeeeeeeeee, 0xfffffffdeeeeeeee, 0xf0000000dddddddd,
+ 0x007fffffdddddddd, 0x003fffffaaaaaaaa, 0x001fffffaaaaaaaa,
+ 0x000fffff, 0x0007ffff, 0x0003ffff,
+ 0x0001ffff, 0x0000ffff, 0x00007fff,
+ 0x00003fff, 0x00001fff, 0x00000fff,
+ 0x000007ff, 0x000003ff, 0x000001ff,
+ 0x00003fffffffffff, 0x00001fffffffffff, 0x00000fffffffffff,
+ 0x000007ffffffffff, 0x000003ffffffffff, 0x000001ffffffffff,
+ 0x8000008000000000, 0x8000008000000001, 0x8000000000000400,
+ 0x8000000000000401};
+ return std::vector<uint64_t>(&kValues[0], &kValues[arraysize(kValues)]);
+ }
+
static const std::vector<double> nan_vector(size_t limit = 0) {
- static const double nan = v8::base::OS::nan_value();
+ static const double nan = std::numeric_limits<double>::quiet_NaN();
static const double values[] = {-nan, -V8_INFINITY * -0.0,
-V8_INFINITY * 0.0, V8_INFINITY * -0.0,
V8_INFINITY * 0.0, nan};
@@ -158,6 +303,8 @@
#define FOR_INT32_INPUTS(var) FOR_INPUTS(int32_t, int32, var)
#define FOR_UINT32_INPUTS(var) FOR_INPUTS(uint32_t, uint32, var)
+#define FOR_INT64_INPUTS(var) FOR_INPUTS(int64_t, int64, var)
+#define FOR_UINT64_INPUTS(var) FOR_INPUTS(uint64_t, uint64, var)
#define FOR_FLOAT32_INPUTS(var) FOR_INPUTS(float, float32, var)
#define FOR_FLOAT64_INPUTS(var) FOR_INPUTS(double, float64, var)