diff options
Diffstat (limited to 'deps/v8/test/cctest/compiler')
30 files changed, 838 insertions, 2726 deletions
diff --git a/deps/v8/test/cctest/compiler/c-signature.h b/deps/v8/test/cctest/compiler/c-signature.h index 5d161dbe7a..83b3328a3b 100644 --- a/deps/v8/test/cctest/compiler/c-signature.h +++ b/deps/v8/test/cctest/compiler/c-signature.h @@ -11,76 +11,103 @@ namespace v8 { namespace internal { namespace compiler { +#define FOREACH_CTYPE_MACHINE_TYPE_MAPPING(V) \ + V(void, kMachNone) \ + V(bool, kMachBool) \ + V(int8_t, kMachInt8) \ + V(uint8_t, kMachUint8) \ + V(int16_t, kMachInt16) \ + V(uint16_t, kMachUint16) \ + V(int32_t, kMachInt32) \ + V(uint32_t, kMachUint32) \ + V(int64_t, kMachInt64) \ + V(uint64_t, kMachUint64) \ + V(float, kMachFloat32) \ + V(double, kMachFloat64) \ + V(void*, kMachPtr) \ + V(int*, kMachPtr) + template <typename T> inline MachineType MachineTypeForC() { - CHECK(false); // Instantiated with invalid type. - return kMachNone; -} - -template <> -inline MachineType MachineTypeForC<void>() { - return kMachNone; -} - -template <> -inline MachineType MachineTypeForC<int8_t>() { - return kMachInt8; -} - -template <> -inline MachineType MachineTypeForC<uint8_t>() { - return kMachUint8; -} - -template <> -inline MachineType MachineTypeForC<int16_t>() { - return kMachInt16; -} - -template <> -inline MachineType MachineTypeForC<uint16_t>() { - return kMachUint16; -} - -template <> -inline MachineType MachineTypeForC<int32_t>() { - return kMachInt32; + while (false) { + // All other types T must be assignable to Object* + *(static_cast<Object* volatile*>(0)) = static_cast<T>(0); + } + return kMachAnyTagged; } -template <> -inline MachineType MachineTypeForC<uint32_t>() { - return kMachUint32; -} +#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<int64_t>() { - return kMachInt64; -} +// 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<uint64_t>() { - return kMachUint64; -} + 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(kMachNone, params[p]); + } + } + } -template <> -inline MachineType MachineTypeForC<double>() { - return kMachFloat64; -} + static CSignature* New(Zone* zone, MachineType ret, + MachineType p1 = kMachNone, MachineType p2 = kMachNone, + MachineType p3 = kMachNone, MachineType p4 = kMachNone, + MachineType p5 = kMachNone) { + MachineType* buffer = zone->NewArray<MachineType>(6); + int pos = 0; + size_t return_count = 0; + if (ret != kMachNone) { + 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 == kMachNone) param_count--; + if (p4 == kMachNone) param_count--; + if (p3 == kMachNone) param_count--; + if (p2 == kMachNone) param_count--; + if (p1 == kMachNone) param_count--; + for (size_t i = 0; i < param_count; i++) { + // Check that there are no kMachNone's in the middle of parameters. + CHECK_NE(kMachNone, buffer[return_count + i]); + } + return new (zone) CSignature(return_count, param_count, buffer); + } +}; -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>() != kMachNone ? 1 : 0, kParamCount, + reinterpret_cast<MachineType*>(&storage_)) { if (return_count_ == 1) storage_[0] = MachineTypeForC<Ret>(); } void Set(int index, MachineType type) { @@ -123,9 +150,11 @@ class CSignature3 : public CSignatureOf<Ret, 3> { } }; -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; +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 v8::internal::compiler diff --git a/deps/v8/test/cctest/compiler/call-tester.h b/deps/v8/test/cctest/compiler/call-tester.h index 6d8c761452..dc265ea5fa 100644 --- a/deps/v8/test/cctest/compiler/call-tester.h +++ b/deps/v8/test/cctest/compiler/call-tester.h @@ -9,6 +9,8 @@ #include "src/simulator.h" +#include "test/cctest/compiler/c-signature.h" + #if V8_TARGET_ARCH_IA32 #if __GNUC__ #define V8_CDECL __attribute__((cdecl)) @@ -23,95 +25,64 @@ namespace v8 { 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; } -}; - -template <> -struct ReturnValueTraits<int64_t> { - static int64_t Cast(uintptr_t r) { return static_cast<int64_t>(r); } - static MachineType Representation() { return kMachInt64; } -}; +inline int64_t CastReturnValue(uintptr_t r) { + return static_cast<int64_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 uint64_t CastReturnValue(uintptr_t r) { + return static_cast<uint64_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 int16_t CastReturnValue(uintptr_t r) { + return static_cast<int16_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 uint16_t CastReturnValue(uintptr_t r) { + return static_cast<uint16_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 int8_t CastReturnValue(uintptr_t r) { + return static_cast<int8_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; } -}; +inline uint8_t CastReturnValue(uintptr_t r) { + return static_cast<uint8_t>(r); +} 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 { @@ -148,42 +119,52 @@ struct ParameterTraits<uint32_t> { #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; - - // 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(); + R Call() { + typedef R V8_CDECL FType(); + csig_->VerifyParams(); + return DoCall(FUNCTION_CAST<FType*>(Generate())); } - 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]); - } + 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); } + + protected: + CSignature* csig_; + virtual byte* Generate() = 0; private: @@ -193,39 +174,38 @@ class CallHelper { 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 || V8_TARGET_ARCH_PPC64) uintptr_t CallSimulator(byte* f, int64_t p1 = 0, int64_t p2 = 0, @@ -235,31 +215,30 @@ class CallHelper { } - 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))); @@ -271,179 +250,60 @@ class CallHelper { Simulator* simulator = Simulator::current(isolate_); return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4)); } - 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))); } #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); - } -#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 { - public: - R Call() { return helper()->template Call0<R>(); } - - 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); - } - - private: - CallHelper* helper() { return static_cast<C*>(this); } -}; - } // namespace compiler } // namespace internal } // namespace v8 diff --git a/deps/v8/test/cctest/compiler/codegen-tester.h b/deps/v8/test/cctest/compiler/codegen-tester.h index f2fc48a479..bc6d938ce1 100644 --- a/deps/v8/test/cctest/compiler/codegen-tester.h +++ b/deps/v8/test/cctest/compiler/codegen-tester.h @@ -17,38 +17,26 @@ namespace v8 { 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 = kMachNone, + MachineType p1 = kMachNone, + MachineType p2 = kMachNone, + MachineType p3 = kMachNone, + MachineType p4 = kMachNone) : HandleAndZoneScope(), - CallHelper( + CallHelper<ReturnType>( main_isolate(), - MakeMachineSignature(main_zone(), return_type, p0, p1, p2, p3, p4)), - MachineAssembler( + CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0, p1, + p2, p3, p4)), + RawMachineAssembler( main_isolate(), 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), + kMachPtr, InstructionSelector::SupportedMachineOperatorFlags()) {} void CheckNumber(double expected, Object* number) { CHECK(this->isolate()->factory()->NewNumber(expected)->SameValue(number)); @@ -79,41 +67,6 @@ class MachineAssemblerTester : public HandleAndZoneScope, }; -template <typename ReturnType> -class RawMachineAssemblerTester - : public MachineAssemblerTester<RawMachineAssembler>, - public CallHelper2<ReturnType, RawMachineAssemblerTester<ReturnType> > { - 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()) {} - - 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)); - } - } - - 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)); - } - } - } -}; - - static const bool USE_RESULT_BUFFER = true; static const bool USE_RETURN_REGISTER = false; static const int32_t CHECK_VALUE = 0x99BEEDCE; diff --git a/deps/v8/test/cctest/compiler/function-tester.h b/deps/v8/test/cctest/compiler/function-tester.h index 20efd1e304..54c62ab634 100644 --- a/deps/v8/test/cctest/compiler/function-tester.h +++ b/deps/v8/test/cctest/compiler/function-tester.h @@ -34,15 +34,16 @@ class FunctionTester : public InitializedHandleScope { flags_(flags) { Compile(function); const uint32_t supported_flags = CompilationInfo::kContextSpecializing | - CompilationInfo::kBuiltinInliningEnabled | CompilationInfo::kInliningEnabled | CompilationInfo::kTypingEnabled; CHECK_EQ(0u, flags_ & ~supported_flags); } + // TODO(turbofan): generalize FunctionTester to work with N arguments. Now, it + // can handle up to four. explicit FunctionTester(Graph* graph) : isolate(main_isolate()), - function(NewFunction("(function(a,b){})")), + function(NewFunction("(function(a,b,c,d){})")), flags_(0) { CompileGraph(graph); } @@ -55,8 +56,14 @@ class FunctionTester : public InitializedHandleScope { return Execution::Call(isolate, function, undefined(), 2, args, false); } + 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, false); + } + 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()); @@ -66,7 +73,7 @@ class FunctionTester : public InitializedHandleScope { v8::Handle<v8::Message> CheckThrowsReturnMessage(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()); @@ -153,6 +160,7 @@ class FunctionTester : public InitializedHandleScope { Zone zone; ParseInfo parse_info(&zone, function); CompilationInfo info(&parse_info); + info.MarkAsDeoptimizationEnabled(); CHECK(Parser::ParseStatic(info.parse_info())); info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code())); @@ -170,11 +178,8 @@ class FunctionTester : public InitializedHandleScope { Pipeline pipeline(&info); Handle<Code> code = pipeline.GenerateCode(); - if (FLAG_turbo_deoptimization) { - info.context()->native_context()->AddOptimizedCode(*code); - } - CHECK(!code.is_null()); + info.context()->native_context()->AddOptimizedCode(*code); function->ReplaceCode(*code); #elif USE_CRANKSHAFT Handle<Code> unoptimized = Handle<Code>(function->code()); diff --git a/deps/v8/test/cctest/compiler/graph-builder-tester.h b/deps/v8/test/cctest/compiler/graph-builder-tester.h index 9a5174c1d7..7270293e0f 100644 --- a/deps/v8/test/cctest/compiler/graph-builder-tester.h +++ b/deps/v8/test/cctest/compiler/graph-builder-tester.h @@ -39,12 +39,10 @@ class GraphAndBuilders { template <typename ReturnType> -class GraphBuilderTester - : public HandleAndZoneScope, - private GraphAndBuilders, - public CallHelper, - public SimplifiedGraphBuilder, - public CallHelper2<ReturnType, GraphBuilderTester<ReturnType> > { +class GraphBuilderTester : public HandleAndZoneScope, + private GraphAndBuilders, + public CallHelper<ReturnType>, + public SimplifiedGraphBuilder { public: explicit GraphBuilderTester(MachineType p0 = kMachNone, MachineType p1 = kMachNone, @@ -52,11 +50,10 @@ class GraphBuilderTester MachineType p3 = kMachNone, MachineType p4 = kMachNone) : GraphAndBuilders(main_zone()), - CallHelper( + CallHelper<ReturnType>( main_isolate(), - MakeMachineSignature( - main_zone(), ReturnValueTraits<ReturnType>::Representation(), - p0, p1, p2, p3, p4)), + CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0, p1, + p2, p3, p4)), SimplifiedGraphBuilder(main_isolate(), main_graph_, &main_common_, &main_machine_, &main_simplified_), parameters_(main_zone()->template NewArray<Node*>(parameter_count())) { @@ -79,7 +76,7 @@ class GraphBuilderTester if (code_.is_null()) { Zone* zone = graph()->zone(); CallDescriptor* desc = - Linkage::GetSimplifiedCDescriptor(zone, machine_sig_); + Linkage::GetSimplifiedCDescriptor(zone, this->csig_); code_ = Pipeline::GenerateCodeForTesting(main_isolate(), desc, graph()); } return code_.ToHandleChecked()->entry(); @@ -92,7 +89,7 @@ class GraphBuilderTester } } - size_t parameter_count() const { return machine_sig_->parameter_count(); } + size_t parameter_count() const { return this->csig_->parameter_count(); } private: Node** parameters_; diff --git a/deps/v8/test/cctest/compiler/simplified-graph-builder.cc b/deps/v8/test/cctest/compiler/simplified-graph-builder.cc index 6afdc0a211..4d57719eff 100644 --- a/deps/v8/test/cctest/compiler/simplified-graph-builder.cc +++ b/deps/v8/test/cctest/compiler/simplified-graph-builder.cc @@ -23,7 +23,7 @@ SimplifiedGraphBuilder::SimplifiedGraphBuilder( void SimplifiedGraphBuilder::Begin(int num_parameters) { DCHECK(graph()->start() == NULL); - Node* start = graph()->NewNode(common()->Start(num_parameters)); + Node* start = graph()->NewNode(common()->Start(num_parameters + 3)); graph()->SetStart(start); effect_ = start; } @@ -37,7 +37,7 @@ void SimplifiedGraphBuilder::Return(Node* value) { void SimplifiedGraphBuilder::End() { - Node* end = graph()->NewNode(common()->End(), return_); + Node* end = graph()->NewNode(common()->End(1), return_); graph()->SetEnd(end); } diff --git a/deps/v8/test/cctest/compiler/simplified-graph-builder.h b/deps/v8/test/cctest/compiler/simplified-graph-builder.h index c9ba002c25..50c51d5ed8 100644 --- a/deps/v8/test/cctest/compiler/simplified-graph-builder.h +++ b/deps/v8/test/cctest/compiler/simplified-graph-builder.h @@ -92,9 +92,6 @@ class SimplifiedGraphBuilder : public GraphBuilder { 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); diff --git a/deps/v8/test/cctest/compiler/test-changes-lowering.cc b/deps/v8/test/cctest/compiler/test-changes-lowering.cc index d11210bb8b..04b5b9176b 100644 --- a/deps/v8/test/cctest/compiler/test-changes-lowering.cc +++ b/deps/v8/test/cctest/compiler/test-changes-lowering.cc @@ -88,7 +88,7 @@ class ChangesLoweringTester : public GraphBuilderTester<ReturnType> { 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); } @@ -104,7 +104,7 @@ class ChangesLoweringTester : public GraphBuilderTester<ReturnType> { 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); } @@ -119,18 +119,18 @@ class ChangesLoweringTester : public GraphBuilderTester<ReturnType> { 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. - Typer typer(this->isolate(), this->graph(), Handle<Context>()); + Typer typer(this->isolate(), this->graph()); typer.Run(); 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); diff --git a/deps/v8/test/cctest/compiler/test-codegen-deopt.cc b/deps/v8/test/cctest/compiler/test-codegen-deopt.cc deleted file mode 100644 index 0b59308216..0000000000 --- a/deps/v8/test/cctest/compiler/test-codegen-deopt.cc +++ /dev/null @@ -1,301 +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)), - parse_info(scope->main_zone(), function), - info(&parse_info), - bailout_id(-1), - tagged_type(1, kMachAnyTagged, zone()), - empty_types(zone()) { - CHECK(Parser::ParseStatic(&parse_info)); - info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code())); - CHECK(Compiler::Analyze(&parse_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(); } - Isolate* isolate() { return scope_->main_isolate(); } - - HandleAndZoneScope* scope_; - Handle<JSFunction> function; - ParseInfo parse_info; - CompilationInfo info; - BailoutId bailout_id; - Handle<Code> result_code; - TestInstrSeq* code; - Graph* graph; - ZoneVector<MachineType> tagged_type; - ZoneVector<MachineType> empty_types; -}; - - -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(isolate(), 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.TypedStateValues(&tagged_type), m.UndefinedConstant()); - Node* locals = m.NewNode(common.TypedStateValues(&empty_types)); - Node* stack = m.NewNode(common.TypedStateValues(&empty_types)); - - 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(isolate(), 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.TypedStateValues(&tagged_type), m.UndefinedConstant()); - Node* locals = m.NewNode(common.TypedStateValues(&empty_types)); - Node* stack = m.NewNode(common.TypedStateValues(&empty_types)); - - 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/deps/v8/test/cctest/compiler/test-control-reducer.cc b/deps/v8/test/cctest/compiler/test-control-reducer.cc deleted file mode 100644 index e969e27106..0000000000 --- a/deps/v8/test/cctest/compiler/test-control-reducer.cc +++ /dev/null @@ -1,1641 +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/all-nodes.h" -#include "src/compiler/common-operator.h" -#include "src/compiler/control-reducer.h" -#include "src/compiler/graph.h" -#include "src/compiler/js-graph.h" -#include "src/compiler/node-properties.h" - -using namespace v8::internal; -using namespace v8::internal::compiler; - -static const size_t kNumLeafs = 4; - -enum Decision { kFalse, kUnknown, kTrue }; - -// 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) { - auto const uses = a->uses(); - return std::find(uses.begin(), uses.end(), b) != uses.end(); -} - - -// A helper for all tests dealing with ControlTester. -class ControlReducerTester : HandleAndZoneScope { - public: - ControlReducerTester() - : isolate(main_isolate()), - common(main_zone()), - graph(main_zone()), - jsgraph(main_isolate(), &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); } - - // Checks one-step reduction of a phi. - void ReducePhi(Node* expect, Node* phi) { - Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, phi); - CHECK_EQ(expect, result); - ReducePhiIterative(expect, phi); // iterative should give the same result. - } - - // Checks one-step reduction of a phi. - void ReducePhiNonIterative(Node* expect, Node* phi) { - Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, phi); - CHECK_EQ(expect, 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); - CheckInputs(end, ret); - CheckInputs(ret, expect, start, start); - } - - void ReduceMerge(Node* expect, Node* merge) { - Node* result = ControlReducer::ReduceMerge(&jsgraph, 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(Decision expected, Node* branch) { - Node* control = branch->InputAt(1); - for (Node* use : branch->uses()) { - if (use->opcode() == IrOpcode::kIfTrue) { - Node* result = ControlReducer::ReduceIfNodeForTesting(&jsgraph, use); - if (expected == kTrue) CHECK_EQ(control, result); - if (expected == kFalse) CHECK_EQ(IrOpcode::kDead, result->opcode()); - if (expected == kUnknown) CHECK_EQ(use, result); - } else if (use->opcode() == IrOpcode::kIfFalse) { - Node* result = ControlReducer::ReduceIfNodeForTesting(&jsgraph, use); - if (expected == kFalse) CHECK_EQ(control, result); - if (expected == kTrue) CHECK_EQ(IrOpcode::kDead, result->opcode()); - if (expected == kUnknown) CHECK_EQ(use, result); - } else { - UNREACHABLE(); - } - } - } - - Node* Return(Node* val, Node* effect, Node* control) { - Node* ret = graph.NewNode(common.Return(), val, effect, control); - end->ReplaceInput(0, ret); - return ret; - } -}; - - -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); } -}; - - -// Helper for checking that nodes are *not* reachable from end. -struct DeadChecker { - Zone zone; - AllNodes nodes; - explicit DeadChecker(Graph* graph) : zone(), nodes(&zone, graph) {} - - void Check(Node* node) { CHECK(!nodes.IsLive(node)); } - - void Check(Diamond& d) { - Check(d.branch); - Check(d.if_true); - Check(d.if_false); - Check(d.merge); - if (d.phi != NULL) Check(d.phi); - } - - void CheckLive(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); - } - } - } -}; - - -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(!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(!phi->InputAt(0)); - CHECK(!phi->InputAt(1)); - CHECK(!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(!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(!phi->InputAt(0)); - CHECK(!phi->InputAt(1)); - CHECK(!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(!phi->InputAt(0)); - CHECK(!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(Trim_EmptyFrameState1) { - ControlReducerTester T; - - Node* node = T.jsgraph.EmptyFrameState(); - T.Trim(); - - for (Node* input : node->inputs()) { - CHECK_NOT_NULL(input); - } -} - - -TEST(Trim_EmptyFrameState2) { - ControlReducerTester T; - CheckTrimConstant(&T, T.jsgraph.EmptyFrameState()); -} - - -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.ReducePhiNonIterative(phi1, phi1); - - Node* phi2 = R.Phi(a, b, R.dead); - R.ReducePhiNonIterative(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* t1 = R.graph.NewNode(R.common.IfTrue(), R.start); - Node* t2 = R.graph.NewNode(R.common.IfTrue(), R.start); - Node* merge = R.graph.NewNode(R.common.Merge(2), t1, t2); - 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.IfTrue(), 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::ReduceMerge(&R.jsgraph, 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(!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); - } -} - - -TEST(CBranchReduce_none1) { - ControlReducerTester R; - Diamond d(R, R.p0); - R.ReduceBranch(kUnknown, d.branch); -} - - -TEST(CBranchReduce_none2) { - ControlReducerTester R; - Diamond d1(R, R.p0); - Diamond d2(R, R.p0); - d2.chain(d1); - R.ReduceBranch(kUnknown, 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]); - R.ReduceBranch(kTrue, d.branch); - } -} - - -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]); - R.ReduceBranch(kFalse, d.branch); - } -} - - -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(R.start, d2.merge); -} - - -TEST(CChainedDiamondsReduce_false_x) { - ControlReducerTester R; - Diamond d1(R, R.zero); - Diamond d2(R, R.p0); - d2.chain(d1); - - R.ReduceMergeIterative(R.start, d2.merge); -} - - -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(CUnusedDiamond1) { - ControlReducerTester R; - // if (p0) { } else { } - Node* branch = R.graph.NewNode(R.common.Branch(), R.p0, R.start); - Node* if_true = R.graph.NewNode(R.common.IfTrue(), branch); - Node* if_false = R.graph.NewNode(R.common.IfFalse(), branch); - Node* merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false); - R.ReduceMergeIterative(R.start, merge); -} - - -TEST(CUnusedDiamond2) { - ControlReducerTester R; - // if (p0) { } else { } - Node* branch = R.graph.NewNode(R.common.Branch(), R.p0, R.start); - Node* if_true = R.graph.NewNode(R.common.IfTrue(), branch); - Node* if_false = R.graph.NewNode(R.common.IfFalse(), branch); - Node* merge = R.graph.NewNode(R.common.Merge(2), if_false, if_true); - R.ReduceMergeIterative(R.start, 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); - - DeadChecker dead(&R.graph); - dead.Check(b.if_true); - dead.Check(b.if_false); - dead.Check(b.branch); - dead.Check(loop); -} - - -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); - - DeadChecker dead(&R.graph); - dead.Check(d); - dead.Check(w.loop); -} - - -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(); - - DeadChecker dead(&R.graph); - dead.Check(d.branch); - dead.Check(d.if_true); - dead.Check(d.if_false); - dead.Check(d.merge); - - 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(); - - DeadChecker dead(&R.graph); - dead.Check(d.branch); - dead.Check(d.if_true); - dead.Check(d.if_false); - dead.Check(d.merge); - dead.Check(d.phi); - - 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(); - - DeadChecker dead(&R.graph); - dead.Check(d.branch); - dead.Check(d.if_true); - dead.Check(d.if_false); - dead.Check(d.merge); - dead.Check(d.phi); - - CheckInputs(R.graph.end(), ret); - CheckInputs(ret, R.half, R.start, R.start); -} - - -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(); - - DeadChecker dead(&R.graph); - dead.Check(d); - dead.Check(effect); - - CheckInputs(R.graph.end(), ret); - CheckInputs(ret, R.p0, e1, R.start); -} - - -TEST(Return_nested_diamonds1) { - ControlReducerTester R; - Diamond d2(R, R.p0, R.one, R.zero); - Diamond d3(R, R.p0, R.one, R.zero); - 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); - - DeadChecker dead(&R.graph); - dead.CheckLive(d2); - dead.CheckLive(d3); -} - - -TEST(Return_nested_diamonds1_dead1) { - ControlReducerTester R; - Diamond d2(R, R.p0); // dead diamond - Diamond d3(R, R.p0, R.one, R.zero); - Diamond d1(R, R.p0, R.one, d3.phi); - - d2.nest(d1, true); - d3.nest(d1, false); - - Node* ret = R.Return(d1.phi, R.start, d1.merge); - - R.ReduceGraph(); - - CheckInputs(ret, d1.phi, R.start, d1.merge); - CheckInputs(d1.phi, R.one, d3.phi, d1.merge); - CheckInputs(d1.merge, d1.if_true, d3.merge); - - DeadChecker dead(&R.graph); - dead.Check(d2); // d2 was a dead diamond. - dead.CheckLive(d3); -} - - -TEST(Return_nested_diamonds1_dead2) { - ControlReducerTester R; - Diamond d2(R, R.p0); // dead diamond - Diamond d3(R, R.p0); // dead diamond - Diamond d1(R, R.p0, R.one, R.zero); - - d2.nest(d1, true); - d3.nest(d1, false); - - Node* ret = R.Return(d1.phi, R.start, d1.merge); - - R.ReduceGraph(); - - CheckInputs(ret, d1.phi, R.start, d1.merge); - CheckInputs(d1.phi, R.one, R.zero, d1.merge); - CheckInputs(d1.merge, d1.if_true, d1.if_false); - - DeadChecker dead(&R.graph); - dead.Check(d2); - dead.Check(d3); -} - - -TEST(Return_nested_diamonds_true1) { - ControlReducerTester R; - Diamond d2(R, R.p0, R.one, R.zero); - Diamond d1(R, R.one, d2.phi, 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. - - CheckInputs(ret, d2.phi, R.start, d2.merge); - CheckInputs(d2.branch, R.p0, R.start); - - DeadChecker dead(&R.graph); - dead.Check(d1); - dead.CheckLive(d2); - dead.Check(d3); -} - - -TEST(Return_nested_diamonds_false1) { - ControlReducerTester R; - Diamond d3(R, R.p0, R.one, R.zero); - Diamond d1(R, R.zero, R.one, d3.phi); - Diamond d2(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, d3.phi, R.start, d3.merge); - CheckInputs(d3.branch, R.p0, R.start); - - DeadChecker dead(&R.graph); - dead.Check(d1); - dead.Check(d2); - dead.CheckLive(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); - - DeadChecker dead(&R.graph); - dead.Check(d1); - dead.Check(d2); - dead.Check(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); - - DeadChecker dead(&R.graph); - dead.Check(d1); - dead.Check(d2); - dead.Check(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); - - DeadChecker dead(&R.graph); - dead.CheckLive(d2); - dead.CheckLive(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); - - DeadChecker dead(&R.graph); - dead.Check(d1); - dead.CheckLive(d2); - dead.Check(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); - - DeadChecker dead(&R.graph); - dead.Check(d1); - dead.Check(d2); - dead.Check(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); - - DeadChecker dead(&R.graph); - dead.Check(d1); - dead.Check(d2); - dead.Check(d3); -} diff --git a/deps/v8/test/cctest/compiler/test-js-constant-cache.cc b/deps/v8/test/cctest/compiler/test-js-constant-cache.cc index 630f911c5e..8774a9a9e3 100644 --- a/deps/v8/test/cctest/compiler/test-js-constant-cache.cc +++ b/deps/v8/test/cctest/compiler/test-js-constant-cache.cc @@ -21,7 +21,7 @@ class JSCacheTesterHelper { : main_graph_(zone), main_common_(zone), main_javascript_(zone), - main_typer_(isolate, &main_graph_, MaybeHandle<Context>()), + main_typer_(isolate, &main_graph_), main_machine_(zone) {} Graph main_graph_; CommonOperatorBuilder main_common_; @@ -41,7 +41,7 @@ class JSConstantCacheTester : public HandleAndZoneScope, JSGraph(main_isolate(), &main_graph_, &main_common_, &main_javascript_, &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_typer_.Run(); } @@ -335,7 +335,7 @@ TEST(JSGraph_GetCachedNodes_int32) { 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 @@ TEST(JSGraph_GetCachedNodes_float64) { 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 @@ TEST(JSGraph_GetCachedNodes_int64) { 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 @@ TEST(JSGraph_GetCachedNodes_number) { 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 @@ TEST(JSGraph_GetCachedNodes_external) { 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]); diff --git a/deps/v8/test/cctest/compiler/test-js-context-specialization.cc b/deps/v8/test/cctest/compiler/test-js-context-specialization.cc index 2450e7cf57..328b0aefdd 100644 --- a/deps/v8/test/cctest/compiler/test-js-context-specialization.cc +++ b/deps/v8/test/cctest/compiler/test-js-context-specialization.cc @@ -3,6 +3,7 @@ // 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.h" @@ -22,8 +23,11 @@ class ContextSpecializationTester : public HandleAndZoneScope { javascript_(main_zone()), machine_(main_zone()), simplified_(main_zone()), - jsgraph_(main_isolate(), graph(), common(), &javascript_, &machine_) {} + jsgraph_(main_isolate(), graph(), common(), &javascript_, &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_; } @@ -38,6 +42,8 @@ class ContextSpecializationTester : public HandleAndZoneScope { MachineOperatorBuilder machine_; SimplifiedOperatorBuilder simplified_; JSGraph jsgraph_; + GraphReducer reducer_; + JSContextSpecialization spec_; }; @@ -60,13 +66,12 @@ TEST(ReduceJSLoadContext) { Node* const_context = t.jsgraph()->Constant(native); Node* deep_const_context = t.jsgraph()->Constant(subcontext2); Node* param_context = t.graph()->NewNode(t.common()->Parameter(0), start); - JSContextSpecializer spec(t.jsgraph()); { // Mutable slot, constant context, depth = 0 => do nothing. Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, 0, false), const_context, const_context, start); - Reduction r = spec.ReduceJSLoadContext(load); + Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } @@ -74,7 +79,7 @@ TEST(ReduceJSLoadContext) { // Mutable slot, non-constant context, depth = 0 => do nothing. Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, 0, false), param_context, param_context, start); - Reduction r = spec.ReduceJSLoadContext(load); + Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } @@ -83,11 +88,11 @@ TEST(ReduceJSLoadContext) { 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); + HeapObjectMatcher match(new_context_input); CHECK_EQ(*native, *match.Value().handle()); ContextAccess access = OpParameter<ContextAccess>(r.replacement()); CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index())); @@ -99,11 +104,11 @@ TEST(ReduceJSLoadContext) { // Immutable slot, constant context, depth = 0 => specialize. Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true), const_context, const_context, start); - Reduction r = spec.ReduceJSLoadContext(load); + 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()); } @@ -132,13 +137,12 @@ TEST(ReduceJSStoreContext) { Node* const_context = t.jsgraph()->Constant(native); Node* deep_const_context = t.jsgraph()->Constant(subcontext2); Node* param_context = t.graph()->NewNode(t.common()->Parameter(0), start); - JSContextSpecializer spec(t.jsgraph()); { // Mutable slot, constant context, depth = 0 => do nothing. Node* load = t.graph()->NewNode(t.javascript()->StoreContext(0, 0), const_context, const_context, start); - Reduction r = spec.ReduceJSStoreContext(load); + Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } @@ -146,7 +150,7 @@ TEST(ReduceJSStoreContext) { // Mutable slot, non-constant context, depth = 0 => do nothing. Node* load = t.graph()->NewNode(t.javascript()->StoreContext(0, 0), param_context, param_context, start); - Reduction r = spec.ReduceJSStoreContext(load); + Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } @@ -154,7 +158,7 @@ TEST(ReduceJSStoreContext) { // Immutable slot, constant context, depth = 0 => do nothing. Node* load = t.graph()->NewNode(t.javascript()->StoreContext(0, slot), const_context, const_context, start); - Reduction r = spec.ReduceJSStoreContext(load); + Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } @@ -163,11 +167,11 @@ TEST(ReduceJSStoreContext) { 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); + 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); + HeapObjectMatcher match(new_context_input); CHECK_EQ(*native, *match.Value().handle()); ContextAccess access = OpParameter<ContextAccess>(r.replacement()); CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index())); @@ -197,7 +201,6 @@ TEST(SpecializeToContext) { Node* const_context = t.jsgraph()->Constant(native); Node* param_context = t.graph()->NewNode(t.common()->Parameter(0), start); - JSContextSpecializer spec(t.jsgraph()); { // Check that specialization replaces values and forwards effects @@ -222,7 +225,7 @@ TEST(SpecializeToContext) { Node* ret = t.graph()->NewNode(t.common()->Return(), add, effect_use, start); - Node* end = t.graph()->NewNode(t.common()->End(), ret); + Node* end = t.graph()->NewNode(t.common()->End(1), ret); USE(end); t.graph()->SetEnd(end); @@ -231,7 +234,9 @@ TEST(SpecializeToContext) { 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(); @@ -242,7 +247,7 @@ TEST(SpecializeToContext) { 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()); } diff --git a/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc b/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc index 92fdb6e874..e512de89b2 100644 --- a/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc +++ b/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc @@ -38,10 +38,10 @@ class JSTypedLoweringTester : public HandleAndZoneScope { simplified(main_zone()), common(main_zone()), graph(main_zone()), - typer(main_isolate(), &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))); typer.Run(); } @@ -79,17 +79,19 @@ class JSTypedLoweringTester : public HandleAndZoneScope { Node* locals = graph.NewNode(common.StateValues(0)); Node* stack = graph.NewNode(common.StateValues(0)); - Node* state_node = - graph.NewNode(common.FrameState(JS_FRAME, BailoutId::None(), - OutputFrameStateCombine::Ignore()), - parameters, locals, stack, context, UndefinedConstant()); + Node* state_node = graph.NewNode( + common.FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(), + nullptr), + parameters, locals, stack, context, UndefinedConstant()); return state_node; } Node* reduce(Node* node) { JSGraph jsgraph(main_isolate(), &graph, &common, &javascript, &machine); - JSTypedLowering reducer(&jsgraph, main_zone()); + // TODO(titzer): mock the GraphReducer here for better unit testing. + GraphReducer graph_reducer(main_zone(), &graph); + JSTypedLowering reducer(&graph_reducer, &jsgraph, main_zone()); Reduction reduction = reducer.Reduce(node); if (reduction.Changed()) return reduction.replacement(); return node; @@ -318,11 +320,11 @@ class JSBitwiseShiftTypedLoweringTester : public JSTypedLoweringTester { : JSTypedLoweringTester(), language_mode_(language_mode) { int i = 0; set(i++, javascript.ShiftLeft(language_mode_), true); - set(i++, machine.Word32Shl(), false); + set(i++, simplified.NumberShiftLeft(), false); set(i++, javascript.ShiftRight(language_mode_), true); - set(i++, machine.Word32Sar(), false); + set(i++, simplified.NumberShiftRight(), false); set(i++, javascript.ShiftRightLogical(language_mode_), false); - set(i++, machine.Word32Shr(), false); + set(i++, simplified.NumberShiftRightLogical(), false); } static const int kNumberOps = 6; const Operator* ops[kNumberOps]; @@ -362,14 +364,7 @@ TEST(Int32BitwiseShifts) { 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); } } } @@ -460,8 +455,9 @@ TEST(JSToNumber_replacement) { 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); @@ -688,18 +684,20 @@ TEST_WITH_STRONG(MixedComparison1) { for (size_t j = 0; j < arraysize(types); j++) { Node* p1 = R.Parameter(types[j], 1); { - Node* cmp = R.Binop(R.javascript.LessThan(language_mode), 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.CheckPureBinop(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.CheckPureBinop(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); } } } @@ -708,8 +706,6 @@ TEST_WITH_STRONG(MixedComparison1) { TEST_WITH_STRONG(RemoveToNumberEffects) { - FLAG_turbo_deoptimization = true; - JSTypedLoweringTester R; Node* effect_use = NULL; @@ -721,27 +717,16 @@ TEST_WITH_STRONG(RemoveToNumberEffects) { switch (i) { case 0: - if (FLAG_turbo_deoptimization) { - DCHECK(OperatorProperties::GetFrameStateInputCount( - R.javascript.ToNumber()) == 1); - effect_use = R.graph.NewNode(R.javascript.ToNumber(), p0, R.context(), - frame_state, ton, R.start()); - } else { + DCHECK(OperatorProperties::GetFrameStateInputCount( + R.javascript.ToNumber()) == 1); effect_use = R.graph.NewNode(R.javascript.ToNumber(), p0, R.context(), - ton, R.start()); - } + frame_state, ton, R.start()); break; case 1: - if (FLAG_turbo_deoptimization) { - DCHECK(OperatorProperties::GetFrameStateInputCount( - R.javascript.ToNumber()) == 1); - effect_use = - R.graph.NewNode(R.javascript.ToNumber(), ton, R.context(), - frame_state, ton, R.start()); - } else { - effect_use = R.graph.NewNode(R.javascript.ToNumber(), ton, - R.context(), ton, R.start()); - } + DCHECK(OperatorProperties::GetFrameStateInputCount( + R.javascript.ToNumber()) == 1); + effect_use = R.graph.NewNode(R.javascript.ToNumber(), ton, R.context(), + frame_state, ton, R.start()); break; case 2: effect_use = R.graph.NewNode(R.common.EffectPhi(1), ton, R.start()); @@ -950,8 +935,6 @@ TEST(OrderNumberBinopEffects1) { R.simplified.NumberMultiply(), R.javascript.Divide(LanguageMode::SLOPPY), R.simplified.NumberDivide(), - R.javascript.Modulus(LanguageMode::SLOPPY), - R.simplified.NumberModulus(), }; for (size_t j = 0; j < arraysize(ops); j += 2) { @@ -982,8 +965,6 @@ TEST(OrderNumberBinopEffects2) { R.simplified.NumberMultiply(), R.javascript.Divide(LanguageMode::SLOPPY), R.simplified.NumberDivide(), - R.javascript.Modulus(LanguageMode::SLOPPY), - R.simplified.NumberModulus(), }; for (size_t j = 0; j < arraysize(ops); j += 2) { diff --git a/deps/v8/test/cctest/compiler/test-jump-threading.cc b/deps/v8/test/cctest/compiler/test-jump-threading.cc index e0a4a2fc62..9fa3c9f28a 100644 --- a/deps/v8/test/cctest/compiler/test-jump-threading.cc +++ b/deps/v8/test/cctest/compiler/test-jump-threading.cc @@ -85,7 +85,7 @@ class TestCode : public HandleAndZoneScope { if (current_ == NULL) { current_ = new (main_zone()) InstructionBlock(main_zone(), rpo_number_, RpoNumber::Invalid(), - RpoNumber::Invalid(), deferred); + RpoNumber::Invalid(), deferred, false); blocks_.push_back(current_); sequence_.StartBlock(rpo_number_); } diff --git a/deps/v8/test/cctest/compiler/test-linkage.cc b/deps/v8/test/cctest/compiler/test-linkage.cc index 212ff3a8f2..252c43133e 100644 --- a/deps/v8/test/cctest/compiler/test-linkage.cc +++ b/deps/v8/test/cctest/compiler/test-linkage.cc @@ -34,8 +34,8 @@ static Handle<JSFunction> Compile(const char* source) { ->NewStringFromUtf8(CStrVector(source)) .ToHandleChecked(); Handle<SharedFunctionInfo> shared_function = Compiler::CompileScript( - source_code, Handle<String>(), 0, 0, false, false, Handle<Object>(), - Handle<Context>(isolate->native_context()), NULL, NULL, + 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()); @@ -114,5 +114,4 @@ TEST(TestLinkageStubCall) { // TODO(titzer): test linkage creation for outgoing stub calls. } - #endif // V8_TURBOFAN_TARGET diff --git a/deps/v8/test/cctest/compiler/test-loop-analysis.cc b/deps/v8/test/cctest/compiler/test-loop-analysis.cc index 06682ef5a9..6560ae337b 100644 --- a/deps/v8/test/cctest/compiler/test-loop-analysis.cc +++ b/deps/v8/test/cctest/compiler/test-loop-analysis.cc @@ -41,7 +41,7 @@ class LoopFinderTester : HandleAndZoneScope { graph(main_zone()), jsgraph(main_isolate(), &graph, &common, NULL, NULL), 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()), diff --git a/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc b/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc index 5f9820c72a..ad05273995 100644 --- a/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc +++ b/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc @@ -51,7 +51,7 @@ struct TestHelper : public HandleAndZoneScope { i::Variable* var = scope->Lookup(name); CHECK(var); - if (var->location() == Variable::UNALLOCATED) { + if (var->location() == VariableLocation::UNALLOCATED) { CHECK_EQ(0, expected); } else { CHECK(var->IsStackAllocated()); diff --git a/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc b/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc index beedc459e7..299f0c02ab 100644 --- a/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc +++ b/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc @@ -60,7 +60,7 @@ class ReducerTester : public HandleAndZoneScope { common(main_zone()), graph(main_zone()), javascript(main_zone()), - typer(isolate, &graph, MaybeHandle<Context>()), + typer(isolate, &graph), jsgraph(isolate, &graph, &common, &javascript, &machine), maxuint32(Constant<int32_t>(kMaxUInt32)) { Node* s = graph.NewNode(common.Start(num_parameters)); diff --git a/deps/v8/test/cctest/compiler/test-osr.cc b/deps/v8/test/cctest/compiler/test-osr.cc index d2171188f8..80dbccc633 100644 --- a/deps/v8/test/cctest/compiler/test-osr.cc +++ b/deps/v8/test/cctest/compiler/test-osr.cc @@ -51,7 +51,7 @@ class OsrDeconstructorTester : public HandleAndZoneScope { jsgraph(main_isolate(), &graph, &common, NULL, NULL), start(graph.NewNode(common.Start(1))), p0(graph.NewNode(common.Parameter(0), start)), - end(graph.NewNode(common.End(), 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))) { @@ -165,30 +165,6 @@ TEST(Deconstruct_osr1) { } -TEST(Deconstruct_osr1_type) { - OsrDeconstructorTester T(1); - - Node* loop = T.NewOsrLoop(1); - Node* osr_phi = - T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant()); - Type* type = Type::Signed32(); - NodeProperties::SetBounds(osr_phi, Bounds(type, type)); - - Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, loop); - T.graph.SetEnd(ret); - - OsrHelper helper(0, 0); - helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); - - CHECK_EQ(type, NodeProperties::GetBounds(T.osr_values[0]).lower); - CHECK_EQ(type, NodeProperties::GetBounds(T.osr_values[0]).upper); - - 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); @@ -370,14 +346,14 @@ TEST(Deconstruct_osr_nested1) { Node* outer_phi = outer.Phi(T.p0, T.p0, nullptr); outer.branch->ReplaceInput(0, outer_phi); - Node* osr_phi = inner.Phi(T.jsgraph.OneConstant(), T.osr_values[0], - T.jsgraph.ZeroConstant()); + 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(), ret); + Node* end = T.graph.NewNode(T.common.End(1), ret); T.graph.SetEnd(end); T.DeconstructOsr(); @@ -385,7 +361,7 @@ TEST(Deconstruct_osr_nested1) { // 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.ZeroConstant(), inner.loop); + 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); @@ -412,8 +388,8 @@ TEST(Deconstruct_osr_nested1) { 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.OneConstant(), T.jsgraph.ZeroConstant(), - new_inner_loop); + 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); } @@ -429,11 +405,11 @@ TEST(Deconstruct_osr_nested2) { Node* outer_phi = outer.Phi(T.p0, T.p0, T.p0); outer.branch->ReplaceInput(0, outer_phi); - Node* osr_phi = inner.Phi(T.jsgraph.OneConstant(), T.osr_values[0], - T.jsgraph.ZeroConstant()); + 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.ZeroConstant()); + 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); @@ -444,7 +420,7 @@ TEST(Deconstruct_osr_nested2) { Node* ret = T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit); - Node* end = T.graph.NewNode(T.common.End(), ret); + Node* end = T.graph.NewNode(T.common.End(1), ret); T.graph.SetEnd(end); T.DeconstructOsr(); @@ -452,7 +428,7 @@ TEST(Deconstruct_osr_nested2) { // 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.ZeroConstant(), inner.loop); + 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); @@ -465,7 +441,7 @@ TEST(Deconstruct_osr_nested2) { CHECK_NE(new_outer_phi, outer_phi); Node* new_entry_phi = FindSuccessor(new_merge, IrOpcode::kPhi); - CheckInputs(new_entry_phi, osr_phi, T.jsgraph.ZeroConstant(), new_merge); + CheckInputs(new_entry_phi, osr_phi, T.jsgraph.FalseConstant(), new_merge); CHECK_EQ(new_merge, new_outer_loop->InputAt(0)); @@ -486,10 +462,10 @@ TEST(Deconstruct_osr_nested2) { 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.OneConstant(), T.jsgraph.ZeroConstant(), - new_inner_loop); + 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.ZeroConstant(), new_outer_loop); + T.jsgraph.FalseConstant(), new_outer_loop); } @@ -523,8 +499,8 @@ TEST(Deconstruct_osr_nested3) { // middle loop. Node* loop1 = T.graph.NewNode(T.common.Loop(2), loop0.if_true, T.self); loop1->ReplaceInput(0, loop0.if_true); - Node* loop1_phi = - T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), loop0_cntr, loop0_cntr); + Node* loop1_phi = T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), loop0_cntr, + loop0_cntr, loop1); // innermost (OSR) loop. While loop2(T, T.p0, true, 1); @@ -549,7 +525,7 @@ TEST(Deconstruct_osr_nested3) { Node* ret = T.graph.NewNode(T.common.Return(), loop0_cntr, T.start, loop0.exit); - Node* end = T.graph.NewNode(T.common.End(), ret); + Node* end = T.graph.NewNode(T.common.End(1), ret); T.graph.SetEnd(end); T.DeconstructOsr(); diff --git a/deps/v8/test/cctest/compiler/test-pipeline.cc b/deps/v8/test/cctest/compiler/test-pipeline.cc index b67af6ecf7..84550d502a 100644 --- a/deps/v8/test/cctest/compiler/test-pipeline.cc +++ b/deps/v8/test/cctest/compiler/test-pipeline.cc @@ -5,23 +5,18 @@ #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" using namespace v8::internal; using namespace v8::internal::compiler; -TEST(PipelineAdd) { - HandleAndZoneScope handles; - const char* source = "(function(a,b) { return a + b; })"; +static void RunPipeline(Zone* zone, const char* source) { Handle<JSFunction> function = v8::Utils::OpenHandle( *v8::Handle<v8::Function>::Cast(CompileRun(source))); - ParseInfo parse_info(handles.main_zone(), function); + ParseInfo parse_info(zone, function); CHECK(Compiler::ParseAndAnalyze(&parse_info)); CompilationInfo info(&parse_info); @@ -34,3 +29,17 @@ TEST(PipelineAdd) { 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; })"); +} diff --git a/deps/v8/test/cctest/compiler/test-representation-change.cc b/deps/v8/test/cctest/compiler/test-representation-change.cc index 55f054a74b..216f9fd847 100644 --- a/deps/v8/test/cctest/compiler/test-representation-change.cc +++ b/deps/v8/test/cctest/compiler/test-representation-change.cc @@ -69,7 +69,7 @@ class RepresentationChangerTester : public HandleAndZoneScope, } void CheckHeapConstant(Node* n, HeapObject* expected) { - HeapObjectMatcher<HeapObject> m(n); + HeapObjectMatcher m(n); CHECK(m.HasValue()); CHECK_EQ(expected, *m.Value().handle()); } @@ -100,9 +100,9 @@ class RepresentationChangerTester : public HandleAndZoneScope, CHECK_EQ(n, c); } }; -} -} -} // namespace v8::internal::compiler +} // namespace compiler +} // namespace internal +} // namespace v8 static const MachineType all_reps[] = {kRepBit, kRepWord32, kRepWord64, diff --git a/deps/v8/test/cctest/compiler/test-run-deopt.cc b/deps/v8/test/cctest/compiler/test-run-deopt.cc index 14c024cdbc..d895924324 100644 --- a/deps/v8/test/cctest/compiler/test-run-deopt.cc +++ b/deps/v8/test/cctest/compiler/test-run-deopt.cc @@ -7,13 +7,12 @@ #include "test/cctest/cctest.h" #include "test/cctest/compiler/function-tester.h" -using namespace v8; using namespace v8::internal; using namespace v8::internal::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 +20,99 @@ static void IsOptimized(const FunctionCallbackInfo<v8::Value>& args) { static void InstallIsOptimizedHelper(v8::Isolate* isolate) { - Local<v8::Context> context = isolate->GetCurrentContext(); - Local<v8::FunctionTemplate> t = FunctionTemplate::New(isolate, IsOptimized); + v8::Local<v8::Context> context = isolate->GetCurrentContext(); + v8::Local<v8::FunctionTemplate> t = + v8::FunctionTemplate::New(isolate, IsOptimized); context->Global()->Set(v8_str("IsOptimized"), t->GetFunction()); } -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)); } + +TEST(DeoptExceptionHandlerCatch) { + FLAG_allow_natives_syntax = true; + FLAG_turbo_try_catch = 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 +} + #endif -TEST(TurboTrivialDeopt) { +TEST(DeoptTrivial) { FLAG_allow_natives_syntax = true; - FLAG_turbo_deoptimization = true; FunctionTester T( "(function foo() {" - "%DeoptimizeFunction(foo);" - "return 1; })"); + " %DeoptimizeFunction(foo);" + " return 1;" + "})"); T.CheckCall(T.Val(1)); } diff --git a/deps/v8/test/cctest/compiler/test-run-inlining.cc b/deps/v8/test/cctest/compiler/test-run-inlining.cc index a6d76e4d57..7f8ae25619 100644 --- a/deps/v8/test/cctest/compiler/test-run-inlining.cc +++ b/deps/v8/test/cctest/compiler/test-run-inlining.cc @@ -13,7 +13,7 @@ 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. void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) { StackTraceFrameIterator it(CcTest::i_isolate()); @@ -21,14 +21,17 @@ void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) { 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())->Value(), functions.length()); } @@ -40,9 +43,8 @@ void InstallAssertInlineCountHelper(v8::Isolate* isolate) { } -const uint32_t kBuiltinInlineFlags = CompilationInfo::kBuiltinInliningEnabled | - CompilationInfo::kContextSpecializing | - CompilationInfo::kTypingEnabled; +const uint32_t kRestrictedInliningFlags = + CompilationInfo::kContextSpecializing | CompilationInfo::kTypingEnabled; const uint32_t kInlineFlags = CompilationInfo::kInliningEnabled | CompilationInfo::kContextSpecializing | @@ -52,7 +54,6 @@ const uint32_t kInlineFlags = CompilationInfo::kInliningEnabled | TEST(SimpleInlining) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function(){" " function foo(s) { AssertInlineCount(2); return s; };" @@ -67,7 +68,6 @@ TEST(SimpleInlining) { TEST(SimpleInliningDeopt) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function(){" " function foo(s) { %DeoptimizeFunction(bar); return s; };" @@ -81,8 +81,21 @@ TEST(SimpleInliningDeopt) { } +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; };" @@ -97,7 +110,6 @@ TEST(SimpleInliningContext) { TEST(SimpleInliningContextDeopt) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s) {" @@ -115,7 +127,6 @@ TEST(SimpleInliningContextDeopt) { TEST(CaptureContext) { - FLAG_turbo_deoptimization = true; FunctionTester T( "var f = (function () {" " var x = 42;" @@ -133,7 +144,6 @@ TEST(CaptureContext) { // 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 () {" @@ -148,7 +158,6 @@ TEST(DontInlineEval) { TEST(InlineOmitArguments) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 42;" @@ -163,7 +172,6 @@ TEST(InlineOmitArguments) { TEST(InlineOmitArgumentsDeopt) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s,t,u,v) { AssertInlineCount(2);" @@ -181,7 +189,6 @@ TEST(InlineOmitArgumentsDeopt) { TEST(InlineSurplusArguments) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 42;" @@ -197,7 +204,6 @@ TEST(InlineSurplusArguments) { TEST(InlineSurplusArgumentsDeopt) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s) { AssertInlineCount(2); %DeoptimizeFunction(bar);" @@ -217,7 +223,6 @@ TEST(InlineSurplusArgumentsDeopt) { TEST(InlineTwice) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 42;" @@ -232,7 +237,6 @@ TEST(InlineTwice) { TEST(InlineTwiceDependent) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 42;" @@ -248,7 +252,6 @@ TEST(InlineTwiceDependent) { TEST(InlineTwiceDependentDiamond) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 41;" @@ -265,7 +268,6 @@ TEST(InlineTwiceDependentDiamond) { TEST(InlineTwiceDependentDiamondDifferent) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 41;" @@ -282,7 +284,6 @@ TEST(InlineTwiceDependentDiamondDifferent) { TEST(InlineLoopGuardedEmpty) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s) { AssertInlineCount(2); if (s) while (s); return s; };" @@ -297,7 +298,6 @@ TEST(InlineLoopGuardedEmpty) { TEST(InlineLoopGuardedOnce) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s,t) { AssertInlineCount(2); if (t > 0) while (s > 0) {" @@ -313,7 +313,6 @@ TEST(InlineLoopGuardedOnce) { TEST(InlineLoopGuardedTwice) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s,t) { AssertInlineCount(2); if (t > 0) while (s > 0) {" @@ -329,7 +328,6 @@ TEST(InlineLoopGuardedTwice) { TEST(InlineLoopUnguardedEmpty) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s) { AssertInlineCount(2); while (s); return s; };" @@ -344,7 +342,6 @@ TEST(InlineLoopUnguardedEmpty) { TEST(InlineLoopUnguardedOnce) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s) { AssertInlineCount(2); while (s) {" @@ -360,7 +357,6 @@ TEST(InlineLoopUnguardedOnce) { TEST(InlineLoopUnguardedTwice) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s) { AssertInlineCount(2); while (s > 0) {" @@ -376,7 +372,6 @@ TEST(InlineLoopUnguardedTwice) { TEST(InlineStrictIntoNonStrict) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = Object.create({}, { y: { value:42, writable:false } });" @@ -393,7 +388,6 @@ TEST(InlineStrictIntoNonStrict) { TEST(InlineNonStrictIntoStrict) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = Object.create({}, { y: { value:42, writable:false } });" @@ -409,7 +403,6 @@ TEST(InlineNonStrictIntoStrict) { TEST(InlineIntrinsicIsSmi) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 42;" @@ -424,7 +417,6 @@ TEST(InlineIntrinsicIsSmi) { TEST(InlineIntrinsicIsNonNegativeSmi) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 42;" @@ -439,7 +431,6 @@ TEST(InlineIntrinsicIsNonNegativeSmi) { TEST(InlineIntrinsicIsArray) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = [1,2,3];" @@ -474,7 +465,6 @@ TEST(InlineIntrinsicIsArray) { TEST(InlineWithArguments) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s,t,u) { AssertInlineCount(2);" @@ -494,15 +484,14 @@ TEST(InlineWithArguments) { TEST(InlineBuiltin) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s,t,u) { AssertInlineCount(2); return true; }" " function bar() { return foo(); };" - " %SetInlineBuiltinFlag(foo);" + " %SetForceInlineFlag(foo);" " return bar;" "})();", - kBuiltinInlineFlags); + kRestrictedInliningFlags); InstallAssertInlineCountHelper(CcTest::isolate()); T.CheckCall(T.true_value()); @@ -510,20 +499,80 @@ TEST(InlineBuiltin) { TEST(InlineNestedBuiltin) { - FLAG_turbo_deoptimization = true; 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(); };" - " %SetInlineBuiltinFlag(foo);" - " %SetInlineBuiltinFlag(baz);" + " %SetForceInlineFlag(foo);" + " %SetForceInlineFlag(baz);" " return bar;" "})();", - kBuiltinInlineFlags); + 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)); +} + #endif // V8_TURBOFAN_TARGET diff --git a/deps/v8/test/cctest/compiler/test-run-intrinsics.cc b/deps/v8/test/cctest/compiler/test-run-intrinsics.cc index 7fc5cc9758..1fa37748c6 100644 --- a/deps/v8/test/cctest/compiler/test-run-intrinsics.cc +++ b/deps/v8/test/cctest/compiler/test-run-intrinsics.cc @@ -12,7 +12,6 @@ uint32_t flags = CompilationInfo::kInliningEnabled; TEST(CallFunction) { - 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; }"); @@ -23,7 +22,6 @@ TEST(CallFunction) { TEST(ClassOf) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_ClassOf(a); })", flags); T.CheckCall(T.Val("Function"), T.NewObject("(function() {})")); @@ -38,7 +36,6 @@ TEST(ClassOf) { TEST(HeapObjectGetMap) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_HeapObjectGetMap(a); })", flags); Factory* factory = T.main_isolate()->factory(); @@ -58,7 +55,6 @@ static int* LookupCounter(const char* name) { TEST(IncrementStatsCounter) { - FLAG_turbo_deoptimization = true; FLAG_native_code_counters = true; reinterpret_cast<v8::Isolate*>(CcTest::InitIsolateOnce()) ->SetCounterFunction(LookupCounter); @@ -76,9 +72,9 @@ TEST(IncrementStatsCounter) { TEST(IsArray) { - FLAG_turbo_deoptimization = true; 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("({})")); @@ -90,10 +86,25 @@ TEST(IsArray) { } +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) { - FLAG_turbo_deoptimization = true; 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("({})")); @@ -106,7 +117,6 @@ TEST(IsFunction) { TEST(IsMinusZero) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_IsMinusZero(a); })", flags); T.CheckFalse(T.Val(1)); @@ -119,7 +129,6 @@ TEST(IsMinusZero) { TEST(IsNonNegativeSmi) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_IsNonNegativeSmi(a); })", flags); T.CheckTrue(T.Val(1)); @@ -132,7 +141,6 @@ TEST(IsNonNegativeSmi) { TEST(IsObject) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_IsObject(a); })", flags); T.CheckFalse(T.NewObject("(function() {})")); @@ -147,9 +155,9 @@ TEST(IsObject) { TEST(IsRegExp) { - FLAG_turbo_deoptimization = true; 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("({})")); @@ -162,20 +170,23 @@ TEST(IsRegExp) { TEST(IsSmi) { - FLAG_turbo_deoptimization = true; 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)); - T.CheckFalse(T.undefined()); } TEST(MapGetInstanceType) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function(a) { return %_MapGetInstanceType(%_HeapObjectGetMap(a)); })", flags); @@ -189,7 +200,6 @@ TEST(MapGetInstanceType) { TEST(ObjectEquals) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_ObjectEquals(a,b); })", flags); CompileRun("var o = {}"); @@ -203,7 +213,6 @@ TEST(ObjectEquals) { TEST(OneByteSeqStringGetChar) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_OneByteSeqStringGetChar(a,b); })", flags); @@ -219,7 +228,6 @@ TEST(OneByteSeqStringGetChar) { TEST(OneByteSeqStringSetChar) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { %_OneByteSeqStringSetChar(a,88,b); })", flags); @@ -236,7 +244,6 @@ TEST(OneByteSeqStringSetChar) { TEST(NewConsString) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function() { " " return %_NewConsString(14, true, 'abcdefghi', 'jklmn');" @@ -248,7 +255,6 @@ TEST(NewConsString) { TEST(SetValueOf) { - 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")); @@ -258,7 +264,6 @@ TEST(SetValueOf) { TEST(StringAdd) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_StringAdd(a,b); })", flags); T.CheckCall(T.Val("aaabbb"), T.Val("aaa"), T.Val("bbb")); @@ -268,7 +273,6 @@ TEST(StringAdd) { TEST(StringCharAt) { - 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)); @@ -278,7 +282,6 @@ TEST(StringCharAt) { TEST(StringCharCodeAt) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_StringCharCodeAt(a,b); })", flags); @@ -289,7 +292,6 @@ TEST(StringCharCodeAt) { TEST(StringCharFromCode) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_StringCharFromCode(a); })", flags); T.CheckCall(T.Val("a"), T.Val(97)); @@ -299,7 +301,6 @@ TEST(StringCharFromCode) { TEST(StringCompare) { - 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")); @@ -309,7 +310,6 @@ TEST(StringCompare) { TEST(SubString) { - 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)); @@ -319,7 +319,6 @@ TEST(SubString) { TEST(TwoByteSeqStringGetChar) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_TwoByteSeqStringGetChar(a,b); })", flags); @@ -335,7 +334,6 @@ TEST(TwoByteSeqStringGetChar) { TEST(TwoByteSeqStringSetChar) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { %_TwoByteSeqStringSetChar(a,88,b); })", flags); @@ -352,7 +350,6 @@ TEST(TwoByteSeqStringSetChar) { TEST(ValueOf) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_ValueOf(a); })", flags); T.CheckCall(T.Val("a"), T.Val("a")); diff --git a/deps/v8/test/cctest/compiler/test-run-jscalls.cc b/deps/v8/test/cctest/compiler/test-run-jscalls.cc index a622af8995..8de2d7a214 100644 --- a/deps/v8/test/cctest/compiler/test-run-jscalls.cc +++ b/deps/v8/test/cctest/compiler/test-run-jscalls.cc @@ -242,6 +242,7 @@ TEST(ContextLoadedFromActivation) { i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value); i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun); jsfun->set_code(T.function->code()); + jsfun->set_shared(T.function->shared()); context->Global()->Set(v8_str("foo"), v8::Utils::ToLocal(jsfun)); CompileRun("var x = 24;"); ExpectInt32("foo();", 24); @@ -263,6 +264,7 @@ TEST(BuiltinLoadedFromActivation) { i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value); i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun); jsfun->set_code(T.function->code()); + jsfun->set_shared(T.function->shared()); context->Global()->Set(v8_str("foo"), v8::Utils::ToLocal(jsfun)); CompileRun("var x = 24;"); ExpectObject("foo()", context->Global()); diff --git a/deps/v8/test/cctest/compiler/test-run-jsexceptions.cc b/deps/v8/test/cctest/compiler/test-run-jsexceptions.cc index 2e2e10e9de..0e1977b720 100644 --- a/deps/v8/test/cctest/compiler/test-run-jsexceptions.cc +++ b/deps/v8/test/cctest/compiler/test-run-jsexceptions.cc @@ -10,19 +10,14 @@ using namespace v8::internal; using namespace v8::internal::compiler; TEST(Throw) { - i::FLAG_turbo_exceptions = true; FunctionTester T("(function(a,b) { if (a) { throw b; } else { return b; }})"); -// TODO(mstarzinger) -#if 0 T.CheckThrows(T.true_value(), T.NewObject("new Error")); -#endif T.CheckCall(T.Val(23), T.false_value(), T.Val(23)); } TEST(ThrowMessagePosition) { - i::FLAG_turbo_exceptions = true; static const char* src = "(function(a, b) { \n" " if (a == 1) throw 1; \n" @@ -48,7 +43,6 @@ TEST(ThrowMessagePosition) { TEST(ThrowMessageDirectly) { - i::FLAG_turbo_exceptions = true; static const char* src = "(function(a, b) {" " if (a) { throw b; } else { throw new Error(b); }" @@ -56,19 +50,17 @@ TEST(ThrowMessageDirectly) { FunctionTester T(src); v8::Handle<v8::Message> message; -// TODO(mstarzinger) -#if 0 message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?")); CHECK(message->Get()->Equals(v8_str("Uncaught Error: Wat?"))); message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!")); CHECK(message->Get()->Equals(v8_str("Uncaught Kaboom!"))); -#endif } TEST(ThrowMessageIndirectly) { - i::FLAG_turbo_exceptions = true; + i::FLAG_turbo_try_catch = true; + i::FLAG_turbo_try_finally = true; static const char* src = "(function(a, b) {" " try {" @@ -80,23 +72,16 @@ TEST(ThrowMessageIndirectly) { FunctionTester T(src); v8::Handle<v8::Message> message; -// TODO(mstarzinger) -#if 0 message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?")); CHECK(message->Get()->Equals(v8_str("Uncaught Error: Wat?"))); message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!")); CHECK(message->Get()->Equals(v8_str("Uncaught Kaboom!"))); -#endif } -// TODO(mstarzinger): Increase test coverage by having similar tests within the -// mjsunit suite to also test integration with other components (e.g. OSR). - - TEST(Catch) { - i::FLAG_turbo_exceptions = true; + i::FLAG_turbo_try_catch = true; const char* src = "(function(a,b) {" " var r = '-';" @@ -115,7 +100,7 @@ TEST(Catch) { TEST(CatchNested) { - i::FLAG_turbo_exceptions = true; + i::FLAG_turbo_try_catch = true; const char* src = "(function(a,b) {" " var r = '-';" @@ -139,7 +124,7 @@ TEST(CatchNested) { TEST(CatchBreak) { - i::FLAG_turbo_exceptions = true; + i::FLAG_turbo_try_catch = true; const char* src = "(function(a,b) {" " var r = '-';" @@ -164,7 +149,7 @@ TEST(CatchBreak) { TEST(CatchCall) { - i::FLAG_turbo_exceptions = true; + i::FLAG_turbo_try_catch = true; const char* src = "(function(fun) {" " var r = '-';" @@ -186,7 +171,7 @@ TEST(CatchCall) { TEST(Finally) { - i::FLAG_turbo_exceptions = true; + i::FLAG_turbo_try_finally = true; const char* src = "(function(a,b) {" " var r = '-';" @@ -204,7 +189,7 @@ TEST(Finally) { TEST(FinallyBreak) { - i::FLAG_turbo_exceptions = true; + i::FLAG_turbo_try_finally = true; const char* src = "(function(a,b) {" " var r = '-';" @@ -228,8 +213,7 @@ TEST(FinallyBreak) { TEST(DeoptTry) { - i::FLAG_turbo_exceptions = true; - i::FLAG_turbo_deoptimization = true; + i::FLAG_turbo_try_catch = true; const char* src = "(function f(a) {" " try {" @@ -246,8 +230,7 @@ TEST(DeoptTry) { TEST(DeoptCatch) { - i::FLAG_turbo_exceptions = true; - i::FLAG_turbo_deoptimization = true; + i::FLAG_turbo_try_catch = true; const char* src = "(function f(a) {" " try {" @@ -264,8 +247,7 @@ TEST(DeoptCatch) { TEST(DeoptFinallyReturn) { - i::FLAG_turbo_exceptions = true; - i::FLAG_turbo_deoptimization = true; + i::FLAG_turbo_try_finally = true; const char* src = "(function f(a) {" " try {" @@ -282,8 +264,7 @@ TEST(DeoptFinallyReturn) { TEST(DeoptFinallyReThrow) { - i::FLAG_turbo_exceptions = true; - i::FLAG_turbo_deoptimization = true; + i::FLAG_turbo_try_finally = true; const char* src = "(function f(a) {" " try {" diff --git a/deps/v8/test/cctest/compiler/test-run-jsops.cc b/deps/v8/test/cctest/compiler/test-run-jsops.cc index 032db82db3..56ac31cbc9 100644 --- a/deps/v8/test/cctest/compiler/test-run-jsops.cc +++ b/deps/v8/test/cctest/compiler/test-run-jsops.cc @@ -523,9 +523,7 @@ TEST(RegExpLiteral) { TEST(ClassLiteral) { - FLAG_harmony_classes = true; FLAG_harmony_sloppy = true; - FLAG_harmony_object_literals = true; const char* src = "(function(a,b) {" " class C {" diff --git a/deps/v8/test/cctest/compiler/test-run-machops.cc b/deps/v8/test/cctest/compiler/test-run-machops.cc index 8d051bc90b..b1fc36968f 100644 --- a/deps/v8/test/cctest/compiler/test-run-machops.cc +++ b/deps/v8/test/cctest/compiler/test-run-machops.cc @@ -82,6 +82,63 @@ TEST(CodeGenInt32Binop) { } +#if V8_TURBOFAN_BACKEND_64 +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(kMachInt64, 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(kMachInt64, kMachInt64); + Node* a = Int64Input(&m, j); + Node* b = Int64Input(&m, k); + m.Return(m.NewNode(kOps[i], a, b)); + m.GenerateCode(); + } + } + } +} + + +// TODO(titzer): add tests that run 64-bit integer operations. +#endif // V8_TURBOFAN_BACKEND_64 + + TEST(RunGoto) { RawMachineAssemblerTester<int32_t> m; int constant = 99999; @@ -164,15 +221,14 @@ template <typename R> static void BuildDiamondPhi(RawMachineAssemblerTester<R>* m, Node* cond_node, MachineType type, Node* true_node, Node* false_node) { - MLabel blocka, blockb; - MLabel* end = m->Exit(); + MLabel 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); + m->Bind(&end); Node* phi = m->Phi(type, true_node, false_node); m->Return(phi); } @@ -237,16 +293,15 @@ TEST(RunLoopPhiConst) { Node* false_node = m.Int32Constant(false_val); // x = false_val; while(false) { x = true_val; } return x; - MLabel body, header; - MLabel* end = m.Exit(); + MLabel body, header, end; m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(kMachInt32, false_node, true_node); - m.Branch(cond_node, &body, end); + 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()); @@ -256,20 +311,19 @@ TEST(RunLoopPhiConst) { TEST(RunLoopPhiParam) { RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32, kMachInt32); - MLabel blocka, blockb; - MLabel* end = m.Exit(); + MLabel 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); + m.Branch(cond, &blockb, &end); m.Bind(&blockb); m.Goto(&blocka); - m.Bind(end); + m.Bind(&end); m.Return(phi); int32_t c1 = 0xa81903b4; @@ -287,22 +341,21 @@ TEST(RunLoopPhiInduction) { int false_val = 0x10777; // x = false_val; while(false) { x++; } return x; - MLabel header, body; - MLabel* end = m.Exit(); + MLabel 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); + 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()); @@ -314,21 +367,20 @@ TEST(RunLoopIncrement) { Int32BinopTester bt(&m); // x = 0; while(x ^ param) { x++; } return x; - MLabel header, body; - MLabel* end = m.Exit(); + MLabel 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); + 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)); @@ -342,21 +394,20 @@ TEST(RunLoopIncrement2) { Int32BinopTester bt(&m); // x = 0; while(x < param) { x++; } return x; - MLabel header, body; - MLabel* end = m.Exit(); + MLabel 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); + 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)); @@ -371,21 +422,20 @@ TEST(RunLoopIncrement3) { Int32BinopTester bt(&m); // x = 0; while(x < param) { x++; } return x; - MLabel header, body; - MLabel* end = m.Exit(); + MLabel 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); + 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)); @@ -400,20 +450,19 @@ TEST(RunLoopDecrement) { Int32BinopTester bt(&m); // x = param; while(x) { x--; } return x; - MLabel header, body; - MLabel* end = m.Exit(); + MLabel header, body, end; m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(kMachInt32, bt.param0, m.Int32Constant(0)); - m.Branch(phi, &body, end); + 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)); @@ -426,8 +475,7 @@ TEST(RunLoopIncrementFloat32) { RawMachineAssemblerTester<int32_t> m; // x = -3.0f; while(x < 10f) { x = x + 0.5f; } return (int) (double) x; - MLabel header, body; - MLabel* end = m.Exit(); + MLabel header, body, end; Node* minus_3 = m.Float32Constant(-3.0f); Node* ten = m.Float32Constant(10.0f); @@ -435,13 +483,13 @@ TEST(RunLoopIncrementFloat32) { m.Bind(&header); Node* phi = m.Phi(kMachFloat32, minus_3, ten); - m.Branch(m.Float32LessThan(phi, ten), &body, end); + 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.Bind(&end); m.Return(m.ChangeFloat64ToInt32(m.ChangeFloat32ToFloat64(phi))); CHECK_EQ(10, m.Call()); @@ -452,8 +500,7 @@ 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(); + MLabel header, body, end; Node* minus_3 = m.Float64Constant(-3.0); Node* ten = m.Float64Constant(10.0); @@ -461,13 +508,13 @@ TEST(RunLoopIncrementFloat64) { m.Bind(&header); Node* phi = m.Phi(kMachFloat64, minus_3, ten); - m.Branch(m.Float64LessThan(phi, ten), &body, end); + 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()); @@ -4395,7 +4442,7 @@ TEST(RunTestIntPtrArithmetic) { 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)); input = m.IntPtrAdd(input, elem_size); @@ -4412,7 +4459,7 @@ TEST(RunTestIntPtrArithmetic) { 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); @@ -4793,7 +4840,8 @@ TEST(RunTruncateFloat64ToInt32P) { {-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, kMachFloat64))); for (size_t i = 0; i < arraysize(kValues); ++i) { input = kValues[i].from; uint64_t expected = static_cast<int64_t>(kValues[i].raw); @@ -5080,7 +5128,7 @@ TEST(RunFloat64RoundDown1) { double input = -1.0; double result = 0.0; RawMachineAssemblerTester<int32_t> m; - if (!m.machine()->HasFloat64RoundDown()) return; + if (!m.machine()->Float64RoundDown().IsSupported()) return; m.StoreToPointer(&result, kMachFloat64, m.Float64RoundDown(m.LoadFromPointer(&input, kMachFloat64))); m.Return(m.Int32Constant(0)); @@ -5097,7 +5145,7 @@ TEST(RunFloat64RoundDown2) { double input = -1.0; double result = 0.0; RawMachineAssemblerTester<int32_t> m; - if (!m.machine()->HasFloat64RoundDown()) return; + if (!m.machine()->Float64RoundDown().IsSupported()) return; m.StoreToPointer(&result, kMachFloat64, m.Float64Sub(m.Float64Constant(-0.0), m.Float64RoundDown(m.Float64Sub( @@ -5117,7 +5165,7 @@ TEST(RunFloat64RoundTruncate) { double input = -1.0; double result = 0.0; RawMachineAssemblerTester<int32_t> m; - if (!m.machine()->HasFloat64RoundTruncate()) return; + if (!m.machine()->Float64RoundTruncate().IsSupported()) return; m.StoreToPointer( &result, kMachFloat64, m.Float64RoundTruncate(m.LoadFromPointer(&input, kMachFloat64))); @@ -5135,7 +5183,7 @@ TEST(RunFloat64RoundTiesAway) { double input = -1.0; double result = 0.0; RawMachineAssemblerTester<int32_t> m; - if (!m.machine()->HasFloat64RoundTiesAway()) return; + if (!m.machine()->Float64RoundTiesAway().IsSupported()) return; m.StoreToPointer( &result, kMachFloat64, m.Float64RoundTiesAway(m.LoadFromPointer(&input, kMachFloat64))); @@ -5148,4 +5196,83 @@ TEST(RunFloat64RoundTiesAway) { } } + +#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, kMachPtr); + m.Return(m.CallCFunction0(kMachInt32, function)); + CHECK_EQ(kMagicFoo0, m.Call()); +} + + +TEST(RunCallCFunction1) { + auto* foo1_ptr = &foo1; + RawMachineAssemblerTester<int32_t> m(kMachInt32); + Node* function = m.LoadFromPointer(&foo1_ptr, kMachPtr); + m.Return(m.CallCFunction1(kMachInt32, kMachInt32, 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(kMachInt32, kMachInt32); + Node* function = m.LoadFromPointer(&foo2_ptr, kMachPtr); + m.Return(m.CallCFunction2(kMachInt32, kMachInt32, kMachInt32, 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(kMachInt32); + Node* function = m.LoadFromPointer(&foo8_ptr, kMachPtr); + Node* param = m.Parameter(0); + m.Return(m.CallCFunction8(kMachInt32, kMachInt32, kMachInt32, kMachInt32, + kMachInt32, kMachInt32, kMachInt32, kMachInt32, + kMachInt32, 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 + #endif // V8_TURBOFAN_TARGET diff --git a/deps/v8/test/cctest/compiler/test-run-stubs.cc b/deps/v8/test/cctest/compiler/test-run-stubs.cc index c81f0f184d..9c7998d7af 100644 --- a/deps/v8/test/cctest/compiler/test-run-stubs.cc +++ b/deps/v8/test/cctest/compiler/test-run-stubs.cc @@ -6,7 +6,10 @@ #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/parser.h" #include "test/cctest/compiler/function-tester.h" @@ -17,60 +20,54 @@ using namespace v8::internal; using namespace v8::internal::compiler; -static Handle<JSFunction> GetFunction(Isolate* isolate, const char* name) { - v8::ExtensionConfiguration no_extensions; - Handle<Context> ctx = isolate->bootstrapper()->CreateEnvironment( - MaybeHandle<JSGlobalProxy>(), v8::Handle<v8::ObjectTemplate>(), - &no_extensions); - Handle<JSBuiltinsObject> builtins = handle(ctx->builtins()); - MaybeHandle<Object> fun = Object::GetProperty(isolate, builtins, name); - Handle<JSFunction> function = Handle<JSFunction>::cast(fun.ToHandleChecked()); - // Just to make sure nobody calls this... - function->set_code(isolate->builtins()->builtin(Builtins::kIllegal)); - return function; -} - - -class StringLengthStubTF : public CodeStub { - public: - explicit StringLengthStubTF(Isolate* isolate) : CodeStub(isolate) {} +TEST(RunMathFloorStub) { + HandleAndZoneScope scope; + Isolate* isolate = scope.main_isolate(); - StringLengthStubTF(uint32_t key, Isolate* isolate) : CodeStub(key, isolate) {} + // Create code and an accompanying descriptor. + MathFloorStub stub(isolate); + Handle<Code> code = stub.GenerateCode(); + Zone* zone = scope.main_zone(); - CallInterfaceDescriptor GetCallInterfaceDescriptor() override { - return LoadDescriptor(isolate()); - }; + CompilationInfo info(&stub, isolate, zone); + CallDescriptor* descriptor = Linkage::ComputeIncoming(zone, &info); - Handle<Code> GenerateCode() override { - Zone zone; - // Build a "hybrid" CompilationInfo for a JSFunction/CodeStub pair. - ParseInfo parse_info(&zone, GetFunction(isolate(), "STRING_LENGTH_STUB")); - CompilationInfo info(&parse_info); - info.SetStub(this); - // Run a "mini pipeline", extracted from compiler.cc. - CHECK(Parser::ParseStatic(info.parse_info())); - CHECK(Compiler::Analyze(info.parse_info())); - return Pipeline(&info).GenerateCode(); - } + // Create a function to call the code using the descriptor. + Graph graph(zone); + CommonOperatorBuilder common(zone); + JSOperatorBuilder javascript(zone); + MachineOperatorBuilder machine(zone); + JSGraph js(isolate, &graph, &common, &javascript, &machine); - Major MajorKey() const override { return StringLength; }; - Code::Kind GetCodeKind() const override { return Code::HANDLER; } - InlineCacheState GetICState() const override { return MONOMORPHIC; } - ExtraICState GetExtraICState() const override { return Code::LOAD_IC; } - Code::StubType GetStubType() const override { return Code::FAST; } + // FunctionTester (ab)uses a 2-argument function + Node* start = graph.NewNode(common.Start(4)); + // Parameter 0 is the number to round + Node* numberParam = graph.NewNode(common.Parameter(1), start); + Unique<HeapObject> u = Unique<HeapObject>::CreateImmovable(code); + Node* theCode = graph.NewNode(common.HeapConstant(u)); + Node* dummyContext = graph.NewNode(common.NumberConstant(0.0)); + Node* call = graph.NewNode(common.Call(descriptor), theCode, + js.UndefinedConstant(), js.UndefinedConstant(), + numberParam, 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); - private: - DISALLOW_COPY_AND_ASSIGN(StringLengthStubTF); -}; + Handle<Object> value = ft.Val(1.5); + Handle<Object> result = ft.Call(value, value).ToHandleChecked(); + CHECK_EQ(1, Smi::cast(*result)->value()); +} -TEST(RunStringLengthStubTF) { +TEST(RunStringLengthTFStub) { HandleAndZoneScope scope; Isolate* isolate = scope.main_isolate(); Zone* zone = scope.main_zone(); // Create code and an accompanying descriptor. - StringLengthStubTF stub(isolate); + StringLengthTFStub stub(isolate); Handle<Code> code = stub.GenerateCode(); CompilationInfo info(&stub, isolate, zone); CallDescriptor* descriptor = Linkage::ComputeIncoming(zone, &info); @@ -78,18 +75,21 @@ TEST(RunStringLengthStubTF) { // Create a function to call the code using the descriptor. Graph graph(zone); CommonOperatorBuilder common(zone); - // FunctionTester (ab)uses a 2-argument function - Node* start = graph.NewNode(common.Start(2)); + // 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); Unique<HeapObject> u = Unique<HeapObject>::CreateImmovable(code); Node* theCode = graph.NewNode(common.HeapConstant(u)); Node* dummyContext = graph.NewNode(common.NumberConstant(0.0)); - Node* call = graph.NewNode(common.Call(descriptor), theCode, receiverParam, - nameParam, dummyContext, start, start); + 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(), ret); + Node* end = graph.NewNode(common.End(1), ret); graph.SetStart(start); graph.SetEnd(end); FunctionTester ft(&graph); @@ -99,8 +99,49 @@ TEST(RunStringLengthStubTF) { Handle<JSReceiver> receiverArg = Object::ToObject(isolate, ft.Val(testString)).ToHandleChecked(); Handle<String> nameArg = ft.Val("length"); - Handle<Object> result = ft.Call(receiverArg, nameArg).ToHandleChecked(); + 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()); } + +TEST(RunStringAddTFStub) { + HandleAndZoneScope scope; + Isolate* isolate = scope.main_isolate(); + Zone* zone = scope.main_zone(); + + // Create code and an accompanying descriptor. + StringAddTFStub stub(isolate, STRING_ADD_CHECK_BOTH, NOT_TENURED); + 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 2-argument function + Node* start = graph.NewNode(common.Start(4)); + // Parameter 0 is the receiver + Node* leftParam = graph.NewNode(common.Parameter(1), start); + Node* rightParam = graph.NewNode(common.Parameter(2), start); + Unique<HeapObject> u = Unique<HeapObject>::CreateImmovable(code); + Node* theCode = graph.NewNode(common.HeapConstant(u)); + Node* dummyContext = graph.NewNode(common.NumberConstant(0.0)); + Node* call = graph.NewNode(common.Call(descriptor), theCode, leftParam, + rightParam, 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); + + // Actuall call through to the stub, verifying its result. + Handle<String> leftArg = ft.Val("links"); + Handle<String> rightArg = ft.Val("rechts"); + Handle<Object> result = ft.Call(leftArg, rightArg).ToHandleChecked(); + CHECK(String::Equals(ft.Val("linksrechts"), Handle<String>::cast(result))); +} + #endif // V8_TURBOFAN_TARGET diff --git a/deps/v8/test/cctest/compiler/test-simplified-lowering.cc b/deps/v8/test/cctest/compiler/test-simplified-lowering.cc index 9242248d60..022e01690b 100644 --- a/deps/v8/test/cctest/compiler/test-simplified-lowering.cc +++ b/deps/v8/test/cctest/compiler/test-simplified-lowering.cc @@ -33,12 +33,9 @@ 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->isolate(), this->graph(), MaybeHandle<Context>()), + MachineType p1 = kMachNone) + : GraphBuilderTester<ReturnType>(p0, p1), + typer(this->isolate(), this->graph()), javascript(this->zone()), jsgraph(this->isolate(), this->graph(), this->common(), &javascript, this->machine()), @@ -63,7 +60,7 @@ class SimplifiedLoweringTester : public GraphBuilderTester<ReturnType> { lowering.LowerAllNodes(); ChangeLowering lowering(&jsgraph); - GraphReducer reducer(this->graph(), this->zone()); + GraphReducer reducer(this->zone(), this->graph()); reducer.AddReducer(&lowering); reducer.ReduceGraph(); Verifier::Run(this->graph()); @@ -538,8 +535,7 @@ class AccessTester : public HandleAndZoneScope { 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]; } @@ -572,8 +568,19 @@ class AccessTester : public HandleAndZoneScope { 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) { @@ -703,14 +710,14 @@ class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders { explicit TestingGraph(Type* p0_type, Type* p1_type = Type::None(), Type* p2_type = Type::None()) : GraphAndBuilders(main_zone()), - typer(main_isolate(), graph(), MaybeHandle<Context>()), + typer(main_isolate(), graph()), javascript(main_zone()), jsgraph(main_isolate(), graph(), common(), &javascript, machine()) { start = graph()->NewNode(common()->Start(2)); 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); @@ -1269,7 +1276,6 @@ TEST(LowerStringOps_to_call_and_compare) { 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()); } } @@ -1443,8 +1449,8 @@ TEST(LowerLoadField_to_load) { 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(); @@ -1624,8 +1630,8 @@ TEST(InsertChangeForLoadField) { FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(), Type::Any(), kMachFloat64}; - 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()); @@ -1679,10 +1685,10 @@ TEST(UpdatePhi) { 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* 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(kMachAnyTagged, 2), load0, load1, t.start); t.Return(t.Use(phi, kMachineTypes[i])); |