+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_CCTEST_COMPILER_CALL_TESTER_H_
-#define V8_CCTEST_COMPILER_CALL_TESTER_H_
-
-#include "src/v8.h"
-
-#include "src/simulator.h"
-
-#if V8_TARGET_ARCH_IA32
-#if __GNUC__
-#define V8_CDECL __attribute__((cdecl))
-#else
-#define V8_CDECL __cdecl
-#endif
-#else
-#define V8_CDECL
-#endif
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-template <typename R>
-struct ReturnValueTraits {
- static R Cast(uintptr_t r) { return reinterpret_cast<R>(r); }
- static MachineRepresentation 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 kMachineTagged;
- }
-};
-
-template <>
-struct ReturnValueTraits<int32_t*> {
- static int32_t* Cast(uintptr_t r) { return reinterpret_cast<int32_t*>(r); }
- static MachineRepresentation Representation() {
- return MachineOperatorBuilder::pointer_rep();
- }
-};
-
-template <>
-struct ReturnValueTraits<void> {
- static void Cast(uintptr_t r) {}
- static MachineRepresentation Representation() {
- return MachineOperatorBuilder::pointer_rep();
- }
-};
-
-template <>
-struct ReturnValueTraits<bool> {
- static bool Cast(uintptr_t r) { return static_cast<bool>(r); }
- static MachineRepresentation Representation() {
- return MachineOperatorBuilder::pointer_rep();
- }
-};
-
-template <>
-struct ReturnValueTraits<int32_t> {
- static int32_t Cast(uintptr_t r) { return static_cast<int32_t>(r); }
- static MachineRepresentation Representation() { return kMachineWord32; }
-};
-
-template <>
-struct ReturnValueTraits<uint32_t> {
- static uint32_t Cast(uintptr_t r) { return static_cast<uint32_t>(r); }
- static MachineRepresentation Representation() { return kMachineWord32; }
-};
-
-template <>
-struct ReturnValueTraits<int64_t> {
- static int64_t Cast(uintptr_t r) { return static_cast<int64_t>(r); }
- static MachineRepresentation Representation() { return kMachineWord64; }
-};
-
-template <>
-struct ReturnValueTraits<uint64_t> {
- static uint64_t Cast(uintptr_t r) { return static_cast<uint64_t>(r); }
- static MachineRepresentation Representation() { return kMachineWord64; }
-};
-
-template <>
-struct ReturnValueTraits<int16_t> {
- static int16_t Cast(uintptr_t r) { return static_cast<int16_t>(r); }
- static MachineRepresentation Representation() {
- return MachineOperatorBuilder::pointer_rep();
- }
-};
-
-template <>
-struct ReturnValueTraits<int8_t> {
- static int8_t Cast(uintptr_t r) { return static_cast<int8_t>(r); }
- static MachineRepresentation Representation() {
- return MachineOperatorBuilder::pointer_rep();
- }
-};
-
-template <>
-struct ReturnValueTraits<double> {
- static double Cast(uintptr_t r) {
- UNREACHABLE();
- return 0.0;
- }
-};
-
-
-template <typename R>
-struct ParameterTraits {
- static uintptr_t Cast(R r) { return static_cast<uintptr_t>(r); }
-};
-
-template <>
-struct ParameterTraits<int*> {
- static uintptr_t Cast(int* r) { return reinterpret_cast<uintptr_t>(r); }
-};
-
-template <typename T>
-struct ParameterTraits<T*> {
- static uintptr_t Cast(void* r) { return reinterpret_cast<uintptr_t>(r); }
-};
-
-class CallHelper {
- public:
- explicit CallHelper(Isolate* isolate) : isolate_(isolate) { USE(isolate_); }
- virtual ~CallHelper() {}
-
- static MachineCallDescriptorBuilder* ToCallDescriptorBuilder(
- Zone* zone, MachineRepresentation return_type,
- MachineRepresentation p0 = kMachineLast,
- MachineRepresentation p1 = kMachineLast,
- MachineRepresentation p2 = kMachineLast,
- MachineRepresentation p3 = kMachineLast,
- MachineRepresentation p4 = kMachineLast) {
- const int kSize = 5;
- MachineRepresentation* params =
- zone->NewArray<MachineRepresentation>(kSize);
- params[0] = p0;
- params[1] = p1;
- params[2] = p2;
- params[3] = p3;
- params[4] = p4;
- int parameter_count = 0;
- for (int i = 0; i < kSize; ++i) {
- if (params[i] == kMachineLast) {
- break;
- }
- parameter_count++;
- }
- return new (zone)
- MachineCallDescriptorBuilder(return_type, parameter_count, params);
- }
-
- protected:
- virtual void VerifyParameters(int parameter_count,
- MachineRepresentation* parameters) = 0;
- virtual byte* Generate() = 0;
-
- private:
-#if USE_SIMULATOR && V8_TARGET_ARCH_ARM64
- uintptr_t CallSimulator(byte* f, Simulator::CallArgument* args) {
- Simulator* simulator = Simulator::current(isolate_);
- return static_cast<uintptr_t>(simulator->CallInt64(f, args));
- }
-
- template <typename R, typename F>
- R DoCall(F* f) {
- Simulator::CallArgument args[] = {Simulator::CallArgument::End()};
- return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
- }
- template <typename R, 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));
- }
- template <typename R, 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));
- }
- template <typename R, 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));
- }
- template <typename R, 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));
- }
-#elif USE_SIMULATOR && V8_TARGET_ARCH_ARM
- uintptr_t CallSimulator(byte* f, int32_t p1 = 0, int32_t p2 = 0,
- int32_t p3 = 0, int32_t p4 = 0) {
- Simulator* simulator = Simulator::current(isolate_);
- return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4));
- }
- template <typename R, typename F>
- R DoCall(F* f) {
- return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
- }
- template <typename R, typename F, typename P1>
- R DoCall(F* f, P1 p1) {
- return ReturnValueTraits<R>::Cast(
- CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1)));
- }
- template <typename R, 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)));
- }
- template <typename R, typename F, typename P1, typename P2, typename P3>
- R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
- return ReturnValueTraits<R>::Cast(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>
- R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
- return ReturnValueTraits<R>::Cast(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>
- R DoCall(F* f) {
- return f();
- }
- template <typename R, typename F, typename P1>
- R DoCall(F* f, P1 p1) {
- return f(p1);
- }
- template <typename R, 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>
- 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>
- 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() {
- MachineRepresentation parameters[] = {
- ReturnValueTraits<P1>::Representation()};
- VerifyParameters(ARRAY_SIZE(parameters), parameters);
- }
-
- template <typename P1, typename P2>
- void VerifyParameters2() {
- MachineRepresentation parameters[] = {
- ReturnValueTraits<P1>::Representation(),
- ReturnValueTraits<P2>::Representation()};
- VerifyParameters(ARRAY_SIZE(parameters), parameters);
- }
-
- template <typename P1, typename P2, typename P3>
- void VerifyParameters3() {
- MachineRepresentation parameters[] = {
- ReturnValueTraits<P1>::Representation(),
- ReturnValueTraits<P2>::Representation(),
- ReturnValueTraits<P3>::Representation()};
- VerifyParameters(ARRAY_SIZE(parameters), parameters);
- }
-
- template <typename P1, typename P2, typename P3, typename P4>
- void VerifyParameters4() {
- MachineRepresentation parameters[] = {
- ReturnValueTraits<P1>::Representation(),
- ReturnValueTraits<P2>::Representation(),
- ReturnValueTraits<P3>::Representation(),
- ReturnValueTraits<P4>::Representation()};
- VerifyParameters(ARRAY_SIZE(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
-
-#endif // V8_CCTEST_COMPILER_CALL_TESTER_H_
+++ /dev/null
-// 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 "test/cctest/compiler/codegen-tester.h"
-#include "test/cctest/compiler/value-helper.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-TEST(CompareWrapper) {
- // Who tests the testers?
- // If CompareWrapper is broken, then test expectations will be broken.
- RawMachineAssemblerTester<int32_t> m;
- CompareWrapper wWord32Equal(IrOpcode::kWord32Equal);
- CompareWrapper wInt32LessThan(IrOpcode::kInt32LessThan);
- CompareWrapper wInt32LessThanOrEqual(IrOpcode::kInt32LessThanOrEqual);
- CompareWrapper wUint32LessThan(IrOpcode::kUint32LessThan);
- CompareWrapper wUint32LessThanOrEqual(IrOpcode::kUint32LessThanOrEqual);
-
- {
- FOR_INT32_INPUTS(pl) {
- FOR_INT32_INPUTS(pr) {
- int32_t a = *pl;
- int32_t b = *pr;
- CHECK_EQ(a == b, wWord32Equal.Int32Compare(a, b));
- CHECK_EQ(a < b, wInt32LessThan.Int32Compare(a, b));
- CHECK_EQ(a <= b, wInt32LessThanOrEqual.Int32Compare(a, b));
- }
- }
- }
-
- {
- FOR_UINT32_INPUTS(pl) {
- FOR_UINT32_INPUTS(pr) {
- uint32_t a = *pl;
- uint32_t b = *pr;
- CHECK_EQ(a == b, wWord32Equal.Int32Compare(a, b));
- CHECK_EQ(a < b, wUint32LessThan.Int32Compare(a, b));
- CHECK_EQ(a <= b, wUint32LessThanOrEqual.Int32Compare(a, b));
- }
- }
- }
-
- CHECK_EQ(true, wWord32Equal.Int32Compare(0, 0));
- CHECK_EQ(true, wWord32Equal.Int32Compare(257, 257));
- CHECK_EQ(true, wWord32Equal.Int32Compare(65539, 65539));
- CHECK_EQ(true, wWord32Equal.Int32Compare(-1, -1));
- CHECK_EQ(true, wWord32Equal.Int32Compare(0xffffffff, 0xffffffff));
-
- CHECK_EQ(false, wWord32Equal.Int32Compare(0, 1));
- CHECK_EQ(false, wWord32Equal.Int32Compare(257, 256));
- CHECK_EQ(false, wWord32Equal.Int32Compare(65539, 65537));
- CHECK_EQ(false, wWord32Equal.Int32Compare(-1, -2));
- CHECK_EQ(false, wWord32Equal.Int32Compare(0xffffffff, 0xfffffffe));
-
- CHECK_EQ(false, wInt32LessThan.Int32Compare(0, 0));
- CHECK_EQ(false, wInt32LessThan.Int32Compare(357, 357));
- CHECK_EQ(false, wInt32LessThan.Int32Compare(75539, 75539));
- CHECK_EQ(false, wInt32LessThan.Int32Compare(-1, -1));
- CHECK_EQ(false, wInt32LessThan.Int32Compare(0xffffffff, 0xffffffff));
-
- CHECK_EQ(true, wInt32LessThan.Int32Compare(0, 1));
- CHECK_EQ(true, wInt32LessThan.Int32Compare(456, 457));
- CHECK_EQ(true, wInt32LessThan.Int32Compare(85537, 85539));
- CHECK_EQ(true, wInt32LessThan.Int32Compare(-2, -1));
- CHECK_EQ(true, wInt32LessThan.Int32Compare(0xfffffffe, 0xffffffff));
-
- CHECK_EQ(false, wInt32LessThan.Int32Compare(1, 0));
- CHECK_EQ(false, wInt32LessThan.Int32Compare(457, 456));
- CHECK_EQ(false, wInt32LessThan.Int32Compare(85539, 85537));
- CHECK_EQ(false, wInt32LessThan.Int32Compare(-1, -2));
- CHECK_EQ(false, wInt32LessThan.Int32Compare(0xffffffff, 0xfffffffe));
-
- CHECK_EQ(true, wInt32LessThanOrEqual.Int32Compare(0, 0));
- CHECK_EQ(true, wInt32LessThanOrEqual.Int32Compare(357, 357));
- CHECK_EQ(true, wInt32LessThanOrEqual.Int32Compare(75539, 75539));
- CHECK_EQ(true, wInt32LessThanOrEqual.Int32Compare(-1, -1));
- CHECK_EQ(true, wInt32LessThanOrEqual.Int32Compare(0xffffffff, 0xffffffff));
-
- CHECK_EQ(true, wInt32LessThanOrEqual.Int32Compare(0, 1));
- CHECK_EQ(true, wInt32LessThanOrEqual.Int32Compare(456, 457));
- CHECK_EQ(true, wInt32LessThanOrEqual.Int32Compare(85537, 85539));
- CHECK_EQ(true, wInt32LessThanOrEqual.Int32Compare(-2, -1));
- CHECK_EQ(true, wInt32LessThanOrEqual.Int32Compare(0xfffffffe, 0xffffffff));
-
- CHECK_EQ(false, wInt32LessThanOrEqual.Int32Compare(1, 0));
- CHECK_EQ(false, wInt32LessThanOrEqual.Int32Compare(457, 456));
- CHECK_EQ(false, wInt32LessThanOrEqual.Int32Compare(85539, 85537));
- CHECK_EQ(false, wInt32LessThanOrEqual.Int32Compare(-1, -2));
- CHECK_EQ(false, wInt32LessThanOrEqual.Int32Compare(0xffffffff, 0xfffffffe));
-
- // Unsigned comparisons.
- CHECK_EQ(false, wUint32LessThan.Int32Compare(0, 0));
- CHECK_EQ(false, wUint32LessThan.Int32Compare(357, 357));
- CHECK_EQ(false, wUint32LessThan.Int32Compare(75539, 75539));
- CHECK_EQ(false, wUint32LessThan.Int32Compare(-1, -1));
- CHECK_EQ(false, wUint32LessThan.Int32Compare(0xffffffff, 0xffffffff));
- CHECK_EQ(false, wUint32LessThan.Int32Compare(0xffffffff, 0));
- CHECK_EQ(false, wUint32LessThan.Int32Compare(-2999, 0));
-
- CHECK_EQ(true, wUint32LessThan.Int32Compare(0, 1));
- CHECK_EQ(true, wUint32LessThan.Int32Compare(456, 457));
- CHECK_EQ(true, wUint32LessThan.Int32Compare(85537, 85539));
- CHECK_EQ(true, wUint32LessThan.Int32Compare(-11, -10));
- CHECK_EQ(true, wUint32LessThan.Int32Compare(0xfffffffe, 0xffffffff));
- CHECK_EQ(true, wUint32LessThan.Int32Compare(0, 0xffffffff));
- CHECK_EQ(true, wUint32LessThan.Int32Compare(0, -2996));
-
- CHECK_EQ(false, wUint32LessThan.Int32Compare(1, 0));
- CHECK_EQ(false, wUint32LessThan.Int32Compare(457, 456));
- CHECK_EQ(false, wUint32LessThan.Int32Compare(85539, 85537));
- CHECK_EQ(false, wUint32LessThan.Int32Compare(-10, -21));
- CHECK_EQ(false, wUint32LessThan.Int32Compare(0xffffffff, 0xfffffffe));
-
- CHECK_EQ(true, wUint32LessThanOrEqual.Int32Compare(0, 0));
- CHECK_EQ(true, wUint32LessThanOrEqual.Int32Compare(357, 357));
- CHECK_EQ(true, wUint32LessThanOrEqual.Int32Compare(75539, 75539));
- CHECK_EQ(true, wUint32LessThanOrEqual.Int32Compare(-1, -1));
- CHECK_EQ(true, wUint32LessThanOrEqual.Int32Compare(0xffffffff, 0xffffffff));
-
- CHECK_EQ(true, wUint32LessThanOrEqual.Int32Compare(0, 1));
- CHECK_EQ(true, wUint32LessThanOrEqual.Int32Compare(456, 457));
- CHECK_EQ(true, wUint32LessThanOrEqual.Int32Compare(85537, 85539));
- CHECK_EQ(true, wUint32LessThanOrEqual.Int32Compare(-300, -299));
- CHECK_EQ(true, wUint32LessThanOrEqual.Int32Compare(-300, -300));
- CHECK_EQ(true, wUint32LessThanOrEqual.Int32Compare(0xfffffffe, 0xffffffff));
- CHECK_EQ(true, wUint32LessThanOrEqual.Int32Compare(0, -2995));
-
- CHECK_EQ(false, wUint32LessThanOrEqual.Int32Compare(1, 0));
- CHECK_EQ(false, wUint32LessThanOrEqual.Int32Compare(457, 456));
- CHECK_EQ(false, wUint32LessThanOrEqual.Int32Compare(85539, 85537));
- CHECK_EQ(false, wUint32LessThanOrEqual.Int32Compare(-130, -170));
- CHECK_EQ(false, wUint32LessThanOrEqual.Int32Compare(0xffffffff, 0xfffffffe));
- CHECK_EQ(false, wUint32LessThanOrEqual.Int32Compare(-2997, 0));
-
- CompareWrapper wFloat64Equal(IrOpcode::kFloat64Equal);
- CompareWrapper wFloat64LessThan(IrOpcode::kFloat64LessThan);
- CompareWrapper wFloat64LessThanOrEqual(IrOpcode::kFloat64LessThanOrEqual);
-
- // Check NaN handling.
- double nan = v8::base::OS::nan_value();
- double inf = V8_INFINITY;
- CHECK_EQ(false, wFloat64Equal.Float64Compare(nan, 0.0));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(nan, 1.0));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(nan, inf));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(nan, -inf));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(nan, nan));
-
- CHECK_EQ(false, wFloat64Equal.Float64Compare(0.0, nan));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(1.0, nan));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(inf, nan));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(-inf, nan));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(nan, nan));
-
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(nan, 0.0));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(nan, 1.0));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(nan, inf));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(nan, -inf));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(nan, nan));
-
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(0.0, nan));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(1.0, nan));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(inf, nan));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(-inf, nan));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(nan, nan));
-
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(nan, 0.0));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(nan, 1.0));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(nan, inf));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(nan, -inf));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(nan, nan));
-
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(0.0, nan));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(1.0, nan));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(inf, nan));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(-inf, nan));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(nan, nan));
-
- // Check inf handling.
- CHECK_EQ(false, wFloat64Equal.Float64Compare(inf, 0.0));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(inf, 1.0));
- CHECK_EQ(true, wFloat64Equal.Float64Compare(inf, inf));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(inf, -inf));
-
- CHECK_EQ(false, wFloat64Equal.Float64Compare(0.0, inf));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(1.0, inf));
- CHECK_EQ(true, wFloat64Equal.Float64Compare(inf, inf));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(-inf, inf));
-
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(inf, 0.0));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(inf, 1.0));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(inf, inf));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(inf, -inf));
-
- CHECK_EQ(true, wFloat64LessThan.Float64Compare(0.0, inf));
- CHECK_EQ(true, wFloat64LessThan.Float64Compare(1.0, inf));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(inf, inf));
- CHECK_EQ(true, wFloat64LessThan.Float64Compare(-inf, inf));
-
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(inf, 0.0));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(inf, 1.0));
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(inf, inf));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(inf, -inf));
-
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(0.0, inf));
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(1.0, inf));
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(inf, inf));
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(-inf, inf));
-
- // Check -inf handling.
- CHECK_EQ(false, wFloat64Equal.Float64Compare(-inf, 0.0));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(-inf, 1.0));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(-inf, inf));
- CHECK_EQ(true, wFloat64Equal.Float64Compare(-inf, -inf));
-
- CHECK_EQ(false, wFloat64Equal.Float64Compare(0.0, -inf));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(1.0, -inf));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(inf, -inf));
- CHECK_EQ(true, wFloat64Equal.Float64Compare(-inf, -inf));
-
- CHECK_EQ(true, wFloat64LessThan.Float64Compare(-inf, 0.0));
- CHECK_EQ(true, wFloat64LessThan.Float64Compare(-inf, 1.0));
- CHECK_EQ(true, wFloat64LessThan.Float64Compare(-inf, inf));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(-inf, -inf));
-
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(0.0, -inf));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(1.0, -inf));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(inf, -inf));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(-inf, -inf));
-
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(-inf, 0.0));
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(-inf, 1.0));
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(-inf, inf));
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(-inf, -inf));
-
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(0.0, -inf));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(1.0, -inf));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(inf, -inf));
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(-inf, -inf));
-
- // Check basic values.
- CHECK_EQ(true, wFloat64Equal.Float64Compare(0, 0));
- CHECK_EQ(true, wFloat64Equal.Float64Compare(257.1, 257.1));
- CHECK_EQ(true, wFloat64Equal.Float64Compare(65539.1, 65539.1));
- CHECK_EQ(true, wFloat64Equal.Float64Compare(-1.1, -1.1));
-
- CHECK_EQ(false, wFloat64Equal.Float64Compare(0, 1));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(257.2, 256.2));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(65539.2, 65537.2));
- CHECK_EQ(false, wFloat64Equal.Float64Compare(-1.2, -2.2));
-
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(0, 0));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(357.3, 357.3));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(75539.3, 75539.3));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(-1.3, -1.3));
-
- CHECK_EQ(true, wFloat64LessThan.Float64Compare(0, 1));
- CHECK_EQ(true, wFloat64LessThan.Float64Compare(456.4, 457.4));
- CHECK_EQ(true, wFloat64LessThan.Float64Compare(85537.4, 85539.4));
- CHECK_EQ(true, wFloat64LessThan.Float64Compare(-2.4, -1.4));
-
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(1, 0));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(457.5, 456.5));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(85539.5, 85537.5));
- CHECK_EQ(false, wFloat64LessThan.Float64Compare(-1.5, -2.5));
-
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(0, 0));
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(357.6, 357.6));
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(75539.6, 75539.6));
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(-1.6, -1.6));
-
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(0, 1));
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(456.7, 457.7));
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(85537.7, 85539.7));
- CHECK_EQ(true, wFloat64LessThanOrEqual.Float64Compare(-2.7, -1.7));
-
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(1, 0));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(457.8, 456.8));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(85539.8, 85537.8));
- CHECK_EQ(false, wFloat64LessThanOrEqual.Float64Compare(-1.8, -2.8));
-}
-
-
-void Int32BinopInputShapeTester::TestAllInputShapes() {
- std::vector<int32_t> inputs = ValueHelper::int32_vector();
- int num_int_inputs = static_cast<int>(inputs.size());
- if (num_int_inputs > 16) num_int_inputs = 16; // limit to 16 inputs
-
- for (int i = -2; i < num_int_inputs; i++) { // for all left shapes
- for (int j = -2; j < num_int_inputs; j++) { // for all right shapes
- if (i >= 0 && j >= 0) break; // No constant/constant combos
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
- Node* p0 = m.Parameter(0);
- Node* p1 = m.Parameter(1);
- Node* n0;
- Node* n1;
-
- // left = Parameter | Load | Constant
- if (i == -2) {
- n0 = p0;
- } else if (i == -1) {
- n0 = m.LoadFromPointer(&input_a, kMachineWord32);
- } else {
- n0 = m.Int32Constant(inputs[i]);
- }
-
- // right = Parameter | Load | Constant
- if (j == -2) {
- n1 = p1;
- } else if (j == -1) {
- n1 = m.LoadFromPointer(&input_b, kMachineWord32);
- } else {
- n1 = m.Int32Constant(inputs[j]);
- }
-
- gen->gen(&m, n0, n1);
-
- if (false) printf("Int32BinopInputShapeTester i=%d, j=%d\n", i, j);
- if (i >= 0) {
- input_a = inputs[i];
- RunRight(&m);
- } else if (j >= 0) {
- input_b = inputs[j];
- RunLeft(&m);
- } else {
- Run(&m);
- }
- }
- }
-}
-
-
-void Int32BinopInputShapeTester::Run(RawMachineAssemblerTester<int32_t>* m) {
- FOR_INT32_INPUTS(pl) {
- FOR_INT32_INPUTS(pr) {
- input_a = *pl;
- input_b = *pr;
- int32_t expect = gen->expected(input_a, input_b);
- if (false) printf(" cmp(a=%d, b=%d) ?== %d\n", input_a, input_b, expect);
- CHECK_EQ(expect, m->Call(input_a, input_b));
- }
- }
-}
-
-
-void Int32BinopInputShapeTester::RunLeft(
- RawMachineAssemblerTester<int32_t>* m) {
- FOR_UINT32_INPUTS(i) {
- input_a = *i;
- int32_t expect = gen->expected(input_a, input_b);
- if (false) printf(" cmp(a=%d, b=%d) ?== %d\n", input_a, input_b, expect);
- CHECK_EQ(expect, m->Call(input_a, input_b));
- }
-}
-
-
-void Int32BinopInputShapeTester::RunRight(
- RawMachineAssemblerTester<int32_t>* m) {
- FOR_UINT32_INPUTS(i) {
- input_b = *i;
- int32_t expect = gen->expected(input_a, input_b);
- if (false) printf(" cmp(a=%d, b=%d) ?== %d\n", input_a, input_b, expect);
- CHECK_EQ(expect, m->Call(input_a, input_b));
- }
-}
-
-
-TEST(ParametersEqual) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
- Node* p1 = m.Parameter(1);
- CHECK_NE(NULL, p1);
- Node* p0 = m.Parameter(0);
- CHECK_NE(NULL, p0);
- CHECK_EQ(p0, m.Parameter(0));
- CHECK_EQ(p1, m.Parameter(1));
-}
-
-
-#if V8_TURBOFAN_TARGET
-
-void RunSmiConstant(int32_t v) {
-// TODO(dcarney): on x64 Smis are generated with the SmiConstantRegister
-#if !V8_TARGET_ARCH_X64
- if (Smi::IsValid(v)) {
- RawMachineAssemblerTester<Object*> m;
- m.Return(m.NumberConstant(v));
- CHECK_EQ(Smi::FromInt(v), m.Call());
- }
-#endif
-}
-
-
-void RunNumberConstant(double v) {
- RawMachineAssemblerTester<Object*> m;
-#if V8_TARGET_ARCH_X64
- // TODO(dcarney): on x64 Smis are generated with the SmiConstantRegister
- Handle<Object> number = m.isolate()->factory()->NewNumber(v);
- if (number->IsSmi()) return;
-#endif
- m.Return(m.NumberConstant(v));
- Object* result = m.Call();
- m.CheckNumber(v, result);
-}
-
-
-TEST(RunEmpty) {
- RawMachineAssemblerTester<int32_t> m;
- m.Return(m.Int32Constant(0));
- CHECK_EQ(0, m.Call());
-}
-
-
-TEST(RunInt32Constants) {
- FOR_INT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m;
- m.Return(m.Int32Constant(*i));
- CHECK_EQ(*i, m.Call());
- }
-}
-
-
-TEST(RunSmiConstants) {
- for (int32_t i = 1; i < Smi::kMaxValue && i != 0; i = i << 1) {
- RunSmiConstant(i);
- RunSmiConstant(3 * i);
- RunSmiConstant(5 * i);
- RunSmiConstant(-i);
- RunSmiConstant(i | 1);
- RunSmiConstant(i | 3);
- }
- RunSmiConstant(Smi::kMaxValue);
- RunSmiConstant(Smi::kMaxValue - 1);
- RunSmiConstant(Smi::kMinValue);
- RunSmiConstant(Smi::kMinValue + 1);
-
- FOR_INT32_INPUTS(i) { RunSmiConstant(*i); }
-}
-
-
-TEST(RunNumberConstants) {
- {
- FOR_FLOAT64_INPUTS(i) { RunNumberConstant(*i); }
- }
- {
- FOR_INT32_INPUTS(i) { RunNumberConstant(*i); }
- }
-
- for (int32_t i = 1; i < Smi::kMaxValue && i != 0; i = i << 1) {
- RunNumberConstant(i);
- RunNumberConstant(-i);
- RunNumberConstant(i | 1);
- RunNumberConstant(i | 3);
- }
- RunNumberConstant(Smi::kMaxValue);
- RunNumberConstant(Smi::kMaxValue - 1);
- RunNumberConstant(Smi::kMinValue);
- RunNumberConstant(Smi::kMinValue + 1);
-}
-
-
-TEST(RunEmptyString) {
- RawMachineAssemblerTester<Object*> m;
- m.Return(m.StringConstant("empty"));
- m.CheckString("empty", m.Call());
-}
-
-
-TEST(RunHeapConstant) {
- RawMachineAssemblerTester<Object*> m;
- m.Return(m.StringConstant("empty"));
- m.CheckString("empty", m.Call());
-}
-
-
-TEST(RunHeapNumberConstant) {
- RawMachineAssemblerTester<Object*> m;
- Handle<Object> number = m.isolate()->factory()->NewHeapNumber(100.5);
- m.Return(m.HeapConstant(number));
- Object* result = m.Call();
- CHECK_EQ(result, *number);
-}
-
-
-TEST(RunParam1) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Parameter(0));
-
- FOR_INT32_INPUTS(i) {
- int32_t result = m.Call(*i);
- CHECK_EQ(*i, result);
- }
-}
-
-
-TEST(RunParam2_1) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
- Node* p0 = m.Parameter(0);
- Node* p1 = m.Parameter(1);
- m.Return(p0);
- USE(p1);
-
- FOR_INT32_INPUTS(i) {
- int32_t result = m.Call(*i, -9999);
- CHECK_EQ(*i, result);
- }
-}
-
-
-TEST(RunParam2_2) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
- Node* p0 = m.Parameter(0);
- Node* p1 = m.Parameter(1);
- m.Return(p1);
- USE(p0);
-
- FOR_INT32_INPUTS(i) {
- int32_t result = m.Call(-7777, *i);
- CHECK_EQ(*i, result);
- }
-}
-
-
-TEST(RunParam3) {
- for (int i = 0; i < 3; i++) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- Node* nodes[] = {m.Parameter(0), m.Parameter(1), m.Parameter(2)};
- m.Return(nodes[i]);
-
- int p[] = {-99, -77, -88};
- FOR_INT32_INPUTS(j) {
- p[i] = *j;
- int32_t result = m.Call(p[0], p[1], p[2]);
- CHECK_EQ(*j, result);
- }
- }
-}
-
-
-TEST(RunBinopTester) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(bt.param0);
-
- FOR_INT32_INPUTS(i) { CHECK_EQ(*i, bt.call(*i, 777)); }
- }
-
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(bt.param1);
-
- FOR_INT32_INPUTS(i) { CHECK_EQ(*i, bt.call(666, *i)); }
- }
-
- {
- RawMachineAssemblerTester<int32_t> m;
- Float64BinopTester bt(&m);
- bt.AddReturn(bt.param0);
-
- FOR_FLOAT64_INPUTS(i) { CHECK_EQ(*i, bt.call(*i, 9.0)); }
- }
-
- {
- RawMachineAssemblerTester<int32_t> m;
- Float64BinopTester bt(&m);
- bt.AddReturn(bt.param1);
-
- FOR_FLOAT64_INPUTS(i) { CHECK_EQ(*i, bt.call(-11.25, *i)); }
- }
-}
-
-#endif // V8_TURBOFAN_TARGET
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_CCTEST_COMPILER_CODEGEN_TESTER_H_
-#define V8_CCTEST_COMPILER_CODEGEN_TESTER_H_
-
-#include "src/v8.h"
-
-#include "src/compiler/pipeline.h"
-#include "src/compiler/raw-machine-assembler.h"
-#include "src/compiler/structured-machine-assembler.h"
-#include "src/simulator.h"
-#include "test/cctest/compiler/call-tester.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-template <typename MachineAssembler>
-class MachineAssemblerTester : public HandleAndZoneScope,
- public CallHelper,
- public MachineAssembler {
- public:
- MachineAssemblerTester(MachineRepresentation return_type,
- MachineRepresentation p0, MachineRepresentation p1,
- MachineRepresentation p2, MachineRepresentation p3,
- MachineRepresentation p4)
- : HandleAndZoneScope(),
- CallHelper(main_isolate()),
- MachineAssembler(new (main_zone()) Graph(main_zone()),
- ToCallDescriptorBuilder(main_zone(), return_type, p0,
- p1, p2, p3, p4),
- MachineOperatorBuilder::pointer_rep()) {}
-
- Node* LoadFromPointer(void* address, MachineRepresentation rep,
- int32_t offset = 0) {
- return this->Load(rep, this->PointerConstant(address),
- this->Int32Constant(offset));
- }
-
- void StoreToPointer(void* address, MachineRepresentation rep, Node* node) {
- this->Store(rep, this->PointerConstant(address), node);
- }
-
- Node* StringConstant(const char* string) {
- return this->HeapConstant(
- this->isolate()->factory()->InternalizeUtf8String(string));
- }
-
- void CheckNumber(double expected, Object* number) {
- CHECK(this->isolate()->factory()->NewNumber(expected)->SameValue(number));
- }
-
- void CheckString(const char* expected, Object* string) {
- CHECK(
- this->isolate()->factory()->InternalizeUtf8String(expected)->SameValue(
- string));
- }
-
- void GenerateCode() { Generate(); }
-
- protected:
- virtual void VerifyParameters(int parameter_count,
- MachineRepresentation* parameter_types) {
- CHECK_EQ(this->parameter_count(), parameter_count);
- const MachineRepresentation* expected_types = this->parameter_types();
- for (int i = 0; i < parameter_count; i++) {
- CHECK_EQ(expected_types[i], parameter_types[i]);
- }
- }
-
- virtual byte* Generate() {
- if (code_.is_null()) {
- Schedule* schedule = this->Export();
- CallDescriptor* call_descriptor = this->call_descriptor();
- Graph* graph = this->graph();
- CompilationInfo info(graph->zone()->isolate(), graph->zone());
- Linkage linkage(&info, call_descriptor);
- Pipeline pipeline(&info);
- code_ = pipeline.GenerateCodeForMachineGraph(&linkage, graph, schedule);
- }
- return this->code_.ToHandleChecked()->entry();
- }
-
- private:
- MaybeHandle<Code> code_;
-};
-
-
-template <typename ReturnType>
-class RawMachineAssemblerTester
- : public MachineAssemblerTester<RawMachineAssembler>,
- public CallHelper2<ReturnType, RawMachineAssemblerTester<ReturnType> > {
- public:
- RawMachineAssemblerTester(MachineRepresentation p0 = kMachineLast,
- MachineRepresentation p1 = kMachineLast,
- MachineRepresentation p2 = kMachineLast,
- MachineRepresentation p3 = kMachineLast,
- MachineRepresentation p4 = kMachineLast)
- : MachineAssemblerTester(ReturnValueTraits<ReturnType>::Representation(),
- p0, p1, p2, p3, p4) {}
-};
-
-
-template <typename ReturnType>
-class StructuredMachineAssemblerTester
- : public MachineAssemblerTester<StructuredMachineAssembler>,
- public CallHelper2<ReturnType,
- StructuredMachineAssemblerTester<ReturnType> > {
- public:
- StructuredMachineAssemblerTester(MachineRepresentation p0 = kMachineLast,
- MachineRepresentation p1 = kMachineLast,
- MachineRepresentation p2 = kMachineLast,
- MachineRepresentation p3 = kMachineLast,
- MachineRepresentation p4 = kMachineLast)
- : MachineAssemblerTester(ReturnValueTraits<ReturnType>::Representation(),
- p0, p1, p2, p3, p4) {}
-};
-
-
-static const bool USE_RESULT_BUFFER = true;
-static const bool USE_RETURN_REGISTER = false;
-
-// TODO(titzer): use the C-style calling convention, or any register-based
-// calling convention for binop tests.
-template <typename CType, MachineRepresentation rep, bool use_result_buffer>
-class BinopTester {
- public:
- static const int32_t CHECK_VALUE = 0x99BEEDCE;
-
- explicit BinopTester(RawMachineAssemblerTester<int32_t>* tester)
- : T(tester),
- param0(T->LoadFromPointer(&p0, rep)),
- param1(T->LoadFromPointer(&p1, rep)),
- p0(static_cast<CType>(0)),
- p1(static_cast<CType>(0)),
- result(static_cast<CType>(0)) {}
-
- RawMachineAssemblerTester<int32_t>* T;
- Node* param0;
- Node* param1;
-
- CType call(CType a0, CType a1) {
- p0 = a0;
- p1 = a1;
- if (use_result_buffer) {
- CHECK_EQ(CHECK_VALUE, T->Call());
- return result;
- } else {
- return T->Call();
- }
- }
-
- void AddReturn(Node* val) {
- if (use_result_buffer) {
- T->Store(rep, T->PointerConstant(&result), T->Int32Constant(0), val);
- T->Return(T->Int32Constant(CHECK_VALUE));
- } else {
- T->Return(val);
- }
- }
-
- protected:
- CType p0;
- CType p1;
- CType result;
-};
-
-
-// A helper class for testing code sequences that take two int parameters and
-// return an int value.
-class Int32BinopTester
- : public BinopTester<int32_t, kMachineWord32, USE_RETURN_REGISTER> {
- public:
- explicit Int32BinopTester(RawMachineAssemblerTester<int32_t>* tester)
- : BinopTester<int32_t, kMachineWord32, USE_RETURN_REGISTER>(tester) {}
-
- int32_t call(uint32_t a0, uint32_t a1) {
- p0 = static_cast<int32_t>(a0);
- p1 = static_cast<int32_t>(a1);
- return T->Call();
- }
-};
-
-
-// A helper class for testing code sequences that take two double parameters and
-// return a double value.
-// TODO(titzer): figure out how to return doubles correctly on ia32.
-class Float64BinopTester
- : public BinopTester<double, kMachineFloat64, USE_RESULT_BUFFER> {
- public:
- explicit Float64BinopTester(RawMachineAssemblerTester<int32_t>* tester)
- : BinopTester<double, kMachineFloat64, USE_RESULT_BUFFER>(tester) {}
-};
-
-
-// A helper class for testing code sequences that take two pointer parameters
-// and return a pointer value.
-// TODO(titzer): pick word size of pointers based on V8_TARGET.
-template <typename Type>
-class PointerBinopTester
- : public BinopTester<Type*, kMachineWord32, USE_RETURN_REGISTER> {
- public:
- explicit PointerBinopTester(RawMachineAssemblerTester<int32_t>* tester)
- : BinopTester<Type*, kMachineWord32, USE_RETURN_REGISTER>(tester) {}
-};
-
-
-// A helper class for testing code sequences that take two tagged parameters and
-// return a tagged value.
-template <typename Type>
-class TaggedBinopTester
- : public BinopTester<Type*, kMachineTagged, USE_RETURN_REGISTER> {
- public:
- explicit TaggedBinopTester(RawMachineAssemblerTester<int32_t>* tester)
- : BinopTester<Type*, kMachineTagged, USE_RETURN_REGISTER>(tester) {}
-};
-
-// A helper class for testing compares. Wraps a machine opcode and provides
-// evaluation routines and the operators.
-class CompareWrapper {
- public:
- explicit CompareWrapper(IrOpcode::Value op) : opcode(op) {}
-
- Node* MakeNode(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) {
- return m->NewNode(op(m->machine()), a, b);
- }
-
- Operator* op(MachineOperatorBuilder* machine) {
- switch (opcode) {
- case IrOpcode::kWord32Equal:
- return machine->Word32Equal();
- case IrOpcode::kInt32LessThan:
- return machine->Int32LessThan();
- case IrOpcode::kInt32LessThanOrEqual:
- return machine->Int32LessThanOrEqual();
- case IrOpcode::kUint32LessThan:
- return machine->Uint32LessThan();
- case IrOpcode::kUint32LessThanOrEqual:
- return machine->Uint32LessThanOrEqual();
- case IrOpcode::kFloat64Equal:
- return machine->Float64Equal();
- case IrOpcode::kFloat64LessThan:
- return machine->Float64LessThan();
- case IrOpcode::kFloat64LessThanOrEqual:
- return machine->Float64LessThanOrEqual();
- default:
- UNREACHABLE();
- }
- return NULL;
- }
-
- bool Int32Compare(int32_t a, int32_t b) {
- switch (opcode) {
- case IrOpcode::kWord32Equal:
- return a == b;
- case IrOpcode::kInt32LessThan:
- return a < b;
- case IrOpcode::kInt32LessThanOrEqual:
- return a <= b;
- case IrOpcode::kUint32LessThan:
- return static_cast<uint32_t>(a) < static_cast<uint32_t>(b);
- case IrOpcode::kUint32LessThanOrEqual:
- return static_cast<uint32_t>(a) <= static_cast<uint32_t>(b);
- default:
- UNREACHABLE();
- }
- return false;
- }
-
- bool Float64Compare(double a, double b) {
- switch (opcode) {
- case IrOpcode::kFloat64Equal:
- return a == b;
- case IrOpcode::kFloat64LessThan:
- return a < b;
- case IrOpcode::kFloat64LessThanOrEqual:
- return a <= b;
- default:
- UNREACHABLE();
- }
- return false;
- }
-
- IrOpcode::Value opcode;
-};
-
-
-// A small closure class to generate code for a function of two inputs that
-// produces a single output so that it can be used in many different contexts.
-// The {expected()} method should compute the expected output for a given
-// pair of inputs.
-template <typename T>
-class BinopGen {
- public:
- virtual void gen(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) = 0;
- virtual T expected(T a, T b) = 0;
- virtual ~BinopGen() {}
-};
-
-// A helper class to generate various combination of input shape combinations
-// and run the generated code to ensure it produces the correct results.
-class Int32BinopInputShapeTester {
- public:
- explicit Int32BinopInputShapeTester(BinopGen<int32_t>* g) : gen(g) {}
-
- void TestAllInputShapes();
-
- private:
- BinopGen<int32_t>* gen;
- int32_t input_a;
- int32_t input_b;
-
- void Run(RawMachineAssemblerTester<int32_t>* m);
- void RunLeft(RawMachineAssemblerTester<int32_t>* m);
- void RunRight(RawMachineAssemblerTester<int32_t>* m);
-};
-} // namespace compiler
-} // namespace internal
-} // namespace v8
-
-#endif // V8_CCTEST_COMPILER_CODEGEN_TESTER_H_
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
-#define V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
-
-#include "src/v8.h"
-#include "test/cctest/cctest.h"
-
-#include "src/compiler.h"
-#include "src/compiler/pipeline.h"
-#include "src/execution.h"
-#include "src/full-codegen.h"
-#include "src/handles.h"
-#include "src/objects-inl.h"
-#include "src/parser.h"
-#include "src/rewriter.h"
-#include "src/scopes.h"
-
-#define USE_CRANKSHAFT 0
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-class FunctionTester : public InitializedHandleScope {
- public:
- explicit FunctionTester(const char* source)
- : isolate(main_isolate()),
- function((FLAG_allow_natives_syntax = true, NewFunction(source))) {
- Compile(function);
- }
-
- Isolate* isolate;
- Handle<JSFunction> function;
-
- Handle<JSFunction> Compile(Handle<JSFunction> function) {
-#if V8_TURBOFAN_TARGET
- CompilationInfoWithZone info(function);
-
- CHECK(Parser::Parse(&info));
- StrictMode strict_mode = info.function()->strict_mode();
- info.SetStrictMode(strict_mode);
- info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
- CHECK(Rewriter::Rewrite(&info));
- CHECK(Scope::Analyze(&info));
- CHECK_NE(NULL, info.scope());
-
- EnsureDeoptimizationSupport(&info);
-
- Pipeline pipeline(&info);
- Handle<Code> code = pipeline.GenerateCode();
-
- CHECK(!code.is_null());
- function->ReplaceCode(*code);
-#elif USE_CRANKSHAFT
- Handle<Code> unoptimized = Handle<Code>(function->code());
- Handle<Code> code = Compiler::GetOptimizedCode(function, unoptimized,
- Compiler::NOT_CONCURRENT);
- CHECK(!code.is_null());
-#if ENABLE_DISASSEMBLER
- if (FLAG_print_opt_code) {
- CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
- code->Disassemble("test code", tracing_scope.file());
- }
-#endif
- function->ReplaceCode(*code);
-#endif
- return function;
- }
-
- static void EnsureDeoptimizationSupport(CompilationInfo* info) {
- bool should_recompile = !info->shared_info()->has_deoptimization_support();
- if (should_recompile) {
- CompilationInfoWithZone unoptimized(info->shared_info());
- // Note that we use the same AST that we will use for generating the
- // optimized code.
- unoptimized.SetFunction(info->function());
- unoptimized.PrepareForCompilation(info->scope());
- unoptimized.SetContext(info->context());
- if (should_recompile) unoptimized.EnableDeoptimizationSupport();
- bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
- CHECK(succeeded);
- Handle<SharedFunctionInfo> shared = info->shared_info();
- shared->EnableDeoptimizationSupport(*unoptimized.code());
- }
- }
-
- MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) {
- Handle<Object> args[] = {a, b};
- return Execution::Call(isolate, function, undefined(), 2, args, false);
- }
-
- void CheckThrows(Handle<Object> a, Handle<Object> b) {
- TryCatch try_catch;
- MaybeHandle<Object> no_result = Call(a, b);
- CHECK(isolate->has_pending_exception());
- CHECK(try_catch.HasCaught());
- CHECK(no_result.is_null());
- // TODO(mstarzinger): Temporary workaround for issue chromium:362388.
- isolate->OptionalRescheduleException(true);
- }
-
- v8::Handle<v8::Message> CheckThrowsReturnMessage(Handle<Object> a,
- Handle<Object> b) {
- TryCatch try_catch;
- MaybeHandle<Object> no_result = Call(a, b);
- CHECK(isolate->has_pending_exception());
- CHECK(try_catch.HasCaught());
- CHECK(no_result.is_null());
- // TODO(mstarzinger): Calling OptionalRescheduleException is a dirty hack,
- // it's the only way to make Message() not to assert because an external
- // exception has been caught by the try_catch.
- isolate->OptionalRescheduleException(true);
- return try_catch.Message();
- }
-
- void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b) {
- Handle<Object> result = Call(a, b).ToHandleChecked();
- CHECK(expected->SameValue(*result));
- }
-
- void CheckCall(Handle<Object> expected, Handle<Object> a) {
- CheckCall(expected, a, undefined());
- }
-
- void CheckCall(Handle<Object> expected) {
- CheckCall(expected, undefined(), undefined());
- }
-
- void CheckCall(double expected, double a, double b) {
- CheckCall(Val(expected), Val(a), Val(b));
- }
-
- void CheckTrue(Handle<Object> a, Handle<Object> b) {
- CheckCall(true_value(), a, b);
- }
-
- void CheckTrue(Handle<Object> a) { CheckCall(true_value(), a, undefined()); }
-
- void CheckTrue(double a, double b) {
- CheckCall(true_value(), Val(a), Val(b));
- }
-
- void CheckFalse(Handle<Object> a, Handle<Object> b) {
- CheckCall(false_value(), a, b);
- }
-
- void CheckFalse(Handle<Object> a) {
- CheckCall(false_value(), a, undefined());
- }
-
- void CheckFalse(double a, double b) {
- CheckCall(false_value(), Val(a), Val(b));
- }
-
- Handle<JSFunction> NewFunction(const char* source) {
- return v8::Utils::OpenHandle(
- *v8::Handle<v8::Function>::Cast(CompileRun(source)));
- }
-
- Handle<JSObject> NewObject(const char* source) {
- return v8::Utils::OpenHandle(
- *v8::Handle<v8::Object>::Cast(CompileRun(source)));
- }
-
- Handle<String> Val(const char* string) {
- return isolate->factory()->InternalizeUtf8String(string);
- }
-
- Handle<Object> Val(double value) {
- return isolate->factory()->NewNumber(value);
- }
-
- Handle<Object> infinity() { return isolate->factory()->infinity_value(); }
-
- Handle<Object> minus_infinity() { return Val(-V8_INFINITY); }
-
- Handle<Object> nan() { return isolate->factory()->nan_value(); }
-
- Handle<Object> undefined() { return isolate->factory()->undefined_value(); }
-
- Handle<Object> null() { return isolate->factory()->null_value(); }
-
- Handle<Object> true_value() { return isolate->factory()->true_value(); }
-
- Handle<Object> false_value() { return isolate->factory()->false_value(); }
-};
-}
-}
-} // namespace v8::internal::compiler
-
-#endif // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "test/cctest/compiler/graph-builder-tester.h"
-#include "src/compiler/pipeline.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-MachineCallHelper::MachineCallHelper(Zone* zone,
- MachineCallDescriptorBuilder* builder)
- : CallHelper(zone->isolate()),
- call_descriptor_builder_(builder),
- parameters_(NULL),
- graph_(NULL) {}
-
-
-void MachineCallHelper::InitParameters(GraphBuilder* builder,
- CommonOperatorBuilder* common) {
- ASSERT_EQ(NULL, parameters_);
- graph_ = builder->graph();
- if (parameter_count() == 0) return;
- parameters_ = builder->graph()->zone()->NewArray<Node*>(parameter_count());
- for (int i = 0; i < parameter_count(); ++i) {
- parameters_[i] = builder->NewNode(common->Parameter(i));
- }
-}
-
-
-byte* MachineCallHelper::Generate() {
- ASSERT(parameter_count() == 0 || parameters_ != NULL);
- if (code_.is_null()) {
- Zone* zone = graph_->zone();
- CompilationInfo info(zone->isolate(), zone);
- Linkage linkage(&info, call_descriptor_builder_->BuildCallDescriptor(zone));
- Pipeline pipeline(&info);
- code_ = pipeline.GenerateCodeForMachineGraph(&linkage, graph_);
- }
- return code_.ToHandleChecked()->entry();
-}
-
-
-void MachineCallHelper::VerifyParameters(
- int parameter_count, MachineRepresentation* parameter_types) {
- CHECK_EQ(this->parameter_count(), parameter_count);
- const MachineRepresentation* expected_types =
- call_descriptor_builder_->parameter_types();
- for (int i = 0; i < parameter_count; i++) {
- CHECK_EQ(expected_types[i], parameter_types[i]);
- }
-}
-
-
-Node* MachineCallHelper::Parameter(int offset) {
- ASSERT_NE(NULL, parameters_);
- ASSERT(0 <= offset && offset < parameter_count());
- return parameters_[offset];
-}
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_CCTEST_COMPILER_GRAPH_BUILDER_TESTER_H_
-#define V8_CCTEST_COMPILER_GRAPH_BUILDER_TESTER_H_
-
-#include "src/v8.h"
-#include "test/cctest/cctest.h"
-
-#include "src/compiler/common-operator.h"
-#include "src/compiler/graph-builder.h"
-#include "src/compiler/machine-node-factory.h"
-#include "src/compiler/machine-operator.h"
-#include "src/compiler/simplified-node-factory.h"
-#include "src/compiler/simplified-operator.h"
-#include "test/cctest/compiler/call-tester.h"
-#include "test/cctest/compiler/simplified-graph-builder.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-// A class that just passes node creation on to the Graph.
-class DirectGraphBuilder : public GraphBuilder {
- public:
- explicit DirectGraphBuilder(Graph* graph) : GraphBuilder(graph) {}
- virtual ~DirectGraphBuilder() {}
-
- protected:
- virtual Node* MakeNode(Operator* op, int value_input_count,
- Node** value_inputs) {
- return graph()->NewNode(op, value_input_count, value_inputs);
- }
-};
-
-
-class MachineCallHelper : public CallHelper {
- public:
- MachineCallHelper(Zone* zone, MachineCallDescriptorBuilder* builder);
-
- Node* Parameter(int offset);
-
- protected:
- virtual byte* Generate();
- virtual void VerifyParameters(int parameter_count,
- MachineRepresentation* parameters);
- void InitParameters(GraphBuilder* builder, CommonOperatorBuilder* common);
-
- private:
- int parameter_count() const {
- return call_descriptor_builder_->parameter_count();
- }
- MachineCallDescriptorBuilder* call_descriptor_builder_;
- Node** parameters_;
- // TODO(dcarney): shouldn't need graph stored.
- Graph* graph_;
- MaybeHandle<Code> code_;
-};
-
-
-class GraphAndBuilders {
- public:
- explicit GraphAndBuilders(Zone* zone)
- : main_graph_(new (zone) Graph(zone)),
- main_common_(zone),
- main_machine_(zone),
- main_simplified_(zone) {}
-
- protected:
- // Prefixed with main_ to avoid naiming conflicts.
- Graph* const main_graph_;
- CommonOperatorBuilder main_common_;
- MachineOperatorBuilder main_machine_;
- SimplifiedOperatorBuilder main_simplified_;
-};
-
-
-template <typename ReturnType>
-class GraphBuilderTester
- : public HandleAndZoneScope,
- private GraphAndBuilders,
- public MachineCallHelper,
- public SimplifiedGraphBuilder,
- public CallHelper2<ReturnType, GraphBuilderTester<ReturnType> > {
- public:
- explicit GraphBuilderTester(MachineRepresentation p0,
- MachineRepresentation p1,
- MachineRepresentation p2,
- MachineRepresentation p3,
- MachineRepresentation p4)
- : GraphAndBuilders(main_zone()),
- MachineCallHelper(
- main_zone(),
- ToCallDescriptorBuilder(
- main_zone(), ReturnValueTraits<ReturnType>::Representation(),
- p0, p1, p2, p3, p4)),
- SimplifiedGraphBuilder(main_graph_, &main_common_, &main_machine_,
- &main_simplified_) {
- Begin();
- InitParameters(this, &main_common_);
- }
- virtual ~GraphBuilderTester() {}
-
- Factory* factory() const { return isolate()->factory(); }
-};
-} // namespace compiler
-} // namespace internal
-} // namespace v8
-
-#endif // V8_CCTEST_COMPILER_GRAPH_BUILDER_TESTER_H_
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_CCTEST_COMPILER_GRAPH_TESTER_H_
-#define V8_CCTEST_COMPILER_GRAPH_TESTER_H_
-
-#include "src/v8.h"
-#include "test/cctest/cctest.h"
-
-#include "src/compiler/common-operator.h"
-#include "src/compiler/graph.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-class GraphTester : public HandleAndZoneScope, public Graph {
- public:
- GraphTester() : Graph(main_zone()) {}
-};
-
-
-class GraphWithStartNodeTester : public GraphTester {
- public:
- GraphWithStartNodeTester()
- : builder_(main_zone()), start_node_(NewNode(builder_.Start())) {
- SetStart(start_node_);
- }
-
- Node* start_node() { return start_node_; }
-
- private:
- CommonOperatorBuilder builder_;
- Node* start_node_;
-};
-}
-}
-} // namespace v8::internal::compiler
-
-#endif // V8_CCTEST_COMPILER_GRAPH_TESTER_H_
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_CCTEST_COMPILER_INSTRUCTION_SELECTOR_TEST_H_
-#define V8_CCTEST_COMPILER_INSTRUCTION_SELECTOR_TEST_H_
-
-#include <deque>
-#include <set>
-
-#include "src/compiler/instruction-selector.h"
-#include "src/compiler/raw-machine-assembler.h"
-#include "src/ostreams.h"
-#include "test/cctest/cctest.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-typedef std::set<int> VirtualRegisterSet;
-
-enum InstructionSelectorTesterMode { kTargetMode, kInternalMode };
-
-class InstructionSelectorTester : public HandleAndZoneScope,
- public RawMachineAssembler {
- public:
- enum Mode { kTargetMode, kInternalMode };
-
- static const int kParameterCount = 3;
- static MachineRepresentation* BuildParameterArray(Zone* zone) {
- MachineRepresentation* array =
- zone->NewArray<MachineRepresentation>(kParameterCount);
- for (int i = 0; i < kParameterCount; ++i) {
- array[i] = kMachineWord32;
- }
- return array;
- }
-
- explicit InstructionSelectorTester(Mode mode = kTargetMode)
- : RawMachineAssembler(
- new (main_zone()) Graph(main_zone()), new (main_zone())
- MachineCallDescriptorBuilder(kMachineWord32, kParameterCount,
- BuildParameterArray(main_zone())),
- MachineOperatorBuilder::pointer_rep()),
- mode_(mode) {}
-
- void SelectInstructions() {
- OFStream out(stdout);
- Schedule* schedule = Export();
- CHECK_NE(0, graph()->NodeCount());
- CompilationInfo info(main_isolate(), main_zone());
- Linkage linkage(&info, call_descriptor());
- InstructionSequence sequence(&linkage, graph(), schedule);
- SourcePositionTable source_positions(graph());
- InstructionSelector selector(&sequence, &source_positions);
- selector.SelectInstructions();
- out << "--- Code sequence after instruction selection --- " << endl
- << sequence;
- for (InstructionSequence::const_iterator i = sequence.begin();
- i != sequence.end(); ++i) {
- Instruction* instr = *i;
- if (instr->opcode() < 0) continue;
- if (mode_ == kTargetMode) {
- switch (ArchOpcodeField::decode(instr->opcode())) {
-#define CASE(Name) \
- case k##Name: \
- break;
- TARGET_ARCH_OPCODE_LIST(CASE)
-#undef CASE
- default:
- continue;
- }
- }
- code.push_back(instr);
- }
- for (int vreg = 0; vreg < sequence.VirtualRegisterCount(); ++vreg) {
- if (sequence.IsDouble(vreg)) {
- CHECK(!sequence.IsReference(vreg));
- doubles.insert(vreg);
- }
- if (sequence.IsReference(vreg)) {
- CHECK(!sequence.IsDouble(vreg));
- references.insert(vreg);
- }
- }
- immediates.assign(sequence.immediates().begin(),
- sequence.immediates().end());
- }
-
- int32_t ToInt32(const InstructionOperand* operand) const {
- size_t i = operand->index();
- CHECK(i < immediates.size());
- CHECK_EQ(InstructionOperand::IMMEDIATE, operand->kind());
- return immediates[i].ToInt32();
- }
-
- std::deque<Instruction*> code;
- VirtualRegisterSet doubles;
- VirtualRegisterSet references;
- std::deque<Constant> immediates;
-
- private:
- Mode mode_;
-};
-
-
-static inline void CheckSameVreg(InstructionOperand* exp,
- InstructionOperand* val) {
- CHECK_EQ(InstructionOperand::UNALLOCATED, exp->kind());
- CHECK_EQ(InstructionOperand::UNALLOCATED, val->kind());
- CHECK_EQ(UnallocatedOperand::cast(exp)->virtual_register(),
- UnallocatedOperand::cast(val)->virtual_register());
-}
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
-
-#endif // V8_CCTEST_COMPILER_INSTRUCTION_SELECTOR_TEST_H_
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "test/cctest/compiler/simplified-graph-builder.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-SimplifiedGraphBuilder::SimplifiedGraphBuilder(
- Graph* graph, CommonOperatorBuilder* common,
- MachineOperatorBuilder* machine, SimplifiedOperatorBuilder* simplified)
- : StructuredGraphBuilder(graph, common),
- machine_(machine),
- simplified_(simplified) {}
-
-
-void SimplifiedGraphBuilder::Begin() {
- ASSERT(graph()->start() == NULL);
- Node* start = graph()->NewNode(common()->Start());
- graph()->SetStart(start);
- set_environment(new (zone()) Environment(this, start));
-}
-
-
-void SimplifiedGraphBuilder::Return(Node* value) {
- Node* control = NewNode(common()->Return(), value);
- UpdateControlDependencyToLeaveFunction(control);
-}
-
-
-void SimplifiedGraphBuilder::End() {
- environment()->UpdateControlDependency(exit_control());
- graph()->SetEnd(NewNode(common()->End()));
-}
-
-
-SimplifiedGraphBuilder::Environment::Environment(
- SimplifiedGraphBuilder* builder, Node* control_dependency)
- : StructuredGraphBuilder::Environment(builder, control_dependency) {}
-
-
-Node* SimplifiedGraphBuilder::Environment::Top() {
- ASSERT(!values()->empty());
- return values()->back();
-}
-
-
-void SimplifiedGraphBuilder::Environment::Push(Node* node) {
- values()->push_back(node);
-}
-
-
-Node* SimplifiedGraphBuilder::Environment::Pop() {
- ASSERT(!values()->empty());
- Node* back = values()->back();
- values()->pop_back();
- return back;
-}
-
-
-void SimplifiedGraphBuilder::Environment::Poke(size_t depth, Node* node) {
- ASSERT(depth < values()->size());
- size_t index = values()->size() - depth - 1;
- values()->at(index) = node;
-}
-
-
-Node* SimplifiedGraphBuilder::Environment::Peek(size_t depth) {
- ASSERT(depth < values()->size());
- size_t index = values()->size() - depth - 1;
- return values()->at(index);
-}
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_CCTEST_COMPILER_SIMPLIFIED_GRAPH_BUILDER_H_
-#define V8_CCTEST_COMPILER_SIMPLIFIED_GRAPH_BUILDER_H_
-
-#include "src/compiler/common-operator.h"
-#include "src/compiler/graph-builder.h"
-#include "src/compiler/machine-node-factory.h"
-#include "src/compiler/machine-operator.h"
-#include "src/compiler/simplified-node-factory.h"
-#include "src/compiler/simplified-operator.h"
-#include "test/cctest/cctest.h"
-#include "test/cctest/compiler/call-tester.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-class SimplifiedGraphBuilder
- : public StructuredGraphBuilder,
- public MachineNodeFactory<SimplifiedGraphBuilder>,
- public SimplifiedNodeFactory<SimplifiedGraphBuilder> {
- public:
- SimplifiedGraphBuilder(Graph* graph, CommonOperatorBuilder* common,
- MachineOperatorBuilder* machine,
- SimplifiedOperatorBuilder* simplified);
- virtual ~SimplifiedGraphBuilder() {}
-
- class Environment : public StructuredGraphBuilder::Environment {
- public:
- Environment(SimplifiedGraphBuilder* builder, Node* control_dependency);
-
- // TODO(dcarney): encode somehow and merge into StructuredGraphBuilder.
- // SSA renaming operations.
- Node* Top();
- void Push(Node* node);
- Node* Pop();
- void Poke(size_t depth, Node* node);
- Node* Peek(size_t depth);
- };
-
- Isolate* isolate() const { return zone()->isolate(); }
- Zone* zone() const { return StructuredGraphBuilder::zone(); }
- CommonOperatorBuilder* common() const {
- return StructuredGraphBuilder::common();
- }
- MachineOperatorBuilder* machine() const { return machine_; }
- SimplifiedOperatorBuilder* simplified() const { return simplified_; }
- Environment* environment() {
- return reinterpret_cast<Environment*>(environment_internal());
- }
-
- // Initialize graph and builder.
- void Begin();
-
- void Return(Node* value);
-
- // Close the graph.
- void End();
-
- private:
- MachineOperatorBuilder* machine_;
- SimplifiedOperatorBuilder* simplified_;
-};
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
-
-#endif // V8_CCTEST_COMPILER_SIMPLIFIED_GRAPH_BUILDER_H_
+++ /dev/null
-// 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 "test/cctest/compiler/codegen-tester.h"
-#include "test/cctest/compiler/value-helper.h"
-
-#if V8_TURBOFAN_TARGET
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-typedef RawMachineAssembler::Label MLabel;
-
-static IrOpcode::Value int32cmp_opcodes[] = {
- IrOpcode::kWord32Equal, IrOpcode::kInt32LessThan,
- IrOpcode::kInt32LessThanOrEqual, IrOpcode::kUint32LessThan,
- IrOpcode::kUint32LessThanOrEqual};
-
-
-TEST(BranchCombineWord32EqualZero_1) {
- // Test combining a branch with x == 0
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- int32_t eq_constant = -1033;
- int32_t ne_constant = 825118;
- Node* p0 = m.Parameter(0);
-
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(p0, m.Int32Constant(0)), &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(eq_constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(ne_constant));
-
- FOR_INT32_INPUTS(i) {
- int32_t a = *i;
- int32_t expect = a == 0 ? eq_constant : ne_constant;
- CHECK_EQ(expect, m.Call(a));
- }
-}
-
-
-TEST(BranchCombineWord32EqualZero_chain) {
- // Test combining a branch with a chain of x == 0 == 0 == 0 ...
- int32_t eq_constant = -1133;
- int32_t ne_constant = 815118;
-
- for (int k = 0; k < 6; k++) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- Node* p0 = m.Parameter(0);
- MLabel blocka, blockb;
- Node* cond = p0;
- for (int j = 0; j < k; j++) {
- cond = m.Word32Equal(cond, m.Int32Constant(0));
- }
- m.Branch(cond, &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(eq_constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(ne_constant));
-
- FOR_INT32_INPUTS(i) {
- int32_t a = *i;
- int32_t expect = (k & 1) == 1 ? (a == 0 ? eq_constant : ne_constant)
- : (a == 0 ? ne_constant : eq_constant);
- CHECK_EQ(expect, m.Call(a));
- }
- }
-}
-
-
-TEST(BranchCombineInt32LessThanZero_1) {
- // Test combining a branch with x < 0
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- int32_t eq_constant = -1433;
- int32_t ne_constant = 845118;
- Node* p0 = m.Parameter(0);
-
- MLabel blocka, blockb;
- m.Branch(m.Int32LessThan(p0, m.Int32Constant(0)), &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(eq_constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(ne_constant));
-
- FOR_INT32_INPUTS(i) {
- int32_t a = *i;
- int32_t expect = a < 0 ? eq_constant : ne_constant;
- CHECK_EQ(expect, m.Call(a));
- }
-}
-
-
-TEST(BranchCombineUint32LessThan100_1) {
- // Test combining a branch with x < 100
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- int32_t eq_constant = 1471;
- int32_t ne_constant = 88845718;
- Node* p0 = m.Parameter(0);
-
- MLabel blocka, blockb;
- m.Branch(m.Uint32LessThan(p0, m.Int32Constant(100)), &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(eq_constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(ne_constant));
-
- FOR_UINT32_INPUTS(i) {
- uint32_t a = *i;
- int32_t expect = a < 100 ? eq_constant : ne_constant;
- CHECK_EQ(expect, m.Call(a));
- }
-}
-
-
-TEST(BranchCombineUint32LessThanOrEqual100_1) {
- // Test combining a branch with x <= 100
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- int32_t eq_constant = 1479;
- int32_t ne_constant = 77845719;
- Node* p0 = m.Parameter(0);
-
- MLabel blocka, blockb;
- m.Branch(m.Uint32LessThanOrEqual(p0, m.Int32Constant(100)), &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(eq_constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(ne_constant));
-
- FOR_UINT32_INPUTS(i) {
- uint32_t a = *i;
- int32_t expect = a <= 100 ? eq_constant : ne_constant;
- CHECK_EQ(expect, m.Call(a));
- }
-}
-
-
-TEST(BranchCombineZeroLessThanInt32_1) {
- // Test combining a branch with 0 < x
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- int32_t eq_constant = -2033;
- int32_t ne_constant = 225118;
- Node* p0 = m.Parameter(0);
-
- MLabel blocka, blockb;
- m.Branch(m.Int32LessThan(m.Int32Constant(0), p0), &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(eq_constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(ne_constant));
-
- FOR_INT32_INPUTS(i) {
- int32_t a = *i;
- int32_t expect = 0 < a ? eq_constant : ne_constant;
- CHECK_EQ(expect, m.Call(a));
- }
-}
-
-
-TEST(BranchCombineInt32GreaterThanZero_1) {
- // Test combining a branch with x > 0
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- int32_t eq_constant = -1073;
- int32_t ne_constant = 825178;
- Node* p0 = m.Parameter(0);
-
- MLabel blocka, blockb;
- m.Branch(m.Int32GreaterThan(p0, m.Int32Constant(0)), &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(eq_constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(ne_constant));
-
- FOR_INT32_INPUTS(i) {
- int32_t a = *i;
- int32_t expect = a > 0 ? eq_constant : ne_constant;
- CHECK_EQ(expect, m.Call(a));
- }
-}
-
-
-TEST(BranchCombineWord32EqualP) {
- // Test combining a branch with an Word32Equal.
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
- int32_t eq_constant = -1035;
- int32_t ne_constant = 825018;
- Node* p0 = m.Parameter(0);
- Node* p1 = m.Parameter(1);
-
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(p0, p1), &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(eq_constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(ne_constant));
-
- FOR_INT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- int32_t a = *i;
- int32_t b = *j;
- int32_t expect = a == b ? eq_constant : ne_constant;
- CHECK_EQ(expect, m.Call(a, b));
- }
- }
-}
-
-
-TEST(BranchCombineWord32EqualI) {
- int32_t eq_constant = -1135;
- int32_t ne_constant = 925718;
-
- for (int left = 0; left < 2; left++) {
- FOR_INT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- int32_t a = *i;
-
- Node* p0 = m.Int32Constant(a);
- Node* p1 = m.Parameter(0);
-
- MLabel blocka, blockb;
- if (left == 1) m.Branch(m.Word32Equal(p0, p1), &blocka, &blockb);
- if (left == 0) m.Branch(m.Word32Equal(p1, p0), &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(eq_constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(ne_constant));
-
- FOR_INT32_INPUTS(j) {
- int32_t b = *j;
- int32_t expect = a == b ? eq_constant : ne_constant;
- CHECK_EQ(expect, m.Call(b));
- }
- }
- }
-}
-
-
-TEST(BranchCombineInt32CmpP) {
- int32_t eq_constant = -1235;
- int32_t ne_constant = 725018;
-
- for (int op = 0; op < 2; op++) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
- Node* p0 = m.Parameter(0);
- Node* p1 = m.Parameter(1);
-
- MLabel blocka, blockb;
- if (op == 0) m.Branch(m.Int32LessThan(p0, p1), &blocka, &blockb);
- if (op == 1) m.Branch(m.Int32LessThanOrEqual(p0, p1), &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(eq_constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(ne_constant));
-
- FOR_INT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- int32_t a = *i;
- int32_t b = *j;
- int32_t expect = 0;
- if (op == 0) expect = a < b ? eq_constant : ne_constant;
- if (op == 1) expect = a <= b ? eq_constant : ne_constant;
- CHECK_EQ(expect, m.Call(a, b));
- }
- }
- }
-}
-
-
-TEST(BranchCombineInt32CmpI) {
- int32_t eq_constant = -1175;
- int32_t ne_constant = 927711;
-
- for (int op = 0; op < 2; op++) {
- FOR_INT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- int32_t a = *i;
- Node* p0 = m.Int32Constant(a);
- Node* p1 = m.Parameter(0);
-
- MLabel blocka, blockb;
- if (op == 0) m.Branch(m.Int32LessThan(p0, p1), &blocka, &blockb);
- if (op == 1) m.Branch(m.Int32LessThanOrEqual(p0, p1), &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(eq_constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(ne_constant));
-
- FOR_INT32_INPUTS(j) {
- int32_t b = *j;
- int32_t expect = 0;
- if (op == 0) expect = a < b ? eq_constant : ne_constant;
- if (op == 1) expect = a <= b ? eq_constant : ne_constant;
- CHECK_EQ(expect, m.Call(b));
- }
- }
- }
-}
-
-
-// Now come the sophisticated tests for many input shape combinations.
-
-// Materializes a boolean (1 or 0) from a comparison.
-class CmpMaterializeBoolGen : public BinopGen<int32_t> {
- public:
- CompareWrapper w;
- bool invert;
-
- CmpMaterializeBoolGen(IrOpcode::Value opcode, bool i)
- : w(opcode), invert(i) {}
-
- virtual void gen(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) {
- Node* cond = w.MakeNode(m, a, b);
- if (invert) cond = m->Word32Equal(cond, m->Int32Constant(0));
- m->Return(cond);
- }
- virtual int32_t expected(int32_t a, int32_t b) {
- if (invert) return !w.Int32Compare(a, b) ? 1 : 0;
- return w.Int32Compare(a, b) ? 1 : 0;
- }
-};
-
-
-// Generates a branch and return one of two values from a comparison.
-class CmpBranchGen : public BinopGen<int32_t> {
- public:
- CompareWrapper w;
- bool invert;
- bool true_first;
- int32_t eq_constant;
- int32_t ne_constant;
-
- CmpBranchGen(IrOpcode::Value opcode, bool i, bool t, int32_t eq, int32_t ne)
- : w(opcode), invert(i), true_first(t), eq_constant(eq), ne_constant(ne) {}
-
- virtual void gen(RawMachineAssemblerTester<int32_t>* m, Node* a, Node* b) {
- MLabel blocka, blockb;
- Node* cond = w.MakeNode(m, a, b);
- if (invert) cond = m->Word32Equal(cond, m->Int32Constant(0));
- m->Branch(cond, &blocka, &blockb);
- if (true_first) {
- m->Bind(&blocka);
- m->Return(m->Int32Constant(eq_constant));
- m->Bind(&blockb);
- m->Return(m->Int32Constant(ne_constant));
- } else {
- m->Bind(&blockb);
- m->Return(m->Int32Constant(ne_constant));
- m->Bind(&blocka);
- m->Return(m->Int32Constant(eq_constant));
- }
- }
- virtual int32_t expected(int32_t a, int32_t b) {
- if (invert) return !w.Int32Compare(a, b) ? eq_constant : ne_constant;
- return w.Int32Compare(a, b) ? eq_constant : ne_constant;
- }
-};
-
-
-TEST(BranchCombineInt32CmpAllInputShapes_materialized) {
- for (size_t i = 0; i < ARRAY_SIZE(int32cmp_opcodes); i++) {
- CmpMaterializeBoolGen gen(int32cmp_opcodes[i], false);
- Int32BinopInputShapeTester tester(&gen);
- tester.TestAllInputShapes();
- }
-}
-
-
-TEST(BranchCombineInt32CmpAllInputShapes_inverted_materialized) {
- for (size_t i = 0; i < ARRAY_SIZE(int32cmp_opcodes); i++) {
- CmpMaterializeBoolGen gen(int32cmp_opcodes[i], true);
- Int32BinopInputShapeTester tester(&gen);
- tester.TestAllInputShapes();
- }
-}
-
-
-TEST(BranchCombineInt32CmpAllInputShapes_branch_true) {
- for (size_t i = 0; i < ARRAY_SIZE(int32cmp_opcodes); i++) {
- CmpBranchGen gen(int32cmp_opcodes[i], false, false, 995 + i, -1011 - i);
- Int32BinopInputShapeTester tester(&gen);
- tester.TestAllInputShapes();
- }
-}
-
-
-TEST(BranchCombineInt32CmpAllInputShapes_branch_false) {
- for (size_t i = 0; i < ARRAY_SIZE(int32cmp_opcodes); i++) {
- CmpBranchGen gen(int32cmp_opcodes[i], false, true, 795 + i, -2011 - i);
- Int32BinopInputShapeTester tester(&gen);
- tester.TestAllInputShapes();
- }
-}
-
-
-TEST(BranchCombineInt32CmpAllInputShapes_inverse_branch_true) {
- for (size_t i = 0; i < ARRAY_SIZE(int32cmp_opcodes); i++) {
- CmpBranchGen gen(int32cmp_opcodes[i], true, false, 695 + i, -3011 - i);
- Int32BinopInputShapeTester tester(&gen);
- tester.TestAllInputShapes();
- }
-}
-
-
-TEST(BranchCombineInt32CmpAllInputShapes_inverse_branch_false) {
- for (size_t i = 0; i < ARRAY_SIZE(int32cmp_opcodes); i++) {
- CmpBranchGen gen(int32cmp_opcodes[i], true, true, 595 + i, -4011 - i);
- Int32BinopInputShapeTester tester(&gen);
- tester.TestAllInputShapes();
- }
-}
-
-
-TEST(BranchCombineFloat64Compares) {
- double inf = V8_INFINITY;
- double nan = v8::base::OS::nan_value();
- double inputs[] = {0.0, 1.0, -1.0, -inf, inf, nan};
-
- int32_t eq_constant = -1733;
- int32_t ne_constant = 915118;
-
- double input_a = 0.0;
- double input_b = 0.0;
-
- CompareWrapper cmps[] = {CompareWrapper(IrOpcode::kFloat64Equal),
- CompareWrapper(IrOpcode::kFloat64LessThan),
- CompareWrapper(IrOpcode::kFloat64LessThanOrEqual)};
-
- for (size_t c = 0; c < ARRAY_SIZE(cmps); c++) {
- CompareWrapper cmp = cmps[c];
- for (int invert = 0; invert < 2; invert++) {
- RawMachineAssemblerTester<int32_t> m;
- Node* a = m.LoadFromPointer(&input_a, kMachineFloat64);
- Node* b = m.LoadFromPointer(&input_b, kMachineFloat64);
-
- MLabel blocka, blockb;
- Node* cond = cmp.MakeNode(&m, a, b);
- if (invert) cond = m.Word32Equal(cond, m.Int32Constant(0));
- m.Branch(cond, &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(eq_constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(ne_constant));
-
- for (size_t i = 0; i < ARRAY_SIZE(inputs); i++) {
- for (size_t j = 0; j < ARRAY_SIZE(inputs); j += 2) {
- input_a = inputs[i];
- input_b = inputs[i];
- int32_t expected =
- invert ? (cmp.Float64Compare(input_a, input_b) ? ne_constant
- : eq_constant)
- : (cmp.Float64Compare(input_a, input_b) ? eq_constant
- : ne_constant);
- CHECK_EQ(expected, m.Call());
- }
- }
- }
- }
-}
-#endif // V8_TURBOFAN_TARGET
+++ /dev/null
-// 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/full-codegen.h"
-#include "src/parser.h"
-#include "src/rewriter.h"
-
-#include "test/cctest/compiler/function-tester.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-typedef RawMachineAssembler::Label MLabel;
-
-static Handle<JSFunction> NewFunction(const char* source) {
- return v8::Utils::OpenHandle(
- *v8::Handle<v8::Function>::Cast(CompileRun(source)));
-}
-
-
-class DeoptCodegenTester {
- public:
- explicit DeoptCodegenTester(HandleAndZoneScope* scope, const char* src)
- : scope_(scope),
- function(NewFunction(src)),
- info(function, scope->main_zone()),
- bailout_id(-1) {
- CHECK(Parser::Parse(&info));
- StrictMode strict_mode = info.function()->strict_mode();
- info.SetStrictMode(strict_mode);
- info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
- CHECK(Rewriter::Rewrite(&info));
- CHECK(Scope::Analyze(&info));
- CHECK_NE(NULL, info.scope());
-
- FunctionTester::EnsureDeoptimizationSupport(&info);
-
- ASSERT(info.shared_info()->has_deoptimization_support());
-
- graph = new (scope_->main_zone()) Graph(scope_->main_zone());
- }
-
- virtual ~DeoptCodegenTester() { delete code; }
-
- void GenerateCodeFromSchedule(Schedule* schedule) {
- OFStream os(stdout);
- os << *schedule;
-
- // Initialize the codegen and generate code.
- Linkage* linkage = new (scope_->main_zone()) Linkage(&info);
- code = new v8::internal::compiler::InstructionSequence(linkage, graph,
- schedule);
- SourcePositionTable source_positions(graph);
- InstructionSelector selector(code, &source_positions);
- selector.SelectInstructions();
-
- os << "----- Instruction sequence before register allocation -----\n"
- << *code;
-
- RegisterAllocator allocator(code);
- CHECK(allocator.Allocate());
-
- os << "----- Instruction sequence after register allocation -----\n"
- << *code;
-
- compiler::CodeGenerator generator(code);
- result_code = generator.GenerateCode();
-
-#ifdef DEBUG
- result_code->Print();
-#endif
- }
-
- Zone* zone() { return scope_->main_zone(); }
-
- HandleAndZoneScope* scope_;
- Handle<JSFunction> function;
- CompilationInfo info;
- BailoutId bailout_id;
- Handle<Code> result_code;
- v8::internal::compiler::InstructionSequence* code;
- Graph* graph;
-};
-
-
-class TrivialDeoptCodegenTester : public DeoptCodegenTester {
- public:
- explicit TrivialDeoptCodegenTester(HandleAndZoneScope* scope)
- : DeoptCodegenTester(scope,
- "function foo() { deopt(); return 42; }; foo") {}
-
- void GenerateCode() {
- GenerateCodeFromSchedule(BuildGraphAndSchedule(graph));
- }
-
- Schedule* BuildGraphAndSchedule(Graph* graph) {
- Isolate* isolate = info.isolate();
- CommonOperatorBuilder common(zone());
-
- // Manually construct a schedule for the function below:
- // function foo() {
- // deopt();
- // }
-
- MachineRepresentation parameter_reps[] = {kMachineTagged};
- MachineCallDescriptorBuilder descriptor_builder(kMachineTagged, 1,
- parameter_reps);
-
- RawMachineAssembler m(graph, &descriptor_builder);
-
- Handle<Object> undef_object =
- Handle<Object>(isolate->heap()->undefined_value(), isolate);
- PrintableUnique<Object> undef_constant =
- PrintableUnique<Object>::CreateUninitialized(zone(), undef_object);
- Node* undef_node = m.NewNode(common.HeapConstant(undef_constant));
-
- Handle<JSFunction> deopt_function =
- NewFunction("function deopt() { %DeoptimizeFunction(foo); }; deopt");
- PrintableUnique<Object> deopt_fun_constant =
- PrintableUnique<Object>::CreateUninitialized(zone(), deopt_function);
- Node* deopt_fun_node = m.NewNode(common.HeapConstant(deopt_fun_constant));
-
- MLabel deopt, cont;
- Node* call = m.CallJS0(deopt_fun_node, undef_node, &cont, &deopt);
-
- m.Bind(&cont);
- m.NewNode(common.Continuation(), call);
- m.Return(undef_node);
-
- m.Bind(&deopt);
- m.NewNode(common.LazyDeoptimization(), call);
-
- bailout_id = GetCallBailoutId();
- FrameStateDescriptor stateDescriptor(bailout_id);
- Node* state_node = m.NewNode(common.FrameState(stateDescriptor));
- m.Deoptimize(state_node);
-
- // Schedule the graph:
- Schedule* schedule = m.Export();
-
- cont_block = cont.block();
- deopt_block = deopt.block();
-
- 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);
- }
-
- BasicBlock* cont_block;
- BasicBlock* deopt_block;
-};
-
-
-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());
-
- Label* cont_label = t.code->GetLabel(t.cont_block);
- Label* deopt_label = t.code->GetLabel(t.deopt_block);
-
- // Check the patch table. It should patch the continuation address to the
- // deoptimization block address.
- CHECK_EQ(1, data->ReturnAddressPatchCount());
- CHECK_EQ(cont_label->pos(), data->ReturnAddressPc(0)->value());
- CHECK_EQ(deopt_label->pos(), data->PatchedAddressPc(0)->value());
-
- // Check that we deoptimize to the right AST id.
- CHECK_EQ(1, data->DeoptCount());
- 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) {
- Isolate* isolate = info.isolate();
- CommonOperatorBuilder common(zone());
-
- // Manually construct a schedule for the function below:
- // function foo() {
- // %DeoptimizeFunction(foo);
- // }
-
- MachineRepresentation parameter_reps[] = {kMachineTagged};
- MachineCallDescriptorBuilder descriptor_builder(kMachineTagged, 2,
- parameter_reps);
-
- RawMachineAssembler m(graph, &descriptor_builder);
-
- Handle<Object> undef_object =
- Handle<Object>(isolate->heap()->undefined_value(), isolate);
- PrintableUnique<Object> undef_constant =
- PrintableUnique<Object>::CreateUninitialized(zone(), undef_object);
- Node* undef_node = m.NewNode(common.HeapConstant(undef_constant));
-
- PrintableUnique<Object> this_fun_constant =
- PrintableUnique<Object>::CreateUninitialized(zone(), function);
- Node* this_fun_node = m.NewNode(common.HeapConstant(this_fun_constant));
-
- MLabel deopt, cont;
- Node* call = m.CallRuntime1(Runtime::kDeoptimizeFunction, this_fun_node,
- &cont, &deopt);
-
- m.Bind(&cont);
- m.NewNode(common.Continuation(), call);
- m.Return(undef_node);
-
- m.Bind(&deopt);
- m.NewNode(common.LazyDeoptimization(), call);
-
- bailout_id = GetCallBailoutId();
- FrameStateDescriptor stateDescriptor(bailout_id);
- Node* state_node = m.NewNode(common.FrameState(stateDescriptor));
- m.Deoptimize(state_node);
-
- // Schedule the graph:
- Schedule* schedule = m.Export();
-
- cont_block = cont.block();
- deopt_block = deopt.block();
-
- 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);
- }
-
- BasicBlock* cont_block;
- BasicBlock* deopt_block;
-};
-
-
-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)));
-}
+++ /dev/null
-// 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/compiler/gap-resolver.h"
-
-#include "src/base/utils/random-number-generator.h"
-#include "test/cctest/cctest.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-// The state of our move interpreter is the mapping of operands to values. Note
-// that the actual values don't really matter, all we care about is equality.
-class InterpreterState {
- public:
- typedef std::vector<MoveOperands> Moves;
-
- void ExecuteInParallel(Moves moves) {
- InterpreterState copy(*this);
- for (Moves::iterator it = moves.begin(); it != moves.end(); ++it) {
- if (!it->IsRedundant()) write(it->destination(), copy.read(it->source()));
- }
- }
-
- bool operator==(const InterpreterState& other) const {
- return values_ == other.values_;
- }
-
- bool operator!=(const InterpreterState& other) const {
- return values_ != other.values_;
- }
-
- private:
- // Internally, the state is a normalized permutation of (kind,index) pairs.
- typedef std::pair<InstructionOperand::Kind, int> Key;
- typedef Key Value;
- typedef std::map<Key, Value> OperandMap;
-
- Value read(const InstructionOperand* op) const {
- OperandMap::const_iterator it = values_.find(KeyFor(op));
- return (it == values_.end()) ? ValueFor(op) : it->second;
- }
-
- void write(const InstructionOperand* op, Value v) {
- if (v == ValueFor(op)) {
- values_.erase(KeyFor(op));
- } else {
- values_[KeyFor(op)] = v;
- }
- }
-
- static Key KeyFor(const InstructionOperand* op) {
- return Key(op->kind(), op->index());
- }
-
- static Value ValueFor(const InstructionOperand* op) {
- return Value(op->kind(), op->index());
- }
-
- friend OStream& operator<<(OStream& os, const InterpreterState& is) {
- for (OperandMap::const_iterator it = is.values_.begin();
- it != is.values_.end(); ++it) {
- if (it != is.values_.begin()) os << " ";
- InstructionOperand source(it->first.first, it->first.second);
- InstructionOperand destination(it->second.first, it->second.second);
- os << MoveOperands(&source, &destination);
- }
- return os;
- }
-
- OperandMap values_;
-};
-
-
-// An abstract interpreter for moves, swaps and parallel moves.
-class MoveInterpreter : public GapResolver::Assembler {
- public:
- virtual void AssembleMove(InstructionOperand* source,
- InstructionOperand* destination) V8_OVERRIDE {
- InterpreterState::Moves moves;
- moves.push_back(MoveOperands(source, destination));
- state_.ExecuteInParallel(moves);
- }
-
- virtual void AssembleSwap(InstructionOperand* source,
- InstructionOperand* destination) V8_OVERRIDE {
- InterpreterState::Moves moves;
- moves.push_back(MoveOperands(source, destination));
- moves.push_back(MoveOperands(destination, source));
- state_.ExecuteInParallel(moves);
- }
-
- void AssembleParallelMove(const ParallelMove* pm) {
- InterpreterState::Moves moves(pm->move_operands()->begin(),
- pm->move_operands()->end());
- state_.ExecuteInParallel(moves);
- }
-
- InterpreterState state() const { return state_; }
-
- private:
- InterpreterState state_;
-};
-
-
-class ParallelMoveCreator : public HandleAndZoneScope {
- public:
- ParallelMoveCreator() : rng_(CcTest::random_number_generator()) {}
-
- ParallelMove* Create(int size) {
- ParallelMove* parallel_move = new (main_zone()) ParallelMove(main_zone());
- std::set<InstructionOperand*, InstructionOperandComparator> seen;
- for (int i = 0; i < size; ++i) {
- MoveOperands mo(CreateRandomOperand(), CreateRandomOperand());
- if (!mo.IsRedundant() && seen.find(mo.destination()) == seen.end()) {
- parallel_move->AddMove(mo.source(), mo.destination(), main_zone());
- seen.insert(mo.destination());
- }
- }
- return parallel_move;
- }
-
- private:
- struct InstructionOperandComparator {
- bool operator()(const InstructionOperand* x, const InstructionOperand* y) {
- return (x->kind() < y->kind()) ||
- (x->kind() == y->kind() && x->index() < y->index());
- }
- };
-
- InstructionOperand* CreateRandomOperand() {
- int index = rng_->NextInt(6);
- switch (rng_->NextInt(5)) {
- case 0:
- return ConstantOperand::Create(index, main_zone());
- case 1:
- return StackSlotOperand::Create(index, main_zone());
- case 2:
- return DoubleStackSlotOperand::Create(index, main_zone());
- case 3:
- return RegisterOperand::Create(index, main_zone());
- case 4:
- return DoubleRegisterOperand::Create(index, main_zone());
- }
- UNREACHABLE();
- return NULL;
- }
-
- private:
- v8::base::RandomNumberGenerator* rng_;
-};
-
-
-TEST(FuzzResolver) {
- ParallelMoveCreator pmc;
- for (int size = 0; size < 20; ++size) {
- for (int repeat = 0; repeat < 50; ++repeat) {
- ParallelMove* pm = pmc.Create(size);
-
- // Note: The gap resolver modifies the ParallelMove, so interpret first.
- MoveInterpreter mi1;
- mi1.AssembleParallelMove(pm);
-
- MoveInterpreter mi2;
- GapResolver resolver(&mi2);
- resolver.Resolve(pm);
-
- CHECK(mi1.state() == mi2.state());
- }
- }
-}
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-
-#include "graph-tester.h"
-#include "src/compiler/generic-node-inl.h"
-#include "src/compiler/graph-reducer.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-const uint8_t OPCODE_A0 = 10;
-const uint8_t OPCODE_A1 = 11;
-const uint8_t OPCODE_A2 = 12;
-const uint8_t OPCODE_B0 = 20;
-const uint8_t OPCODE_B1 = 21;
-const uint8_t OPCODE_B2 = 22;
-const uint8_t OPCODE_C0 = 30;
-const uint8_t OPCODE_C1 = 31;
-const uint8_t OPCODE_C2 = 32;
-
-static SimpleOperator OPA0(OPCODE_A0, Operator::kNoWrite, 0, 0, "opa0");
-static SimpleOperator OPA1(OPCODE_A1, Operator::kNoWrite, 1, 0, "opa1");
-static SimpleOperator OPA2(OPCODE_A2, Operator::kNoWrite, 2, 0, "opa2");
-static SimpleOperator OPB0(OPCODE_B0, Operator::kNoWrite, 0, 0, "opa0");
-static SimpleOperator OPB1(OPCODE_B1, Operator::kNoWrite, 1, 0, "opa1");
-static SimpleOperator OPB2(OPCODE_B2, Operator::kNoWrite, 2, 0, "opa2");
-static SimpleOperator OPC0(OPCODE_C0, Operator::kNoWrite, 0, 0, "opc0");
-static SimpleOperator OPC1(OPCODE_C1, Operator::kNoWrite, 1, 0, "opc1");
-static SimpleOperator OPC2(OPCODE_C2, Operator::kNoWrite, 2, 0, "opc2");
-
-
-// Replaces all "A" operators with "B" operators without creating new nodes.
-class InPlaceABReducer : public Reducer {
- public:
- virtual Reduction Reduce(Node* node) {
- switch (node->op()->opcode()) {
- case OPCODE_A0:
- CHECK_EQ(0, node->InputCount());
- node->set_op(&OPB0);
- return Replace(node);
- case OPCODE_A1:
- CHECK_EQ(1, node->InputCount());
- node->set_op(&OPB1);
- return Replace(node);
- case OPCODE_A2:
- CHECK_EQ(2, node->InputCount());
- node->set_op(&OPB2);
- return Replace(node);
- }
- return NoChange();
- }
-};
-
-
-// Replaces all "A" operators with "B" operators by allocating new nodes.
-class NewABReducer : public Reducer {
- public:
- explicit NewABReducer(Graph* graph) : graph_(graph) {}
- virtual Reduction Reduce(Node* node) {
- switch (node->op()->opcode()) {
- case OPCODE_A0:
- CHECK_EQ(0, node->InputCount());
- return Replace(graph_->NewNode(&OPB0));
- case OPCODE_A1:
- CHECK_EQ(1, node->InputCount());
- return Replace(graph_->NewNode(&OPB1, node->InputAt(0)));
- case OPCODE_A2:
- CHECK_EQ(2, node->InputCount());
- return Replace(
- graph_->NewNode(&OPB2, node->InputAt(0), node->InputAt(1)));
- }
- return NoChange();
- }
- Graph* graph_;
-};
-
-
-// Replaces all "B" operators with "C" operators without creating new nodes.
-class InPlaceBCReducer : public Reducer {
- public:
- virtual Reduction Reduce(Node* node) {
- switch (node->op()->opcode()) {
- case OPCODE_B0:
- CHECK_EQ(0, node->InputCount());
- node->set_op(&OPC0);
- return Replace(node);
- case OPCODE_B1:
- CHECK_EQ(1, node->InputCount());
- node->set_op(&OPC1);
- return Replace(node);
- case OPCODE_B2:
- CHECK_EQ(2, node->InputCount());
- node->set_op(&OPC2);
- return Replace(node);
- }
- return NoChange();
- }
-};
-
-
-// Wraps all "OPA0" nodes in "OPB1" operators by allocating new nodes.
-class A0Wrapper V8_FINAL : public Reducer {
- public:
- explicit A0Wrapper(Graph* graph) : graph_(graph) {}
- virtual Reduction Reduce(Node* node) V8_OVERRIDE {
- switch (node->op()->opcode()) {
- case OPCODE_A0:
- CHECK_EQ(0, node->InputCount());
- return Replace(graph_->NewNode(&OPB1, node));
- }
- return NoChange();
- }
- Graph* graph_;
-};
-
-
-// Wraps all "OPB0" nodes in two "OPC1" operators by allocating new nodes.
-class B0Wrapper V8_FINAL : public Reducer {
- public:
- explicit B0Wrapper(Graph* graph) : graph_(graph) {}
- virtual Reduction Reduce(Node* node) V8_OVERRIDE {
- switch (node->op()->opcode()) {
- case OPCODE_B0:
- CHECK_EQ(0, node->InputCount());
- return Replace(graph_->NewNode(&OPC1, graph_->NewNode(&OPC1, node)));
- }
- return NoChange();
- }
- Graph* graph_;
-};
-
-
-// Replaces all "OPA1" nodes with the first input.
-class A1Forwarder : public Reducer {
- virtual Reduction Reduce(Node* node) {
- switch (node->op()->opcode()) {
- case OPCODE_A1:
- CHECK_EQ(1, node->InputCount());
- return Replace(node->InputAt(0));
- }
- return NoChange();
- }
-};
-
-
-// Replaces all "OPB1" nodes with the first input.
-class B1Forwarder : public Reducer {
- virtual Reduction Reduce(Node* node) {
- switch (node->op()->opcode()) {
- case OPCODE_B1:
- CHECK_EQ(1, node->InputCount());
- return Replace(node->InputAt(0));
- }
- return NoChange();
- }
-};
-
-
-// Swaps the inputs to "OP2A" and "OP2B" nodes based on ids.
-class AB2Sorter : public Reducer {
- virtual Reduction Reduce(Node* node) {
- switch (node->op()->opcode()) {
- case OPCODE_A2:
- case OPCODE_B2:
- CHECK_EQ(2, node->InputCount());
- Node* x = node->InputAt(0);
- Node* y = node->InputAt(1);
- if (x->id() > y->id()) {
- node->ReplaceInput(0, y);
- node->ReplaceInput(1, x);
- return Replace(node);
- }
- }
- return NoChange();
- }
-};
-
-
-// Simply records the nodes visited.
-class ReducerRecorder : public Reducer {
- public:
- explicit ReducerRecorder(Zone* zone)
- : set(NodeSet::key_compare(), NodeSet::allocator_type(zone)) {}
- virtual Reduction Reduce(Node* node) {
- set.insert(node);
- return NoChange();
- }
- void CheckContains(Node* node) { CHECK_EQ(1, set.count(node)); }
- NodeSet set;
-};
-
-
-TEST(ReduceGraphFromEnd1) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* end = graph.NewNode(&OPA1, n1);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph);
- ReducerRecorder recorder(graph.zone());
- reducer.AddReducer(&recorder);
- reducer.ReduceGraph();
- recorder.CheckContains(n1);
- recorder.CheckContains(end);
-}
-
-
-TEST(ReduceGraphFromEnd2) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* n2 = graph.NewNode(&OPA1, n1);
- Node* n3 = graph.NewNode(&OPA1, n1);
- Node* end = graph.NewNode(&OPA2, n2, n3);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph);
- ReducerRecorder recorder(graph.zone());
- reducer.AddReducer(&recorder);
- reducer.ReduceGraph();
- recorder.CheckContains(n1);
- recorder.CheckContains(n2);
- recorder.CheckContains(n3);
- recorder.CheckContains(end);
-}
-
-
-TEST(ReduceInPlace1) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* end = graph.NewNode(&OPA1, n1);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph);
- InPlaceABReducer r;
- reducer.AddReducer(&r);
-
- // Tests A* => B* with in-place updates.
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPB0, n1->op());
- CHECK_EQ(&OPB1, end->op());
- CHECK_EQ(n1, end->InputAt(0));
- }
-}
-
-
-TEST(ReduceInPlace2) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* n2 = graph.NewNode(&OPA1, n1);
- Node* n3 = graph.NewNode(&OPA1, n1);
- Node* end = graph.NewNode(&OPA2, n2, n3);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph);
- InPlaceABReducer r;
- reducer.AddReducer(&r);
-
- // Tests A* => B* with in-place updates.
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPB0, n1->op());
- CHECK_EQ(&OPB1, n2->op());
- CHECK_EQ(n1, n2->InputAt(0));
- CHECK_EQ(&OPB1, n3->op());
- CHECK_EQ(n1, n3->InputAt(0));
- CHECK_EQ(&OPB2, end->op());
- CHECK_EQ(n2, end->InputAt(0));
- CHECK_EQ(n3, end->InputAt(1));
- }
-}
-
-
-TEST(ReduceNew1) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* n2 = graph.NewNode(&OPA1, n1);
- Node* n3 = graph.NewNode(&OPA1, n1);
- Node* end = graph.NewNode(&OPA2, n2, n3);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph);
- NewABReducer r(&graph);
- reducer.AddReducer(&r);
-
- // Tests A* => B* while creating new nodes.
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- if (i == 0) {
- CHECK_NE(before, graph.NodeCount());
- } else {
- CHECK_EQ(before, graph.NodeCount());
- }
- Node* nend = graph.end();
- CHECK_NE(end, nend); // end() should be updated too.
-
- Node* nn2 = nend->InputAt(0);
- Node* nn3 = nend->InputAt(1);
- Node* nn1 = nn2->InputAt(0);
-
- CHECK_EQ(nn1, nn3->InputAt(0));
-
- CHECK_EQ(&OPB0, nn1->op());
- CHECK_EQ(&OPB1, nn2->op());
- CHECK_EQ(&OPB1, nn3->op());
- CHECK_EQ(&OPB2, nend->op());
- }
-}
-
-
-TEST(Wrapping1) {
- GraphTester graph;
-
- Node* end = graph.NewNode(&OPA0);
- graph.SetEnd(end);
- CHECK_EQ(1, graph.NodeCount());
-
- GraphReducer reducer(&graph);
- A0Wrapper r(&graph);
- reducer.AddReducer(&r);
-
- reducer.ReduceGraph();
- CHECK_EQ(2, graph.NodeCount());
-
- Node* nend = graph.end();
- CHECK_NE(end, nend);
- CHECK_EQ(&OPB1, nend->op());
- CHECK_EQ(1, nend->InputCount());
- CHECK_EQ(end, nend->InputAt(0));
-}
-
-
-TEST(Wrapping2) {
- GraphTester graph;
-
- Node* end = graph.NewNode(&OPB0);
- graph.SetEnd(end);
- CHECK_EQ(1, graph.NodeCount());
-
- GraphReducer reducer(&graph);
- B0Wrapper r(&graph);
- reducer.AddReducer(&r);
-
- reducer.ReduceGraph();
- CHECK_EQ(3, graph.NodeCount());
-
- Node* nend = graph.end();
- CHECK_NE(end, nend);
- CHECK_EQ(&OPC1, nend->op());
- CHECK_EQ(1, nend->InputCount());
-
- Node* n1 = nend->InputAt(0);
- CHECK_NE(end, n1);
- CHECK_EQ(&OPC1, n1->op());
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(end, n1->InputAt(0));
-}
-
-
-TEST(Forwarding1) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* end = graph.NewNode(&OPA1, n1);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph);
- A1Forwarder r;
- reducer.AddReducer(&r);
-
- // Tests A1(x) => x
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPA0, n1->op());
- CHECK_EQ(n1, graph.end());
- }
-}
-
-
-TEST(Forwarding2) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* n2 = graph.NewNode(&OPA1, n1);
- Node* n3 = graph.NewNode(&OPA1, n1);
- Node* end = graph.NewNode(&OPA2, n2, n3);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph);
- A1Forwarder r;
- reducer.AddReducer(&r);
-
- // Tests reducing A2(A1(x), A1(y)) => A2(x, y).
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPA0, n1->op());
- CHECK_EQ(n1, end->InputAt(0));
- CHECK_EQ(n1, end->InputAt(1));
- CHECK_EQ(&OPA2, end->op());
- CHECK_EQ(0, n2->UseCount());
- CHECK_EQ(0, n3->UseCount());
- }
-}
-
-
-TEST(Forwarding3) {
- // Tests reducing a chain of A1(A1(A1(A1(x)))) => x.
- for (int i = 0; i < 8; i++) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* end = n1;
- for (int j = 0; j < i; j++) {
- end = graph.NewNode(&OPA1, end);
- }
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph);
- A1Forwarder r;
- reducer.AddReducer(&r);
-
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPA0, n1->op());
- CHECK_EQ(n1, graph.end());
- }
- }
-}
-
-
-TEST(ReduceForward1) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* n2 = graph.NewNode(&OPA1, n1);
- Node* n3 = graph.NewNode(&OPA1, n1);
- Node* end = graph.NewNode(&OPA2, n2, n3);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph);
- InPlaceABReducer r;
- B1Forwarder f;
- reducer.AddReducer(&r);
- reducer.AddReducer(&f);
-
- // Tests first reducing A => B, then B1(x) => x.
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPB0, n1->op());
- CHECK_EQ(&OPB1, n2->op());
- CHECK_EQ(n1, end->InputAt(0));
- CHECK_EQ(&OPB1, n3->op());
- CHECK_EQ(n1, end->InputAt(0));
- CHECK_EQ(&OPB2, end->op());
- CHECK_EQ(0, n2->UseCount());
- CHECK_EQ(0, n3->UseCount());
- }
-}
-
-
-TEST(Sorter1) {
- HandleAndZoneScope scope;
- AB2Sorter r;
- for (int i = 0; i < 6; i++) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* n2 = graph.NewNode(&OPA1, n1);
- Node* n3 = graph.NewNode(&OPA1, n1);
- Node* end;
-
- if (i == 0) end = graph.NewNode(&OPA2, n2, n3);
- if (i == 1) end = graph.NewNode(&OPA2, n3, n2);
- if (i == 2) end = graph.NewNode(&OPA2, n2, n1);
- if (i == 3) end = graph.NewNode(&OPA2, n1, n2);
- if (i == 4) end = graph.NewNode(&OPA2, n3, n1);
- if (i == 5) end = graph.NewNode(&OPA2, n1, n3);
-
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph);
- reducer.AddReducer(&r);
-
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPA0, n1->op());
- CHECK_EQ(&OPA1, n2->op());
- CHECK_EQ(&OPA1, n3->op());
- CHECK_EQ(&OPA2, end->op());
- CHECK_EQ(end, graph.end());
- CHECK(end->InputAt(0)->id() <= end->InputAt(1)->id());
- }
-}
-
-
-// Generate a node graph with the given permutations.
-void GenDAG(Graph* graph, int* p3, int* p2, int* p1) {
- Node* level4 = graph->NewNode(&OPA0);
- Node* level3[] = {graph->NewNode(&OPA1, level4),
- graph->NewNode(&OPA1, level4)};
-
- Node* level2[] = {graph->NewNode(&OPA1, level3[p3[0]]),
- graph->NewNode(&OPA1, level3[p3[1]]),
- graph->NewNode(&OPA1, level3[p3[0]]),
- graph->NewNode(&OPA1, level3[p3[1]])};
-
- Node* level1[] = {graph->NewNode(&OPA2, level2[p2[0]], level2[p2[1]]),
- graph->NewNode(&OPA2, level2[p2[2]], level2[p2[3]])};
-
- Node* end = graph->NewNode(&OPA2, level1[p1[0]], level1[p1[1]]);
- graph->SetEnd(end);
-}
-
-
-TEST(SortForwardReduce) {
- GraphTester graph;
-
- // Tests combined reductions on a series of DAGs.
- for (int j = 0; j < 2; j++) {
- int p3[] = {j, 1 - j};
- for (int m = 0; m < 2; m++) {
- int p1[] = {m, 1 - m};
- for (int k = 0; k < 24; k++) { // All permutations of 0, 1, 2, 3
- int p2[] = {-1, -1, -1, -1};
- int n = k;
- for (int d = 4; d >= 1; d--) { // Construct permutation.
- int p = n % d;
- for (int z = 0; z < 4; z++) {
- if (p2[z] == -1) {
- if (p == 0) p2[z] = d - 1;
- p--;
- }
- }
- n = n / d;
- }
-
- GenDAG(&graph, p3, p2, p1);
-
- GraphReducer reducer(&graph);
- AB2Sorter r1;
- A1Forwarder r2;
- InPlaceABReducer r3;
- reducer.AddReducer(&r1);
- reducer.AddReducer(&r2);
- reducer.AddReducer(&r3);
-
- reducer.ReduceGraph();
-
- Node* end = graph.end();
- CHECK_EQ(&OPB2, end->op());
- Node* n1 = end->InputAt(0);
- Node* n2 = end->InputAt(1);
- CHECK_NE(n1, n2);
- CHECK(n1->id() < n2->id());
- CHECK_EQ(&OPB2, n1->op());
- CHECK_EQ(&OPB2, n2->op());
- Node* n4 = n1->InputAt(0);
- CHECK_EQ(&OPB0, n4->op());
- CHECK_EQ(n4, n1->InputAt(1));
- CHECK_EQ(n4, n2->InputAt(0));
- CHECK_EQ(n4, n2->InputAt(1));
- }
- }
- }
-}
-
-
-TEST(Order) {
- // Test that the order of reducers doesn't matter, as they should be
- // rerun for changed nodes.
- for (int i = 0; i < 2; i++) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* end = graph.NewNode(&OPA1, n1);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph);
- InPlaceABReducer abr;
- InPlaceBCReducer bcr;
- if (i == 0) {
- reducer.AddReducer(&abr);
- reducer.AddReducer(&bcr);
- } else {
- reducer.AddReducer(&bcr);
- reducer.AddReducer(&abr);
- }
-
- // Tests A* => C* with in-place updates.
- for (int i = 0; i < 3; i++) {
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPC0, n1->op());
- CHECK_EQ(&OPC1, end->op());
- CHECK_EQ(n1, end->InputAt(0));
- }
- }
-}
-
-
-// Tests that a reducer is only applied once.
-class OneTimeReducer : public Reducer {
- public:
- OneTimeReducer(Reducer* reducer, Zone* zone)
- : reducer_(reducer),
- nodes_(NodeSet::key_compare(), NodeSet::allocator_type(zone)) {}
- virtual Reduction Reduce(Node* node) {
- CHECK_EQ(0, nodes_.count(node));
- nodes_.insert(node);
- return reducer_->Reduce(node);
- }
- Reducer* reducer_;
- NodeSet nodes_;
-};
-
-
-TEST(OneTimeReduce1) {
- GraphTester graph;
-
- Node* n1 = graph.NewNode(&OPA0);
- Node* end = graph.NewNode(&OPA1, n1);
- graph.SetEnd(end);
-
- GraphReducer reducer(&graph);
- InPlaceABReducer r;
- OneTimeReducer once(&r, graph.zone());
- reducer.AddReducer(&once);
-
- // Tests A* => B* with in-place updates. Should only be applied once.
- int before = graph.NodeCount();
- reducer.ReduceGraph();
- CHECK_EQ(before, graph.NodeCount());
- CHECK_EQ(&OPB0, n1->op());
- CHECK_EQ(&OPB1, end->op());
- CHECK_EQ(n1, end->InputAt(0));
-}
+++ /dev/null
-// 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 <list>
-
-#include "test/cctest/compiler/instruction-selector-tester.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-namespace {
-
-typedef RawMachineAssembler::Label MLabel;
-
-struct DPI {
- Operator* op;
- ArchOpcode arch_opcode;
- ArchOpcode reverse_arch_opcode;
- ArchOpcode test_arch_opcode;
-};
-
-
-// ARM data processing instructions.
-class DPIs V8_FINAL : public std::list<DPI>, private HandleAndZoneScope {
- public:
- DPIs() {
- MachineOperatorBuilder machine(main_zone());
- DPI and_ = {machine.Word32And(), kArmAnd, kArmAnd, kArmTst};
- push_back(and_);
- DPI or_ = {machine.Word32Or(), kArmOrr, kArmOrr, kArmOrr};
- push_back(or_);
- DPI xor_ = {machine.Word32Xor(), kArmEor, kArmEor, kArmTeq};
- push_back(xor_);
- DPI add = {machine.Int32Add(), kArmAdd, kArmAdd, kArmCmn};
- push_back(add);
- DPI sub = {machine.Int32Sub(), kArmSub, kArmRsb, kArmCmp};
- push_back(sub);
- }
-};
-
-
-// ARM immediates.
-class Immediates V8_FINAL : public std::list<int32_t> {
- public:
- Immediates() {
- for (uint32_t imm8 = 0; imm8 < 256; ++imm8) {
- for (uint32_t rot4 = 0; rot4 < 32; rot4 += 2) {
- int32_t imm = (imm8 >> rot4) | (imm8 << (32 - rot4));
- CHECK(Assembler::ImmediateFitsAddrMode1Instruction(imm));
- push_back(imm);
- }
- }
- }
-};
-
-
-struct Shift {
- Operator* op;
- int32_t i_low; // lowest possible immediate
- int32_t i_high; // highest possible immediate
- AddressingMode i_mode; // Operand2_R_<shift>_I
- AddressingMode r_mode; // Operand2_R_<shift>_R
-};
-
-
-// ARM shifts.
-class Shifts V8_FINAL : public std::list<Shift>, private HandleAndZoneScope {
- public:
- Shifts() {
- MachineOperatorBuilder machine(main_zone());
- Shift sar = {machine.Word32Sar(), 1, 32, kMode_Operand2_R_ASR_I,
- kMode_Operand2_R_ASR_R};
- Shift shl = {machine.Word32Shl(), 0, 31, kMode_Operand2_R_LSL_I,
- kMode_Operand2_R_LSL_R};
- Shift shr = {machine.Word32Shr(), 1, 32, kMode_Operand2_R_LSR_I,
- kMode_Operand2_R_LSR_R};
- push_back(sar);
- push_back(shl);
- push_back(shr);
- }
-};
-
-} // namespace
-
-
-TEST(InstructionSelectorDPIP) {
- DPIs dpis;
- for (DPIs::const_iterator i = dpis.begin(); i != dpis.end(); ++i) {
- DPI dpi = *i;
- InstructionSelectorTester m;
- m.Return(m.NewNode(dpi.op, m.Parameter(0), m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- }
-}
-
-
-TEST(InstructionSelectorDPIAndShiftP) {
- DPIs dpis;
- Shifts shifts;
- for (DPIs::const_iterator i = dpis.begin(); i != dpis.end(); ++i) {
- DPI dpi = *i;
- for (Shifts::const_iterator j = shifts.begin(); j != shifts.end(); ++j) {
- Shift shift = *j;
- {
- InstructionSelectorTester m;
- m.Return(
- m.NewNode(dpi.op, m.Parameter(0),
- m.NewNode(shift.op, m.Parameter(1), m.Parameter(2))));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
- }
- {
- InstructionSelectorTester m;
- m.Return(m.NewNode(dpi.op,
- m.NewNode(shift.op, m.Parameter(0), m.Parameter(1)),
- m.Parameter(2)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.reverse_arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
- }
- }
- }
-}
-
-
-TEST(InstructionSelectorDPIAndShiftImm) {
- DPIs dpis;
- Shifts shifts;
- for (DPIs::const_iterator i = dpis.begin(); i != dpis.end(); ++i) {
- DPI dpi = *i;
- for (Shifts::const_iterator j = shifts.begin(); j != shifts.end(); ++j) {
- Shift shift = *j;
- for (int32_t imm = shift.i_low; imm <= shift.i_high; ++imm) {
- {
- InstructionSelectorTester m;
- m.Return(m.NewNode(
- dpi.op, m.Parameter(0),
- m.NewNode(shift.op, m.Parameter(1), m.Int32Constant(imm))));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
- }
- {
- InstructionSelectorTester m;
- m.Return(m.NewNode(
- dpi.op, m.NewNode(shift.op, m.Parameter(0), m.Int32Constant(imm)),
- m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.reverse_arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
- }
- }
- }
- }
-}
-
-
-TEST(InstructionSelectorWord32AndAndWord32XorWithMinus1P) {
- {
- InstructionSelectorTester m;
- m.Return(m.Word32And(m.Parameter(0),
- m.Word32Xor(m.Int32Constant(-1), m.Parameter(1))));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmBic, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- }
- {
- InstructionSelectorTester m;
- m.Return(m.Word32And(m.Parameter(0),
- m.Word32Xor(m.Parameter(1), m.Int32Constant(-1))));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmBic, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- }
- {
- InstructionSelectorTester m;
- m.Return(m.Word32And(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)),
- m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmBic, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- }
- {
- InstructionSelectorTester m;
- m.Return(m.Word32And(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)),
- m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmBic, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- }
-}
-
-
-TEST(InstructionSelectorWord32XorWithMinus1P) {
- {
- InstructionSelectorTester m;
- m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmMvn, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- }
- {
- InstructionSelectorTester m;
- m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmMvn, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- }
-}
-
-
-TEST(InstructionSelectorInt32MulP) {
- InstructionSelectorTester m;
- m.Return(m.Int32Mul(m.Parameter(0), m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmMul, m.code[0]->arch_opcode());
-}
-
-
-TEST(InstructionSelectorInt32MulImm) {
- // x * (2^k + 1) -> (x >> k) + x
- for (int k = 1; k < 31; ++k) {
- InstructionSelectorTester m;
- m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R_LSL_I, m.code[0]->addressing_mode());
- }
- // (2^k + 1) * x -> (x >> k) + x
- for (int k = 1; k < 31; ++k) {
- InstructionSelectorTester m;
- m.Return(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmAdd, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R_LSL_I, m.code[0]->addressing_mode());
- }
- // x * (2^k - 1) -> (x >> k) - x
- for (int k = 3; k < 31; ++k) {
- InstructionSelectorTester m;
- m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) - 1)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmRsb, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R_LSL_I, m.code[0]->addressing_mode());
- }
- // (2^k - 1) * x -> (x >> k) - x
- for (int k = 3; k < 31; ++k) {
- InstructionSelectorTester m;
- m.Return(m.Int32Mul(m.Int32Constant((1 << k) - 1), m.Parameter(0)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmRsb, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R_LSL_I, m.code[0]->addressing_mode());
- }
-}
-
-
-// The following tests depend on the exact CPU features available, which we do
-// only fully control in a simulator build.
-#ifdef USE_SIMULATOR
-
-TEST(InstructionSelectorDPIImm_ARMv7AndVFP3Disabled) {
- i::FLAG_enable_armv7 = false;
- i::FLAG_enable_vfp3 = false;
- DPIs dpis;
- Immediates immediates;
- for (DPIs::const_iterator i = dpis.begin(); i != dpis.end(); ++i) {
- DPI dpi = *i;
- for (Immediates::const_iterator j = immediates.begin();
- j != immediates.end(); ++j) {
- int32_t imm = *j;
- {
- InstructionSelectorTester m;
- m.Return(m.NewNode(dpi.op, m.Parameter(0), m.Int32Constant(imm)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
- }
- {
- InstructionSelectorTester m;
- m.Return(m.NewNode(dpi.op, m.Int32Constant(imm), m.Parameter(0)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.reverse_arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
- }
- }
- }
-}
-
-
-TEST(InstructionSelectorWord32AndImm_ARMv7Enabled) {
- i::FLAG_enable_armv7 = true;
- for (uint32_t width = 1; width <= 32; ++width) {
- InstructionSelectorTester m;
- m.Return(m.Word32And(m.Parameter(0),
- m.Int32Constant(0xffffffffu >> (32 - width))));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmUbfx, m.code[0]->arch_opcode());
- CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(0, m.ToInt32(m.code[0]->InputAt(1)));
- CHECK_EQ(width, m.ToInt32(m.code[0]->InputAt(2)));
- }
- for (uint32_t lsb = 0; lsb <= 31; ++lsb) {
- for (uint32_t width = 1; width < 32 - lsb; ++width) {
- uint32_t msk = ~((0xffffffffu >> (32 - width)) << lsb);
- InstructionSelectorTester m;
- m.Return(m.Word32And(m.Parameter(0), m.Int32Constant(msk)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmBfc, m.code[0]->arch_opcode());
- CHECK_EQ(1, m.code[0]->OutputCount());
- CHECK(UnallocatedOperand::cast(m.code[0]->Output())
- ->HasSameAsInputPolicy());
- CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(lsb, m.ToInt32(m.code[0]->InputAt(1)));
- CHECK_EQ(width, m.ToInt32(m.code[0]->InputAt(2)));
- }
- }
-}
-
-
-TEST(InstructionSelectorWord32AndAndWord32ShrImm_ARMv7Enabled) {
- i::FLAG_enable_armv7 = true;
- for (uint32_t lsb = 0; lsb <= 31; ++lsb) {
- for (uint32_t width = 1; width <= 32 - lsb; ++width) {
- {
- InstructionSelectorTester m;
- m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)),
- m.Int32Constant(0xffffffffu >> (32 - width))));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmUbfx, m.code[0]->arch_opcode());
- CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(lsb, m.ToInt32(m.code[0]->InputAt(1)));
- CHECK_EQ(width, m.ToInt32(m.code[0]->InputAt(2)));
- }
- {
- InstructionSelectorTester m;
- m.Return(
- m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)),
- m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb))));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmUbfx, m.code[0]->arch_opcode());
- CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(lsb, m.ToInt32(m.code[0]->InputAt(1)));
- CHECK_EQ(width, m.ToInt32(m.code[0]->InputAt(2)));
- }
- }
- }
-}
-
-
-TEST(InstructionSelectorWord32ShrAndWord32AndImm_ARMv7Enabled) {
- i::FLAG_enable_armv7 = true;
- for (uint32_t lsb = 0; lsb <= 31; ++lsb) {
- for (uint32_t width = 1; width <= 32 - lsb; ++width) {
- uint32_t max = 1 << lsb;
- if (max > kMaxInt) max -= 1;
- uint32_t jnk = CcTest::random_number_generator()->NextInt(max);
- uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk;
- {
- InstructionSelectorTester m;
- m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)),
- m.Int32Constant(lsb)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmUbfx, m.code[0]->arch_opcode());
- CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(lsb, m.ToInt32(m.code[0]->InputAt(1)));
- CHECK_EQ(width, m.ToInt32(m.code[0]->InputAt(2)));
- }
- {
- InstructionSelectorTester m;
- m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)),
- m.Int32Constant(lsb)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmUbfx, m.code[0]->arch_opcode());
- CHECK_EQ(3, m.code[0]->InputCount());
- CHECK_EQ(lsb, m.ToInt32(m.code[0]->InputAt(1)));
- CHECK_EQ(width, m.ToInt32(m.code[0]->InputAt(2)));
- }
- }
- }
-}
-
-
-TEST(InstructionSelectorInt32SubAndInt32MulP_MlsEnabled) {
- i::FLAG_enable_mls = true;
- InstructionSelectorTester m;
- m.Return(
- m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmMls, m.code[0]->arch_opcode());
-}
-
-
-TEST(InstructionSelectorInt32SubAndInt32MulP_MlsDisabled) {
- i::FLAG_enable_mls = false;
- InstructionSelectorTester m;
- m.Return(
- m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
- m.SelectInstructions();
- CHECK_EQ(2, m.code.size());
- CHECK_EQ(kArmMul, m.code[0]->arch_opcode());
- CHECK_EQ(1, m.code[0]->OutputCount());
- CHECK_EQ(kArmSub, m.code[1]->arch_opcode());
- CHECK_EQ(2, m.code[1]->InputCount());
- CheckSameVreg(m.code[0]->Output(), m.code[1]->InputAt(1));
-}
-
-
-TEST(InstructionSelectorInt32DivP_ARMv7AndSudivEnabled) {
- i::FLAG_enable_armv7 = true;
- i::FLAG_enable_sudiv = true;
- InstructionSelectorTester m;
- m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmSdiv, m.code[0]->arch_opcode());
-}
-
-
-TEST(InstructionSelectorInt32DivP_SudivDisabled) {
- i::FLAG_enable_sudiv = false;
- InstructionSelectorTester m;
- m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(4, m.code.size());
- CHECK_EQ(kArmVcvtF64S32, m.code[0]->arch_opcode());
- CHECK_EQ(1, m.code[0]->OutputCount());
- CHECK_EQ(kArmVcvtF64S32, m.code[1]->arch_opcode());
- CHECK_EQ(1, m.code[1]->OutputCount());
- CHECK_EQ(kArmVdivF64, m.code[2]->arch_opcode());
- CHECK_EQ(2, m.code[2]->InputCount());
- CHECK_EQ(1, m.code[2]->OutputCount());
- CheckSameVreg(m.code[0]->Output(), m.code[2]->InputAt(0));
- CheckSameVreg(m.code[1]->Output(), m.code[2]->InputAt(1));
- CHECK_EQ(kArmVcvtS32F64, m.code[3]->arch_opcode());
- CHECK_EQ(1, m.code[3]->InputCount());
- CheckSameVreg(m.code[2]->Output(), m.code[3]->InputAt(0));
-}
-
-
-TEST(InstructionSelectorInt32UDivP_ARMv7AndSudivEnabled) {
- i::FLAG_enable_armv7 = true;
- i::FLAG_enable_sudiv = true;
- InstructionSelectorTester m;
- m.Return(m.Int32UDiv(m.Parameter(0), m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmUdiv, m.code[0]->arch_opcode());
-}
-
-
-TEST(InstructionSelectorInt32UDivP_SudivDisabled) {
- i::FLAG_enable_sudiv = false;
- InstructionSelectorTester m;
- m.Return(m.Int32UDiv(m.Parameter(0), m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(4, m.code.size());
- CHECK_EQ(kArmVcvtF64U32, m.code[0]->arch_opcode());
- CHECK_EQ(1, m.code[0]->OutputCount());
- CHECK_EQ(kArmVcvtF64U32, m.code[1]->arch_opcode());
- CHECK_EQ(1, m.code[1]->OutputCount());
- CHECK_EQ(kArmVdivF64, m.code[2]->arch_opcode());
- CHECK_EQ(2, m.code[2]->InputCount());
- CHECK_EQ(1, m.code[2]->OutputCount());
- CheckSameVreg(m.code[0]->Output(), m.code[2]->InputAt(0));
- CheckSameVreg(m.code[1]->Output(), m.code[2]->InputAt(1));
- CHECK_EQ(kArmVcvtU32F64, m.code[3]->arch_opcode());
- CHECK_EQ(1, m.code[3]->InputCount());
- CheckSameVreg(m.code[2]->Output(), m.code[3]->InputAt(0));
-}
-
-
-TEST(InstructionSelectorInt32ModP_ARMv7AndMlsAndSudivEnabled) {
- i::FLAG_enable_armv7 = true;
- i::FLAG_enable_mls = true;
- i::FLAG_enable_sudiv = true;
- InstructionSelectorTester m;
- m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(2, m.code.size());
- CHECK_EQ(kArmSdiv, m.code[0]->arch_opcode());
- CHECK_EQ(1, m.code[0]->OutputCount());
- CHECK_EQ(2, m.code[0]->InputCount());
- CHECK_EQ(kArmMls, m.code[1]->arch_opcode());
- CHECK_EQ(1, m.code[1]->OutputCount());
- CHECK_EQ(3, m.code[1]->InputCount());
- CheckSameVreg(m.code[0]->Output(), m.code[1]->InputAt(0));
- CheckSameVreg(m.code[0]->InputAt(1), m.code[1]->InputAt(1));
- CheckSameVreg(m.code[0]->InputAt(0), m.code[1]->InputAt(2));
-}
-
-
-TEST(InstructionSelectorInt32ModP_ARMv7AndSudivEnabled) {
- i::FLAG_enable_armv7 = true;
- i::FLAG_enable_mls = false;
- i::FLAG_enable_sudiv = true;
- InstructionSelectorTester m;
- m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(3, m.code.size());
- CHECK_EQ(kArmSdiv, m.code[0]->arch_opcode());
- CHECK_EQ(1, m.code[0]->OutputCount());
- CHECK_EQ(2, m.code[0]->InputCount());
- CHECK_EQ(kArmMul, m.code[1]->arch_opcode());
- CHECK_EQ(1, m.code[1]->OutputCount());
- CHECK_EQ(2, m.code[1]->InputCount());
- CheckSameVreg(m.code[0]->Output(), m.code[1]->InputAt(0));
- CheckSameVreg(m.code[0]->InputAt(1), m.code[1]->InputAt(1));
- CHECK_EQ(kArmSub, m.code[2]->arch_opcode());
- CHECK_EQ(1, m.code[2]->OutputCount());
- CHECK_EQ(2, m.code[2]->InputCount());
- CheckSameVreg(m.code[0]->InputAt(0), m.code[2]->InputAt(0));
- CheckSameVreg(m.code[1]->Output(), m.code[2]->InputAt(1));
-}
-
-
-TEST(InstructionSelectorInt32ModP_ARMv7AndMlsAndSudivDisabled) {
- i::FLAG_enable_armv7 = false;
- i::FLAG_enable_mls = false;
- i::FLAG_enable_sudiv = false;
- InstructionSelectorTester m;
- m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(6, m.code.size());
- CHECK_EQ(kArmVcvtF64S32, m.code[0]->arch_opcode());
- CHECK_EQ(1, m.code[0]->OutputCount());
- CHECK_EQ(kArmVcvtF64S32, m.code[1]->arch_opcode());
- CHECK_EQ(1, m.code[1]->OutputCount());
- CHECK_EQ(kArmVdivF64, m.code[2]->arch_opcode());
- CHECK_EQ(2, m.code[2]->InputCount());
- CHECK_EQ(1, m.code[2]->OutputCount());
- CheckSameVreg(m.code[0]->Output(), m.code[2]->InputAt(0));
- CheckSameVreg(m.code[1]->Output(), m.code[2]->InputAt(1));
- CHECK_EQ(kArmVcvtS32F64, m.code[3]->arch_opcode());
- CHECK_EQ(1, m.code[3]->InputCount());
- CheckSameVreg(m.code[2]->Output(), m.code[3]->InputAt(0));
- CHECK_EQ(kArmMul, m.code[4]->arch_opcode());
- CHECK_EQ(1, m.code[4]->OutputCount());
- CHECK_EQ(2, m.code[4]->InputCount());
- CheckSameVreg(m.code[3]->Output(), m.code[4]->InputAt(0));
- CheckSameVreg(m.code[1]->InputAt(0), m.code[4]->InputAt(1));
- CHECK_EQ(kArmSub, m.code[5]->arch_opcode());
- CHECK_EQ(1, m.code[5]->OutputCount());
- CHECK_EQ(2, m.code[5]->InputCount());
- CheckSameVreg(m.code[0]->InputAt(0), m.code[5]->InputAt(0));
- CheckSameVreg(m.code[4]->Output(), m.code[5]->InputAt(1));
-}
-
-
-TEST(InstructionSelectorInt32UModP_ARMv7AndMlsAndSudivEnabled) {
- i::FLAG_enable_armv7 = true;
- i::FLAG_enable_mls = true;
- i::FLAG_enable_sudiv = true;
- InstructionSelectorTester m;
- m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(2, m.code.size());
- CHECK_EQ(kArmUdiv, m.code[0]->arch_opcode());
- CHECK_EQ(1, m.code[0]->OutputCount());
- CHECK_EQ(2, m.code[0]->InputCount());
- CHECK_EQ(kArmMls, m.code[1]->arch_opcode());
- CHECK_EQ(1, m.code[1]->OutputCount());
- CHECK_EQ(3, m.code[1]->InputCount());
- CheckSameVreg(m.code[0]->Output(), m.code[1]->InputAt(0));
- CheckSameVreg(m.code[0]->InputAt(1), m.code[1]->InputAt(1));
- CheckSameVreg(m.code[0]->InputAt(0), m.code[1]->InputAt(2));
-}
-
-
-TEST(InstructionSelectorInt32UModP_ARMv7AndSudivEnabled) {
- i::FLAG_enable_armv7 = true;
- i::FLAG_enable_mls = false;
- i::FLAG_enable_sudiv = true;
- InstructionSelectorTester m;
- m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(3, m.code.size());
- CHECK_EQ(kArmUdiv, m.code[0]->arch_opcode());
- CHECK_EQ(1, m.code[0]->OutputCount());
- CHECK_EQ(2, m.code[0]->InputCount());
- CHECK_EQ(kArmMul, m.code[1]->arch_opcode());
- CHECK_EQ(1, m.code[1]->OutputCount());
- CHECK_EQ(2, m.code[1]->InputCount());
- CheckSameVreg(m.code[0]->Output(), m.code[1]->InputAt(0));
- CheckSameVreg(m.code[0]->InputAt(1), m.code[1]->InputAt(1));
- CHECK_EQ(kArmSub, m.code[2]->arch_opcode());
- CHECK_EQ(1, m.code[2]->OutputCount());
- CHECK_EQ(2, m.code[2]->InputCount());
- CheckSameVreg(m.code[0]->InputAt(0), m.code[2]->InputAt(0));
- CheckSameVreg(m.code[1]->Output(), m.code[2]->InputAt(1));
-}
-
-
-TEST(InstructionSelectorInt32UModP_ARMv7AndMlsAndSudivDisabled) {
- i::FLAG_enable_armv7 = false;
- i::FLAG_enable_mls = false;
- i::FLAG_enable_sudiv = false;
- InstructionSelectorTester m;
- m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(6, m.code.size());
- CHECK_EQ(kArmVcvtF64U32, m.code[0]->arch_opcode());
- CHECK_EQ(1, m.code[0]->OutputCount());
- CHECK_EQ(kArmVcvtF64U32, m.code[1]->arch_opcode());
- CHECK_EQ(1, m.code[1]->OutputCount());
- CHECK_EQ(kArmVdivF64, m.code[2]->arch_opcode());
- CHECK_EQ(2, m.code[2]->InputCount());
- CHECK_EQ(1, m.code[2]->OutputCount());
- CheckSameVreg(m.code[0]->Output(), m.code[2]->InputAt(0));
- CheckSameVreg(m.code[1]->Output(), m.code[2]->InputAt(1));
- CHECK_EQ(kArmVcvtU32F64, m.code[3]->arch_opcode());
- CHECK_EQ(1, m.code[3]->InputCount());
- CheckSameVreg(m.code[2]->Output(), m.code[3]->InputAt(0));
- CHECK_EQ(kArmMul, m.code[4]->arch_opcode());
- CHECK_EQ(1, m.code[4]->OutputCount());
- CHECK_EQ(2, m.code[4]->InputCount());
- CheckSameVreg(m.code[3]->Output(), m.code[4]->InputAt(0));
- CheckSameVreg(m.code[1]->InputAt(0), m.code[4]->InputAt(1));
- CHECK_EQ(kArmSub, m.code[5]->arch_opcode());
- CHECK_EQ(1, m.code[5]->OutputCount());
- CHECK_EQ(2, m.code[5]->InputCount());
- CheckSameVreg(m.code[0]->InputAt(0), m.code[5]->InputAt(0));
- CheckSameVreg(m.code[4]->Output(), m.code[5]->InputAt(1));
-}
-
-#endif // USE_SIMULATOR
-
-
-TEST(InstructionSelectorWord32EqualP) {
- InstructionSelectorTester m;
- m.Return(m.Word32Equal(m.Parameter(0), m.Parameter(1)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
-}
-
-
-TEST(InstructionSelectorWord32EqualImm) {
- Immediates immediates;
- for (Immediates::const_iterator i = immediates.begin(); i != immediates.end();
- ++i) {
- int32_t imm = *i;
- {
- InstructionSelectorTester m;
- m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(imm)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- if (imm == 0) {
- CHECK_EQ(kArmTst, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- CHECK_EQ(2, m.code[0]->InputCount());
- CheckSameVreg(m.code[0]->InputAt(0), m.code[0]->InputAt(1));
- } else {
- CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
- }
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- {
- InstructionSelectorTester m;
- m.Return(m.Word32Equal(m.Int32Constant(imm), m.Parameter(0)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- if (imm == 0) {
- CHECK_EQ(kArmTst, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- CHECK_EQ(2, m.code[0]->InputCount());
- CheckSameVreg(m.code[0]->InputAt(0), m.code[0]->InputAt(1));
- } else {
- CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
- }
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- }
-}
-
-
-TEST(InstructionSelectorWord32EqualAndDPIP) {
- DPIs dpis;
- for (DPIs::const_iterator i = dpis.begin(); i != dpis.end(); ++i) {
- DPI dpi = *i;
- {
- InstructionSelectorTester m;
- m.Return(m.Word32Equal(m.NewNode(dpi.op, m.Parameter(0), m.Parameter(1)),
- m.Int32Constant(0)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.test_arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- {
- InstructionSelectorTester m;
- m.Return(
- m.Word32Equal(m.Int32Constant(0),
- m.NewNode(dpi.op, m.Parameter(0), m.Parameter(1))));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.test_arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- }
-}
-
-
-TEST(InstructionSelectorWord32EqualAndDPIImm) {
- DPIs dpis;
- Immediates immediates;
- for (DPIs::const_iterator i = dpis.begin(); i != dpis.end(); ++i) {
- DPI dpi = *i;
- for (Immediates::const_iterator j = immediates.begin();
- j != immediates.end(); ++j) {
- int32_t imm = *j;
- {
- InstructionSelectorTester m;
- m.Return(m.Word32Equal(
- m.NewNode(dpi.op, m.Parameter(0), m.Int32Constant(imm)),
- m.Int32Constant(0)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.test_arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- {
- InstructionSelectorTester m;
- m.Return(m.Word32Equal(
- m.NewNode(dpi.op, m.Int32Constant(imm), m.Parameter(0)),
- m.Int32Constant(0)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.test_arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- {
- InstructionSelectorTester m;
- m.Return(m.Word32Equal(
- m.Int32Constant(0),
- m.NewNode(dpi.op, m.Parameter(0), m.Int32Constant(imm))));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.test_arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- {
- InstructionSelectorTester m;
- m.Return(m.Word32Equal(
- m.Int32Constant(0),
- m.NewNode(dpi.op, m.Int32Constant(imm), m.Parameter(0))));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.test_arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_I, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- }
- }
-}
-
-
-TEST(InstructionSelectorWord32EqualAndShiftP) {
- Shifts shifts;
- for (Shifts::const_iterator i = shifts.begin(); i != shifts.end(); ++i) {
- Shift shift = *i;
- {
- InstructionSelectorTester m;
- m.Return(m.Word32Equal(
- m.Parameter(0), m.NewNode(shift.op, m.Parameter(1), m.Parameter(2))));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
- CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- {
- InstructionSelectorTester m;
- m.Return(m.Word32Equal(
- m.NewNode(shift.op, m.Parameter(0), m.Parameter(1)), m.Parameter(2)));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
- CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_set, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- }
-}
-
-
-TEST(InstructionSelectorBranchWithWord32EqualAndShiftP) {
- Shifts shifts;
- for (Shifts::const_iterator i = shifts.begin(); i != shifts.end(); ++i) {
- Shift shift = *i;
- {
- InstructionSelectorTester m;
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(m.Parameter(0), m.NewNode(shift.op, m.Parameter(1),
- m.Parameter(2))),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(1));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
- CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- {
- InstructionSelectorTester m;
- MLabel blocka, blockb;
- m.Branch(
- m.Word32Equal(m.NewNode(shift.op, m.Parameter(1), m.Parameter(2)),
- m.Parameter(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(1));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
- CHECK_EQ(shift.r_mode, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- }
-}
-
-
-TEST(InstructionSelectorBranchWithWord32EqualAndShiftImm) {
- Shifts shifts;
- for (Shifts::const_iterator i = shifts.begin(); i != shifts.end(); ++i) {
- Shift shift = *i;
- for (int32_t imm = shift.i_low; imm <= shift.i_high; ++imm) {
- {
- InstructionSelectorTester m;
- MLabel blocka, blockb;
- m.Branch(
- m.Word32Equal(m.Parameter(0), m.NewNode(shift.op, m.Parameter(1),
- m.Int32Constant(imm))),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(1));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
- CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- {
- InstructionSelectorTester m;
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(
- m.NewNode(shift.op, m.Parameter(1), m.Int32Constant(imm)),
- m.Parameter(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(1));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(kArmCmp, m.code[0]->arch_opcode());
- CHECK_EQ(shift.i_mode, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- }
- }
-}
-
-
-TEST(InstructionSelectorBranchWithDPIP) {
- DPIs dpis;
- for (DPIs::const_iterator i = dpis.begin(); i != dpis.end(); ++i) {
- DPI dpi = *i;
- {
- InstructionSelectorTester m;
- MLabel blocka, blockb;
- m.Branch(m.NewNode(dpi.op, m.Parameter(0), m.Parameter(1)), &blocka,
- &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(1));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.test_arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
- CHECK_EQ(kNotEqual, m.code[0]->flags_condition());
- }
- {
- InstructionSelectorTester m;
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(m.Int32Constant(0),
- m.NewNode(dpi.op, m.Parameter(0), m.Parameter(1))),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(1));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.test_arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- {
- InstructionSelectorTester m;
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(m.NewNode(dpi.op, m.Parameter(0), m.Parameter(1)),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(1));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0));
- m.SelectInstructions();
- CHECK_EQ(1, m.code.size());
- CHECK_EQ(dpi.test_arch_opcode, m.code[0]->arch_opcode());
- CHECK_EQ(kMode_Operand2_R, m.code[0]->addressing_mode());
- CHECK_EQ(kFlags_branch, m.code[0]->flags_mode());
- CHECK_EQ(kEqual, m.code[0]->flags_condition());
- }
- }
-}
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "test/cctest/compiler/instruction-selector-tester.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-TEST(InstructionSelectionReturnZero) {
- InstructionSelectorTester m(InstructionSelectorTester::kInternalMode);
- m.Return(m.Int32Constant(0));
- m.SelectInstructions();
- CHECK_EQ(2, m.code.size());
- CHECK_EQ(kArchNop, m.code[0]->opcode());
- CHECK_EQ(kArchRet, m.code[1]->opcode());
- CHECK_EQ(1, m.code[1]->InputCount());
-}
+++ /dev/null
-// 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.h"
-#include "src/compiler/machine-operator.h"
-#include "src/compiler/node.h"
-#include "src/compiler/operator.h"
-#include "src/compiler/schedule.h"
-#include "src/compiler/scheduler.h"
-#include "src/lithium.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-typedef v8::internal::compiler::Instruction TestInstr;
-typedef v8::internal::compiler::InstructionSequence TestInstrSeq;
-
-// A testing helper for the register code abstraction.
-class InstructionTester : public HandleAndZoneScope {
- public: // We're all friends here.
- explicit InstructionTester()
- : isolate(main_isolate()),
- graph(zone()),
- schedule(zone()),
- info(static_cast<HydrogenCodeStub*>(NULL), main_isolate()),
- linkage(&info),
- common(zone()),
- machine(zone(), kMachineWord32),
- code(NULL) {}
-
- Isolate* isolate;
- Graph graph;
- Schedule schedule;
- CompilationInfoWithZone info;
- Linkage linkage;
- CommonOperatorBuilder common;
- MachineOperatorBuilder machine;
- TestInstrSeq* code;
-
- Zone* zone() { return main_zone(); }
-
- void allocCode() {
- if (schedule.rpo_order()->size() == 0) {
- // Compute the RPO order.
- Scheduler scheduler(zone(), &graph, &schedule);
- scheduler.ComputeSpecialRPO();
- ASSERT(schedule.rpo_order()->size() > 0);
- }
- code = new TestInstrSeq(&linkage, &graph, &schedule);
- }
-
- Node* Int32Constant(int32_t val) {
- Node* node = graph.NewNode(common.Int32Constant(val));
- schedule.AddNode(schedule.entry(), node);
- return node;
- }
-
- Node* Float64Constant(double val) {
- Node* node = graph.NewNode(common.Float64Constant(val));
- schedule.AddNode(schedule.entry(), node);
- return node;
- }
-
- Node* Parameter(int32_t which) {
- Node* node = graph.NewNode(common.Parameter(which));
- schedule.AddNode(schedule.entry(), node);
- return node;
- }
-
- Node* NewNode(BasicBlock* block) {
- Node* node = graph.NewNode(common.Int32Constant(111));
- schedule.AddNode(block, node);
- return node;
- }
-
- int NewInstr(BasicBlock* block) {
- InstructionCode opcode = static_cast<InstructionCode>(110);
- TestInstr* instr = TestInstr::New(zone(), opcode);
- return code->AddInstruction(instr, block);
- }
-
- UnallocatedOperand* NewUnallocated(int vreg) {
- UnallocatedOperand* unallocated =
- new (zone()) UnallocatedOperand(UnallocatedOperand::ANY);
- unallocated->set_virtual_register(vreg);
- return unallocated;
- }
-};
-
-
-TEST(InstructionBasic) {
- InstructionTester R;
-
- for (int i = 0; i < 10; i++) {
- R.Int32Constant(i); // Add some nodes to the graph.
- }
-
- BasicBlock* last = R.schedule.entry();
- for (int i = 0; i < 5; i++) {
- BasicBlock* block = R.schedule.NewBasicBlock();
- R.schedule.AddGoto(last, block);
- last = block;
- }
-
- R.allocCode();
-
- CHECK_EQ(R.graph.NodeCount(), R.code->ValueCount());
-
- BasicBlockVector* blocks = R.schedule.rpo_order();
- CHECK_EQ(static_cast<int>(blocks->size()), R.code->BasicBlockCount());
-
- int index = 0;
- for (BasicBlockVectorIter i = blocks->begin(); i != blocks->end();
- i++, index++) {
- BasicBlock* block = *i;
- CHECK_EQ(block, R.code->BlockAt(index));
- CHECK_EQ(-1, R.code->GetLoopEnd(block));
- }
-}
-
-
-TEST(InstructionGetBasicBlock) {
- InstructionTester R;
-
- BasicBlock* b0 = R.schedule.entry();
- BasicBlock* b1 = R.schedule.NewBasicBlock();
- BasicBlock* b2 = R.schedule.NewBasicBlock();
- BasicBlock* b3 = R.schedule.exit();
-
- R.schedule.AddGoto(b0, b1);
- R.schedule.AddGoto(b1, b2);
- R.schedule.AddGoto(b2, b3);
-
- R.allocCode();
-
- R.code->StartBlock(b0);
- int i0 = R.NewInstr(b0);
- int i1 = R.NewInstr(b0);
- R.code->EndBlock(b0);
- R.code->StartBlock(b1);
- int i2 = R.NewInstr(b1);
- int i3 = R.NewInstr(b1);
- int i4 = R.NewInstr(b1);
- int i5 = R.NewInstr(b1);
- R.code->EndBlock(b1);
- R.code->StartBlock(b2);
- int i6 = R.NewInstr(b2);
- int i7 = R.NewInstr(b2);
- int i8 = R.NewInstr(b2);
- R.code->EndBlock(b2);
- R.code->StartBlock(b3);
- R.code->EndBlock(b3);
-
- CHECK_EQ(b0, R.code->GetBasicBlock(i0));
- CHECK_EQ(b0, R.code->GetBasicBlock(i1));
-
- CHECK_EQ(b1, R.code->GetBasicBlock(i2));
- CHECK_EQ(b1, R.code->GetBasicBlock(i3));
- CHECK_EQ(b1, R.code->GetBasicBlock(i4));
- CHECK_EQ(b1, R.code->GetBasicBlock(i5));
-
- CHECK_EQ(b2, R.code->GetBasicBlock(i6));
- CHECK_EQ(b2, R.code->GetBasicBlock(i7));
- CHECK_EQ(b2, R.code->GetBasicBlock(i8));
-
- CHECK_EQ(b0, R.code->GetBasicBlock(b0->first_instruction_index()));
- CHECK_EQ(b0, R.code->GetBasicBlock(b0->last_instruction_index()));
-
- CHECK_EQ(b1, R.code->GetBasicBlock(b1->first_instruction_index()));
- CHECK_EQ(b1, R.code->GetBasicBlock(b1->last_instruction_index()));
-
- CHECK_EQ(b2, R.code->GetBasicBlock(b2->first_instruction_index()));
- CHECK_EQ(b2, R.code->GetBasicBlock(b2->last_instruction_index()));
-
- CHECK_EQ(b3, R.code->GetBasicBlock(b3->first_instruction_index()));
- CHECK_EQ(b3, R.code->GetBasicBlock(b3->last_instruction_index()));
-}
-
-
-TEST(InstructionIsGapAt) {
- InstructionTester R;
-
- BasicBlock* b0 = R.schedule.entry();
- R.schedule.AddReturn(b0, R.Int32Constant(1));
-
- R.allocCode();
- TestInstr* i0 = TestInstr::New(R.zone(), 100);
- TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl();
- R.code->StartBlock(b0);
- R.code->AddInstruction(i0, b0);
- R.code->AddInstruction(g, b0);
- R.code->EndBlock(b0);
-
- CHECK_EQ(true, R.code->InstructionAt(0)->IsBlockStart());
-
- CHECK_EQ(true, R.code->IsGapAt(0)); // Label
- CHECK_EQ(true, R.code->IsGapAt(1)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(2)); // i0
- CHECK_EQ(true, R.code->IsGapAt(3)); // Gap
- CHECK_EQ(true, R.code->IsGapAt(4)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(5)); // g
-}
-
-
-TEST(InstructionIsGapAt2) {
- InstructionTester R;
-
- BasicBlock* b0 = R.schedule.entry();
- BasicBlock* b1 = R.schedule.exit();
- R.schedule.AddGoto(b0, b1);
- R.schedule.AddReturn(b1, R.Int32Constant(1));
-
- R.allocCode();
- TestInstr* i0 = TestInstr::New(R.zone(), 100);
- TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl();
- R.code->StartBlock(b0);
- R.code->AddInstruction(i0, b0);
- R.code->AddInstruction(g, b0);
- R.code->EndBlock(b0);
-
- TestInstr* i1 = TestInstr::New(R.zone(), 102);
- TestInstr* g1 = TestInstr::New(R.zone(), 104)->MarkAsControl();
- R.code->StartBlock(b1);
- R.code->AddInstruction(i1, b1);
- R.code->AddInstruction(g1, b1);
- R.code->EndBlock(b1);
-
- CHECK_EQ(true, R.code->InstructionAt(0)->IsBlockStart());
-
- CHECK_EQ(true, R.code->IsGapAt(0)); // Label
- CHECK_EQ(true, R.code->IsGapAt(1)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(2)); // i0
- CHECK_EQ(true, R.code->IsGapAt(3)); // Gap
- CHECK_EQ(true, R.code->IsGapAt(4)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(5)); // g
-
- CHECK_EQ(true, R.code->InstructionAt(6)->IsBlockStart());
-
- CHECK_EQ(true, R.code->IsGapAt(6)); // Label
- CHECK_EQ(true, R.code->IsGapAt(7)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(8)); // i1
- CHECK_EQ(true, R.code->IsGapAt(9)); // Gap
- CHECK_EQ(true, R.code->IsGapAt(10)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(11)); // g1
-}
-
-
-TEST(InstructionAddGapMove) {
- InstructionTester R;
-
- BasicBlock* b0 = R.schedule.entry();
- R.schedule.AddReturn(b0, R.Int32Constant(1));
-
- R.allocCode();
- TestInstr* i0 = TestInstr::New(R.zone(), 100);
- TestInstr* g = TestInstr::New(R.zone(), 103)->MarkAsControl();
- R.code->StartBlock(b0);
- R.code->AddInstruction(i0, b0);
- R.code->AddInstruction(g, b0);
- R.code->EndBlock(b0);
-
- CHECK_EQ(true, R.code->InstructionAt(0)->IsBlockStart());
-
- CHECK_EQ(true, R.code->IsGapAt(0)); // Label
- CHECK_EQ(true, R.code->IsGapAt(1)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(2)); // i0
- CHECK_EQ(true, R.code->IsGapAt(3)); // Gap
- CHECK_EQ(true, R.code->IsGapAt(4)); // Gap
- CHECK_EQ(false, R.code->IsGapAt(5)); // g
-
- int indexes[] = {0, 1, 3, 4, -1};
- for (int i = 0; indexes[i] >= 0; i++) {
- int index = indexes[i];
-
- UnallocatedOperand* op1 = R.NewUnallocated(index + 6);
- UnallocatedOperand* op2 = R.NewUnallocated(index + 12);
-
- R.code->AddGapMove(index, op1, op2);
- GapInstruction* gap = R.code->GapAt(index);
- ParallelMove* move = gap->GetParallelMove(GapInstruction::START);
- CHECK_NE(NULL, move);
- const ZoneList<MoveOperands>* move_operands = move->move_operands();
- CHECK_EQ(1, move_operands->length());
- MoveOperands* cur = &move_operands->at(0);
- CHECK_EQ(op1, cur->source());
- CHECK_EQ(op2, cur->destination());
- }
-}
-
-
-TEST(InstructionOperands) {
- Zone zone(CcTest::InitIsolateOnce());
-
- {
- TestInstr* i = TestInstr::New(&zone, 101);
- CHECK_EQ(0, i->OutputCount());
- CHECK_EQ(0, i->InputCount());
- CHECK_EQ(0, i->TempCount());
- }
-
- InstructionOperand* outputs[] = {
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER)};
-
- InstructionOperand* inputs[] = {
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER)};
-
- InstructionOperand* temps[] = {
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER),
- new (&zone) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER)};
-
- for (size_t i = 0; i < ARRAY_SIZE(outputs); i++) {
- for (size_t j = 0; j < ARRAY_SIZE(inputs); j++) {
- for (size_t k = 0; k < ARRAY_SIZE(temps); k++) {
- TestInstr* m =
- TestInstr::New(&zone, 101, i, outputs, j, inputs, k, temps);
- CHECK(i == m->OutputCount());
- CHECK(j == m->InputCount());
- CHECK(k == m->TempCount());
-
- for (size_t z = 0; z < i; z++) {
- CHECK_EQ(outputs[z], m->OutputAt(z));
- }
-
- for (size_t z = 0; z < j; z++) {
- CHECK_EQ(inputs[z], m->InputAt(z));
- }
-
- for (size_t z = 0; z < k; z++) {
- CHECK_EQ(temps[z], m->TempAt(z));
- }
- }
- }
- }
-}
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-
-#include "src/compiler/js-graph.h"
-#include "src/compiler/node-properties-inl.h"
-#include "src/compiler/typer.h"
-#include "src/types.h"
-#include "test/cctest/cctest.h"
-#include "test/cctest/compiler/value-helper.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-class JSCacheTesterHelper {
- protected:
- explicit JSCacheTesterHelper(Zone* zone)
- : main_graph_(zone), main_common_(zone), main_typer_(zone) {}
- Graph main_graph_;
- CommonOperatorBuilder main_common_;
- Typer main_typer_;
-};
-
-
-class JSConstantCacheTester : public HandleAndZoneScope,
- public JSCacheTesterHelper,
- public JSGraph {
- public:
- JSConstantCacheTester()
- : JSCacheTesterHelper(main_zone()),
- JSGraph(&main_graph_, &main_common_, &main_typer_) {}
-
- Type* upper(Node* node) { return NodeProperties::GetBounds(node).upper; }
-
- Handle<Object> handle(Node* node) {
- CHECK_EQ(IrOpcode::kHeapConstant, node->opcode());
- return ValueOf<Handle<Object> >(node->op());
- }
-
- Factory* factory() { return main_isolate()->factory(); }
-};
-
-
-TEST(ZeroConstant1) {
- JSConstantCacheTester T;
-
- Node* zero = T.ZeroConstant();
-
- CHECK_EQ(IrOpcode::kNumberConstant, zero->opcode());
- CHECK_EQ(zero, T.Constant(0));
- CHECK_NE(zero, T.Constant(-0.0));
- CHECK_NE(zero, T.Constant(1.0));
- CHECK_NE(zero, T.Constant(v8::base::OS::nan_value()));
- CHECK_NE(zero, T.Float64Constant(0));
- CHECK_NE(zero, T.Int32Constant(0));
-
- Type* t = T.upper(zero);
-
- CHECK(t->Is(Type::Number()));
- CHECK(t->Is(Type::Integral32()));
- CHECK(t->Is(Type::Signed32()));
- CHECK(t->Is(Type::Unsigned32()));
- CHECK(t->Is(Type::SignedSmall()));
- CHECK(t->Is(Type::UnsignedSmall()));
-}
-
-
-TEST(MinusZeroConstant) {
- JSConstantCacheTester T;
-
- Node* minus_zero = T.Constant(-0.0);
- Node* zero = T.ZeroConstant();
-
- CHECK_EQ(IrOpcode::kNumberConstant, minus_zero->opcode());
- CHECK_EQ(minus_zero, T.Constant(-0.0));
- CHECK_NE(zero, minus_zero);
-
- Type* t = T.upper(minus_zero);
-
- CHECK(t->Is(Type::Number()));
- CHECK(t->Is(Type::MinusZero()));
- CHECK(!t->Is(Type::Integral32()));
- CHECK(!t->Is(Type::Signed32()));
- CHECK(!t->Is(Type::Unsigned32()));
- CHECK(!t->Is(Type::SignedSmall()));
- CHECK(!t->Is(Type::UnsignedSmall()));
-
- double zero_value = ValueOf<double>(zero->op());
- double minus_zero_value = ValueOf<double>(minus_zero->op());
-
- CHECK_EQ(0.0, zero_value);
- CHECK_NE(-0.0, zero_value);
- CHECK_EQ(-0.0, minus_zero_value);
- CHECK_NE(0.0, minus_zero_value);
-}
-
-
-TEST(ZeroConstant2) {
- JSConstantCacheTester T;
-
- Node* zero = T.Constant(0);
-
- CHECK_EQ(IrOpcode::kNumberConstant, zero->opcode());
- CHECK_EQ(zero, T.ZeroConstant());
- CHECK_NE(zero, T.Constant(-0.0));
- CHECK_NE(zero, T.Constant(1.0));
- CHECK_NE(zero, T.Constant(v8::base::OS::nan_value()));
- CHECK_NE(zero, T.Float64Constant(0));
- CHECK_NE(zero, T.Int32Constant(0));
-
- Type* t = T.upper(zero);
-
- CHECK(t->Is(Type::Number()));
- CHECK(t->Is(Type::Integral32()));
- CHECK(t->Is(Type::Signed32()));
- CHECK(t->Is(Type::Unsigned32()));
- CHECK(t->Is(Type::SignedSmall()));
- CHECK(t->Is(Type::UnsignedSmall()));
-}
-
-
-TEST(OneConstant1) {
- JSConstantCacheTester T;
-
- Node* one = T.OneConstant();
-
- CHECK_EQ(IrOpcode::kNumberConstant, one->opcode());
- CHECK_EQ(one, T.Constant(1));
- CHECK_EQ(one, T.Constant(1.0));
- CHECK_NE(one, T.Constant(1.01));
- CHECK_NE(one, T.Constant(-1.01));
- CHECK_NE(one, T.Constant(v8::base::OS::nan_value()));
- CHECK_NE(one, T.Float64Constant(1.0));
- CHECK_NE(one, T.Int32Constant(1));
-
- Type* t = T.upper(one);
-
- CHECK(t->Is(Type::Number()));
- CHECK(t->Is(Type::Integral32()));
- CHECK(t->Is(Type::Signed32()));
- CHECK(t->Is(Type::Unsigned32()));
- CHECK(t->Is(Type::SignedSmall()));
- CHECK(t->Is(Type::UnsignedSmall()));
-}
-
-
-TEST(OneConstant2) {
- JSConstantCacheTester T;
-
- Node* one = T.Constant(1);
-
- CHECK_EQ(IrOpcode::kNumberConstant, one->opcode());
- CHECK_EQ(one, T.OneConstant());
- CHECK_EQ(one, T.Constant(1.0));
- CHECK_NE(one, T.Constant(1.01));
- CHECK_NE(one, T.Constant(-1.01));
- CHECK_NE(one, T.Constant(v8::base::OS::nan_value()));
- CHECK_NE(one, T.Float64Constant(1.0));
- CHECK_NE(one, T.Int32Constant(1));
-
- Type* t = T.upper(one);
-
- CHECK(t->Is(Type::Number()));
- CHECK(t->Is(Type::Integral32()));
- CHECK(t->Is(Type::Signed32()));
- CHECK(t->Is(Type::Unsigned32()));
- CHECK(t->Is(Type::SignedSmall()));
- CHECK(t->Is(Type::UnsignedSmall()));
-}
-
-
-TEST(Canonicalizations) {
- JSConstantCacheTester T;
-
- CHECK_EQ(T.ZeroConstant(), T.ZeroConstant());
- CHECK_EQ(T.UndefinedConstant(), T.UndefinedConstant());
- CHECK_EQ(T.TheHoleConstant(), T.TheHoleConstant());
- CHECK_EQ(T.TrueConstant(), T.TrueConstant());
- CHECK_EQ(T.FalseConstant(), T.FalseConstant());
- CHECK_EQ(T.NullConstant(), T.NullConstant());
- CHECK_EQ(T.ZeroConstant(), T.ZeroConstant());
- CHECK_EQ(T.OneConstant(), T.OneConstant());
- CHECK_EQ(T.NaNConstant(), T.NaNConstant());
-}
-
-
-TEST(NoAliasing) {
- JSConstantCacheTester T;
-
- Node* nodes[] = {T.UndefinedConstant(), T.TheHoleConstant(), T.TrueConstant(),
- T.FalseConstant(), T.NullConstant(), T.ZeroConstant(),
- T.OneConstant(), T.NaNConstant(), T.Constant(21),
- T.Constant(22.2)};
-
- for (size_t i = 0; i < ARRAY_SIZE(nodes); i++) {
- for (size_t j = 0; j < ARRAY_SIZE(nodes); j++) {
- if (i != j) CHECK_NE(nodes[i], nodes[j]);
- }
- }
-}
-
-
-TEST(CanonicalizingNumbers) {
- JSConstantCacheTester T;
-
- FOR_FLOAT64_INPUTS(i) {
- Node* node = T.Constant(*i);
- for (int j = 0; j < 5; j++) {
- CHECK_EQ(node, T.Constant(*i));
- }
- }
-}
-
-
-TEST(NumberTypes) {
- JSConstantCacheTester T;
-
- FOR_FLOAT64_INPUTS(i) {
- double value = *i;
- Node* node = T.Constant(value);
- CHECK(T.upper(node)->Equals(Type::Of(value, T.main_zone())));
- }
-}
-
-
-TEST(HeapNumbers) {
- JSConstantCacheTester T;
-
- FOR_FLOAT64_INPUTS(i) {
- double value = *i;
- Handle<Object> num = T.factory()->NewNumber(value);
- Handle<HeapNumber> heap = T.factory()->NewHeapNumber(value);
- Node* node1 = T.Constant(value);
- Node* node2 = T.Constant(num);
- Node* node3 = T.Constant(heap);
- CHECK_EQ(node1, node2);
- CHECK_EQ(node1, node3);
- }
-}
-
-
-TEST(OddballHandle) {
- JSConstantCacheTester T;
-
- CHECK_EQ(T.UndefinedConstant(), T.Constant(T.factory()->undefined_value()));
- CHECK_EQ(T.TheHoleConstant(), T.Constant(T.factory()->the_hole_value()));
- CHECK_EQ(T.TrueConstant(), T.Constant(T.factory()->true_value()));
- CHECK_EQ(T.FalseConstant(), T.Constant(T.factory()->false_value()));
- CHECK_EQ(T.NullConstant(), T.Constant(T.factory()->null_value()));
- CHECK_EQ(T.NaNConstant(), T.Constant(T.factory()->nan_value()));
-}
-
-
-TEST(OddballValues) {
- JSConstantCacheTester T;
-
- CHECK_EQ(*T.factory()->undefined_value(), *T.handle(T.UndefinedConstant()));
- CHECK_EQ(*T.factory()->the_hole_value(), *T.handle(T.TheHoleConstant()));
- CHECK_EQ(*T.factory()->true_value(), *T.handle(T.TrueConstant()));
- CHECK_EQ(*T.factory()->false_value(), *T.handle(T.FalseConstant()));
- CHECK_EQ(*T.factory()->null_value(), *T.handle(T.NullConstant()));
-}
-
-
-TEST(OddballTypes) {
- JSConstantCacheTester T;
-
- CHECK(T.upper(T.UndefinedConstant())->Is(Type::Undefined()));
- // TODO(dcarney): figure this out.
- // CHECK(T.upper(T.TheHoleConstant())->Is(Type::Internal()));
- CHECK(T.upper(T.TrueConstant())->Is(Type::Boolean()));
- CHECK(T.upper(T.FalseConstant())->Is(Type::Boolean()));
- CHECK(T.upper(T.NullConstant())->Is(Type::Null()));
- CHECK(T.upper(T.ZeroConstant())->Is(Type::Number()));
- CHECK(T.upper(T.OneConstant())->Is(Type::Number()));
- CHECK(T.upper(T.NaNConstant())->Is(Type::NaN()));
-}
-
-
-TEST(ExternalReferences) {
- // TODO(titzer): test canonicalization of external references.
-}
+++ /dev/null
-// 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/compiler/js-context-specialization.h"
-#include "src/compiler/js-operator.h"
-#include "src/compiler/node-matchers.h"
-#include "src/compiler/node-properties-inl.h"
-#include "src/compiler/simplified-node-factory.h"
-#include "src/compiler/source-position.h"
-#include "src/compiler/typer.h"
-#include "test/cctest/cctest.h"
-#include "test/cctest/compiler/function-tester.h"
-#include "test/cctest/compiler/graph-builder-tester.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-class ContextSpecializationTester
- : public HandleAndZoneScope,
- public DirectGraphBuilder,
- public SimplifiedNodeFactory<ContextSpecializationTester> {
- public:
- ContextSpecializationTester()
- : DirectGraphBuilder(new (main_zone()) Graph(main_zone())),
- common_(main_zone()),
- javascript_(main_zone()),
- simplified_(main_zone()),
- typer_(main_zone()),
- jsgraph_(graph(), common(), &typer_),
- info_(main_isolate(), main_zone()) {}
-
- Factory* factory() { return main_isolate()->factory(); }
- CommonOperatorBuilder* common() { return &common_; }
- JSOperatorBuilder* javascript() { return &javascript_; }
- SimplifiedOperatorBuilder* simplified() { return &simplified_; }
- JSGraph* jsgraph() { return &jsgraph_; }
- CompilationInfo* info() { return &info_; }
-
- private:
- CommonOperatorBuilder common_;
- JSOperatorBuilder javascript_;
- SimplifiedOperatorBuilder simplified_;
- Typer typer_;
- JSGraph jsgraph_;
- CompilationInfo info_;
-};
-
-
-TEST(ReduceJSLoadContext) {
- ContextSpecializationTester t;
-
- Node* start = t.NewNode(t.common()->Start());
- t.graph()->SetStart(start);
-
- // Make a context and initialize it a bit for this test.
- Handle<Context> native = t.factory()->NewNativeContext();
- Handle<Context> ctx1 = t.factory()->NewNativeContext();
- Handle<Context> ctx2 = t.factory()->NewNativeContext();
- ctx2->set_previous(*ctx1);
- ctx1->set_previous(*native);
- Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!");
- const int slot = Context::GLOBAL_OBJECT_INDEX;
- native->set(slot, *expected);
-
- Node* const_context = t.jsgraph()->Constant(native);
- Node* param_context = t.NewNode(t.common()->Parameter(0));
- JSContextSpecializer spec(t.info(), t.jsgraph(), const_context);
-
- {
- // Mutable slot, constant context, depth = 0 => do nothing.
- t.info()->SetContext(native);
- Node* load = t.NewNode(t.javascript()->LoadContext(0, 0, false),
- const_context, start, start);
- Reduction r = spec.ReduceJSLoadContext(load);
- CHECK(!r.Changed());
- }
-
- {
- // Mutable slot, non-constant context, depth = 0 => do nothing.
- t.info()->SetContext(native);
- Node* load = t.NewNode(t.javascript()->LoadContext(0, 0, false),
- param_context, start, start);
- Reduction r = spec.ReduceJSLoadContext(load);
- CHECK(!r.Changed());
- }
-
- {
- // Mutable slot, non-constant context, depth > 0 => fold-in parent context.
- t.info()->SetContext(ctx2);
- Node* load = t.NewNode(
- t.javascript()->LoadContext(2, Context::GLOBAL_EVAL_FUN_INDEX, false),
- param_context, start, start);
- Reduction r = spec.ReduceJSLoadContext(load);
- CHECK(r.Changed());
- CHECK_EQ(IrOpcode::kHeapConstant, r.replacement()->InputAt(0)->opcode());
- ValueMatcher<Handle<Context> > match(r.replacement()->InputAt(0));
- CHECK_EQ(*native, *match.Value());
- ContextAccess access = static_cast<Operator1<ContextAccess>*>(
- r.replacement()->op())->parameter();
- CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, access.index());
- CHECK_EQ(0, access.depth());
- CHECK_EQ(false, access.immutable());
- }
-
- {
- // Immutable slot, constant context => specialize.
- t.info()->SetContext(native);
- Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true),
- const_context, start, start);
- Reduction r = spec.ReduceJSLoadContext(load);
- CHECK(r.Changed());
- CHECK(r.replacement() != load);
-
- ValueMatcher<Handle<Object> > match(r.replacement());
- CHECK(match.HasValue());
- CHECK_EQ(*expected, *match.Value());
- }
-
- {
- // Immutable slot, non-constant context => specialize.
- t.info()->SetContext(native);
- Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true),
- param_context, start, start);
- Reduction r = spec.ReduceJSLoadContext(load);
- CHECK(r.Changed());
- CHECK(r.replacement() != load);
-
- ValueMatcher<Handle<Object> > match(r.replacement());
- CHECK(match.HasValue());
- CHECK_EQ(*expected, *match.Value());
- }
-
- // TODO(titzer): test with other kinds of contexts, e.g. a function context.
- // TODO(sigurds): test that loads below create context are not optimized
-}
-
-
-// TODO(titzer): factor out common code with effects checking in typed lowering.
-static void CheckEffectInput(Node* effect, Node* use) {
- CHECK_EQ(effect, NodeProperties::GetEffectInput(use));
-}
-
-
-TEST(SpecializeToContext) {
- ContextSpecializationTester t;
-
- Node* start = t.NewNode(t.common()->Start());
- t.graph()->SetStart(start);
-
- // Make a context and initialize it a bit for this test.
- Handle<Context> native = t.factory()->NewNativeContext();
- Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!");
- const int slot = Context::GLOBAL_OBJECT_INDEX;
- native->set(slot, *expected);
- t.info()->SetContext(native);
-
- Node* const_context = t.jsgraph()->Constant(native);
- Node* param_context = t.NewNode(t.common()->Parameter(0));
- JSContextSpecializer spec(t.info(), t.jsgraph(), const_context);
-
- {
- // Check that SpecializeToContext() replaces values and forwards effects
- // correctly, and folds values from constant and non-constant contexts
- Node* effect_in = t.NewNode(t.common()->Start());
- Node* load = t.NewNode(t.javascript()->LoadContext(0, slot, true),
- const_context, const_context, effect_in, start);
-
-
- Node* value_use = t.ChangeTaggedToInt32(load);
- Node* other_load = t.NewNode(t.javascript()->LoadContext(0, slot, true),
- param_context, param_context, load, start);
- Node* effect_use = other_load;
- Node* other_use = t.ChangeTaggedToInt32(other_load);
-
- // Double check the above graph is what we expect, or the test is broken.
- CheckEffectInput(effect_in, load);
- CheckEffectInput(load, effect_use);
-
- // Perform the substitution on the entire graph.
- spec.SpecializeToContext();
-
- // Effects should have been forwarded (not replaced with a value).
- CheckEffectInput(effect_in, effect_use);
-
- // Use of {other_load} should not have been replaced.
- CHECK_EQ(other_load, other_use->InputAt(0));
-
- Node* replacement = value_use->InputAt(0);
- ValueMatcher<Handle<Object> > match(replacement);
- CHECK(match.HasValue());
- CHECK_EQ(*expected, *match.Value());
- }
- // TODO(titzer): clean up above test and test more complicated effects.
-}
-
-
-TEST(SpecializeJSFunction_ToConstant1) {
- FunctionTester T(
- "(function() { var x = 1; function inc(a)"
- " { return a + x; } return inc; })()");
-
- T.CheckCall(1.0, 0.0, 0.0);
- T.CheckCall(2.0, 1.0, 0.0);
- T.CheckCall(2.1, 1.1, 0.0);
-}
-
-
-TEST(SpecializeJSFunction_ToConstant2) {
- FunctionTester T(
- "(function() { var x = 1.5; var y = 2.25; var z = 3.75;"
- " function f(a) { return a - x + y - z; } return f; })()");
-
- T.CheckCall(-3.0, 0.0, 0.0);
- T.CheckCall(-2.0, 1.0, 0.0);
- T.CheckCall(-1.9, 1.1, 0.0);
-}
-
-
-TEST(SpecializeJSFunction_ToConstant3) {
- FunctionTester T(
- "(function() { var x = -11.5; function inc()"
- " { return (function(a) { return a + x; }); }"
- " return inc(); })()");
-
- T.CheckCall(-11.5, 0.0, 0.0);
- T.CheckCall(-10.5, 1.0, 0.0);
- T.CheckCall(-10.4, 1.1, 0.0);
-}
-
-
-TEST(SpecializeJSFunction_ToConstant_uninit) {
- {
- FunctionTester T(
- "(function() { if (false) { var x = 1; } function inc(a)"
- " { return x; } return inc; })()"); // x is undefined!
-
- CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsUndefined());
- CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsUndefined());
- CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsUndefined());
- }
-
- {
- FunctionTester T(
- "(function() { if (false) { var x = 1; } function inc(a)"
- " { return a + x; } return inc; })()"); // x is undefined!
-
- CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsNaN());
- CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsNaN());
- CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsNaN());
- }
-}
+++ /dev/null
-// 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/graph-inl.h"
-#include "src/compiler/js-typed-lowering.h"
-#include "src/compiler/node-properties-inl.h"
-#include "src/compiler/opcodes.h"
-#include "src/compiler/typer.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-class JSTypedLoweringTester : public HandleAndZoneScope {
- public:
- JSTypedLoweringTester()
- : isolate(main_isolate()),
- binop(NULL),
- unop(NULL),
- javascript(main_zone()),
- machine(main_zone()),
- simplified(main_zone()),
- common(main_zone()),
- graph(main_zone()),
- typer(main_zone()),
- source_positions(&graph),
- context_node(NULL) {
- typer.DecorateGraph(&graph);
- }
-
- Isolate* isolate;
- Operator* binop;
- Operator* unop;
- JSOperatorBuilder javascript;
- MachineOperatorBuilder machine;
- SimplifiedOperatorBuilder simplified;
- CommonOperatorBuilder common;
- Graph graph;
- Typer typer;
- SourcePositionTable source_positions;
- Node* context_node;
-
- Node* Parameter(Type* t, int32_t index = 0) {
- Node* n = graph.NewNode(common.Parameter(index));
- NodeProperties::SetBounds(n, Bounds(Type::None(), t));
- return n;
- }
-
- Node* reduce(Node* node) {
- JSGraph jsgraph(&graph, &common, &typer);
- JSTypedLowering reducer(&jsgraph, &source_positions);
- Reduction reduction = reducer.Reduce(node);
- if (reduction.Changed()) return reduction.replacement();
- return node;
- }
-
- Node* start() {
- Node* s = graph.start();
- if (s == NULL) {
- s = graph.NewNode(common.Start());
- graph.SetStart(s);
- }
- return s;
- }
-
- Node* context() {
- if (context_node == NULL) {
- context_node = graph.NewNode(common.Parameter(-1));
- }
- return context_node;
- }
-
- Node* control() { return start(); }
-
- void CheckPureBinop(IrOpcode::Value expected, Node* node) {
- CHECK_EQ(expected, node->opcode());
- CHECK_EQ(2, node->InputCount()); // should not have context, effect, etc.
- }
-
- void CheckPureBinop(Operator* expected, Node* node) {
- CHECK_EQ(expected->opcode(), node->op()->opcode());
- CHECK_EQ(2, node->InputCount()); // should not have context, effect, etc.
- }
-
- Node* ReduceUnop(Operator* op, Type* input_type) {
- return reduce(Unop(op, Parameter(input_type)));
- }
-
- Node* ReduceBinop(Operator* op, Type* left_type, Type* right_type) {
- return reduce(Binop(op, Parameter(left_type, 0), Parameter(right_type, 1)));
- }
-
- Node* Binop(Operator* op, Node* left, Node* right) {
- // JS binops also require context, effect, and control
- return graph.NewNode(op, left, right, context(), start(), control());
- }
-
- Node* Unop(Operator* op, Node* input) {
- // JS unops also require context, effect, and control
- return graph.NewNode(op, input, context(), start(), control());
- }
-
- Node* UseForEffect(Node* node) {
- // TODO(titzer): use EffectPhi after fixing EffectCount
- return graph.NewNode(javascript.ToNumber(), node, context(), node,
- control());
- }
-
- void CheckEffectInput(Node* effect, Node* use) {
- CHECK_EQ(effect, NodeProperties::GetEffectInput(use));
- }
-
- void CheckInt32Constant(int32_t expected, Node* result) {
- CHECK_EQ(IrOpcode::kInt32Constant, result->opcode());
- CHECK_EQ(expected, ValueOf<int32_t>(result->op()));
- }
-
- void CheckNumberConstant(double expected, Node* result) {
- CHECK_EQ(IrOpcode::kNumberConstant, result->opcode());
- CHECK_EQ(expected, ValueOf<double>(result->op()));
- }
-
- void CheckNaN(Node* result) {
- CHECK_EQ(IrOpcode::kNumberConstant, result->opcode());
- double value = ValueOf<double>(result->op());
- CHECK(std::isnan(value));
- }
-
- void CheckTrue(Node* result) {
- CheckHandle(isolate->factory()->true_value(), result);
- }
-
- void CheckFalse(Node* result) {
- CheckHandle(isolate->factory()->false_value(), result);
- }
-
- void CheckHandle(Handle<Object> expected, Node* result) {
- CHECK_EQ(IrOpcode::kHeapConstant, result->opcode());
- Handle<Object> value = ValueOf<Handle<Object> >(result->op());
- CHECK_EQ(*expected, *value);
- }
-};
-
-static Type* kStringTypes[] = {Type::InternalizedString(), Type::OtherString(),
- Type::String()};
-
-
-static Type* kInt32Types[] = {
- Type::UnsignedSmall(), Type::OtherSignedSmall(), Type::OtherUnsigned31(),
- Type::OtherUnsigned32(), Type::OtherSigned32(), Type::SignedSmall(),
- Type::Signed32(), Type::Unsigned32(), Type::Integral32()};
-
-
-static Type* kNumberTypes[] = {
- Type::UnsignedSmall(), Type::OtherSignedSmall(), Type::OtherUnsigned31(),
- Type::OtherUnsigned32(), Type::OtherSigned32(), Type::SignedSmall(),
- Type::Signed32(), Type::Unsigned32(), Type::Integral32(),
- Type::MinusZero(), Type::NaN(), Type::OtherNumber(),
- Type::Number()};
-
-
-static Type* kJSTypes[] = {Type::Undefined(), Type::Null(), Type::Boolean(),
- Type::Number(), Type::String(), Type::Object()};
-
-
-static Type* I32Type(bool is_signed) {
- return is_signed ? Type::Signed32() : Type::Unsigned32();
-}
-
-
-static IrOpcode::Value NumberToI32(bool is_signed) {
- return is_signed ? IrOpcode::kNumberToInt32 : IrOpcode::kNumberToUint32;
-}
-
-
-TEST(StringBinops) {
- JSTypedLoweringTester R;
-
- for (size_t i = 0; i < ARRAY_SIZE(kStringTypes); ++i) {
- Node* p0 = R.Parameter(kStringTypes[i], 0);
-
- for (size_t j = 0; j < ARRAY_SIZE(kStringTypes); ++j) {
- Node* p1 = R.Parameter(kStringTypes[j], 1);
-
- Node* add = R.Binop(R.javascript.Add(), p0, p1);
- Node* r = R.reduce(add);
-
- R.CheckPureBinop(IrOpcode::kStringAdd, r);
- CHECK_EQ(p0, r->InputAt(0));
- CHECK_EQ(p1, r->InputAt(1));
- }
- }
-}
-
-
-TEST(AddNumber1) {
- JSTypedLoweringTester R;
- for (size_t i = 0; i < ARRAY_SIZE(kNumberTypes); ++i) {
- Node* p0 = R.Parameter(kNumberTypes[i], 0);
- Node* p1 = R.Parameter(kNumberTypes[i], 1);
- Node* add = R.Binop(R.javascript.Add(), p0, p1);
- Node* r = R.reduce(add);
-
- R.CheckPureBinop(IrOpcode::kNumberAdd, r);
- CHECK_EQ(p0, r->InputAt(0));
- CHECK_EQ(p1, r->InputAt(1));
- }
-}
-
-
-TEST(NumberBinops) {
- JSTypedLoweringTester R;
- Operator* ops[] = {
- R.javascript.Add(), R.simplified.NumberAdd(),
- R.javascript.Subtract(), R.simplified.NumberSubtract(),
- R.javascript.Multiply(), R.simplified.NumberMultiply(),
- R.javascript.Divide(), R.simplified.NumberDivide(),
- R.javascript.Modulus(), R.simplified.NumberModulus(),
- };
-
- for (size_t i = 0; i < ARRAY_SIZE(kNumberTypes); ++i) {
- Node* p0 = R.Parameter(kNumberTypes[i], 0);
-
- for (size_t j = 0; j < ARRAY_SIZE(kNumberTypes); ++j) {
- Node* p1 = R.Parameter(kNumberTypes[j], 1);
-
- for (size_t k = 0; k < ARRAY_SIZE(ops); k += 2) {
- Node* add = R.Binop(ops[k], p0, p1);
- Node* r = R.reduce(add);
-
- R.CheckPureBinop(ops[k + 1], r);
- CHECK_EQ(p0, r->InputAt(0));
- CHECK_EQ(p1, r->InputAt(1));
- }
- }
- }
-}
-
-
-static void CheckToI32(Node* old_input, Node* new_input, bool is_signed) {
- Type* old_type = NodeProperties::GetBounds(old_input).upper;
- Type* expected_type = I32Type(is_signed);
- if (old_type->Is(expected_type)) {
- CHECK_EQ(old_input, new_input);
- } else if (new_input->opcode() == IrOpcode::kNumberConstant) {
- CHECK(NodeProperties::GetBounds(new_input).upper->Is(expected_type));
- double v = ValueOf<double>(new_input->op());
- double e = static_cast<double>(is_signed ? FastD2I(v) : FastD2UI(v));
- CHECK_EQ(e, v);
- } else {
- CHECK_EQ(NumberToI32(is_signed), new_input->opcode());
- }
-}
-
-
-// A helper class for testing lowering of bitwise shift operators.
-class JSBitwiseShiftTypedLoweringTester : public JSTypedLoweringTester {
- public:
- static const int kNumberOps = 6;
- Operator** ops;
- bool* signedness;
-
- JSBitwiseShiftTypedLoweringTester() {
- Operator* o[] = {javascript.ShiftLeft(), machine.Word32Shl(),
- javascript.ShiftRight(), machine.Word32Sar(),
- javascript.ShiftRightLogical(), machine.Word32Shr()};
-
- ops = static_cast<Operator**>(malloc(sizeof(o)));
- memcpy(ops, o, sizeof(o));
-
- // Expected signedness of left and right conversions above.
- bool s[] = {true, false, true, false, false, false};
-
- signedness = static_cast<bool*>(malloc(sizeof(s)));
- memcpy(signedness, s, sizeof(s));
- }
-};
-
-
-TEST(Int32BitwiseShifts) {
- JSBitwiseShiftTypedLoweringTester R;
-
- Type* types[] = {
- Type::SignedSmall(), Type::UnsignedSmall(), Type::OtherSigned32(),
- Type::Unsigned32(), Type::Signed32(), Type::MinusZero(),
- Type::NaN(), Type::OtherNumber(), Type::Undefined(),
- Type::Null(), Type::Boolean(), Type::Number(),
- Type::String(), Type::Object()};
-
- for (size_t i = 0; i < ARRAY_SIZE(types); ++i) {
- Node* p0 = R.Parameter(types[i], 0);
-
- for (size_t j = 0; j < ARRAY_SIZE(types); ++j) {
- Node* p1 = R.Parameter(types[j], 1);
-
- for (int k = 0; k < R.kNumberOps; k += 2) {
- Node* add = R.Binop(R.ops[k], p0, p1);
- Node* r = R.reduce(add);
-
- R.CheckPureBinop(R.ops[k + 1], r);
- Node* r0 = r->InputAt(0);
- Node* r1 = r->InputAt(1);
-
- CheckToI32(p0, r0, R.signedness[k]);
-
- R.CheckPureBinop(IrOpcode::kWord32And, r1);
- CheckToI32(p1, r1->InputAt(0), R.signedness[k + 1]);
- R.CheckInt32Constant(0x1F, r1->InputAt(1));
- }
- }
- }
-}
-
-
-// A helper class for testing lowering of bitwise operators.
-class JSBitwiseTypedLoweringTester : public JSTypedLoweringTester {
- public:
- static const int kNumberOps = 6;
- Operator** ops;
- bool* signedness;
-
- JSBitwiseTypedLoweringTester() {
- Operator* o[] = {javascript.BitwiseOr(), machine.Word32Or(),
- javascript.BitwiseXor(), machine.Word32Xor(),
- javascript.BitwiseAnd(), machine.Word32And()};
-
- ops = static_cast<Operator**>(malloc(sizeof(o)));
- memcpy(ops, o, sizeof(o));
-
- // Expected signedness of left and right conversions above.
- bool s[] = {true, true, true, true, true, true};
-
- signedness = static_cast<bool*>(malloc(sizeof(s)));
- memcpy(signedness, s, sizeof(s));
- }
-};
-
-
-TEST(Int32BitwiseBinops) {
- JSBitwiseTypedLoweringTester R;
-
- Type* types[] = {
- Type::SignedSmall(), Type::UnsignedSmall(), Type::OtherSigned32(),
- Type::Unsigned32(), Type::Signed32(), Type::MinusZero(),
- Type::NaN(), Type::OtherNumber(), Type::Undefined(),
- Type::Null(), Type::Boolean(), Type::Number(),
- Type::String(), Type::Object()};
-
- for (size_t i = 0; i < ARRAY_SIZE(types); ++i) {
- Node* p0 = R.Parameter(types[i], 0);
-
- for (size_t j = 0; j < ARRAY_SIZE(types); ++j) {
- Node* p1 = R.Parameter(types[j], 1);
-
- for (int k = 0; k < R.kNumberOps; k += 2) {
- Node* add = R.Binop(R.ops[k], p0, p1);
- Node* r = R.reduce(add);
-
- R.CheckPureBinop(R.ops[k + 1], r);
-
- CheckToI32(p0, r->InputAt(0), R.signedness[k]);
- CheckToI32(p1, r->InputAt(1), R.signedness[k + 1]);
- }
- }
- }
-}
-
-
-TEST(JSToNumber1) {
- JSTypedLoweringTester R;
- Operator* ton = R.javascript.ToNumber();
-
- for (size_t i = 0; i < ARRAY_SIZE(kNumberTypes); i++) { // ToNumber(number)
- Node* r = R.ReduceUnop(ton, kNumberTypes[i]);
- CHECK_EQ(IrOpcode::kParameter, r->opcode());
- }
-
- { // ToNumber(undefined)
- Node* r = R.ReduceUnop(ton, Type::Undefined());
- R.CheckNaN(r);
- }
-
- { // ToNumber(null)
- Node* r = R.ReduceUnop(ton, Type::Null());
- R.CheckNumberConstant(0.0, r);
- }
-}
-
-
-TEST(JSToNumber_replacement) {
- JSTypedLoweringTester R;
-
- Type* types[] = {Type::Null(), Type::Undefined(), Type::Number()};
-
- for (size_t i = 0; i < ARRAY_SIZE(types); i++) {
- Node* n = R.Parameter(types[i]);
- Node* c = R.graph.NewNode(R.javascript.ToNumber(), n, R.context(),
- R.start(), R.start());
- Node* effect_use = R.UseForEffect(c);
- Node* add = R.graph.NewNode(R.simplified.ReferenceEqual(Type::Any()), n, c);
-
- R.CheckEffectInput(c, effect_use);
- Node* r = R.reduce(c);
-
- if (types[i]->Is(Type::Number())) {
- CHECK_EQ(n, r);
- } else {
- CHECK_EQ(IrOpcode::kNumberConstant, r->opcode());
- }
-
- CHECK_EQ(n, add->InputAt(0));
- CHECK_EQ(r, add->InputAt(1));
- R.CheckEffectInput(R.start(), effect_use);
- }
-}
-
-
-TEST(JSToNumberOfConstant) {
- JSTypedLoweringTester R;
-
- Operator* ops[] = {R.common.NumberConstant(0), R.common.NumberConstant(-1),
- R.common.NumberConstant(0.1), R.common.Int32Constant(1177),
- R.common.Float64Constant(0.99)};
-
- for (size_t i = 0; i < ARRAY_SIZE(ops); i++) {
- Node* n = R.graph.NewNode(ops[i]);
- Node* convert = R.Unop(R.javascript.ToNumber(), n);
- Node* r = R.reduce(convert);
- // Note that either outcome below is correct. It only depends on whether
- // the types of constants are eagerly computed or only computed by the
- // typing pass.
- if (NodeProperties::GetBounds(n).upper->Is(Type::Number())) {
- // If number constants are eagerly typed, then reduction should
- // remove the ToNumber.
- CHECK_EQ(n, r);
- } else {
- // Otherwise, type-based lowering should only look at the type, and
- // *not* try to constant fold.
- CHECK_EQ(convert, r);
- }
- }
-}
-
-
-TEST(JSToNumberOfNumberOrOtherPrimitive) {
- JSTypedLoweringTester R;
- Type* others[] = {Type::Undefined(), Type::Null(), Type::Boolean(),
- Type::String()};
-
- for (size_t i = 0; i < ARRAY_SIZE(others); i++) {
- Type* t = Type::Union(Type::Number(), others[i], R.main_zone());
- Node* r = R.ReduceUnop(R.javascript.ToNumber(), t);
- CHECK_EQ(IrOpcode::kJSToNumber, r->opcode());
- }
-}
-
-
-TEST(JSToBoolean) {
- JSTypedLoweringTester R;
- Operator* op = R.javascript.ToBoolean();
-
- { // ToBoolean(undefined)
- Node* r = R.ReduceUnop(op, Type::Undefined());
- R.CheckFalse(r);
- }
-
- { // ToBoolean(null)
- Node* r = R.ReduceUnop(op, Type::Null());
- R.CheckFalse(r);
- }
-
- { // ToBoolean(boolean)
- Node* r = R.ReduceUnop(op, Type::Boolean());
- CHECK_EQ(IrOpcode::kParameter, r->opcode());
- }
-
- { // ToBoolean(number)
- Node* r = R.ReduceUnop(op, Type::Number());
- CHECK_EQ(IrOpcode::kBooleanNot, r->opcode());
- Node* i = r->InputAt(0);
- CHECK_EQ(IrOpcode::kNumberEqual, i->opcode());
- // ToBoolean(number) => BooleanNot(NumberEqual(x, #0))
- }
-
- { // ToBoolean(string)
- Node* r = R.ReduceUnop(op, Type::String());
- // TODO(titzer): test will break with better js-typed-lowering
- CHECK_EQ(IrOpcode::kJSToBoolean, r->opcode());
- }
-
- { // ToBoolean(object)
- Node* r = R.ReduceUnop(op, Type::DetectableObject());
- R.CheckTrue(r);
- }
-
- { // ToBoolean(undetectable)
- Node* r = R.ReduceUnop(op, Type::Undetectable());
- R.CheckFalse(r);
- }
-
- { // ToBoolean(object)
- Node* r = R.ReduceUnop(op, Type::Object());
- CHECK_EQ(IrOpcode::kJSToBoolean, r->opcode());
- }
-}
-
-
-TEST(JSToBoolean_replacement) {
- JSTypedLoweringTester R;
-
- Type* types[] = {Type::Null(), Type::Undefined(), Type::Boolean(),
- Type::DetectableObject(), Type::Undetectable()};
-
- for (size_t i = 0; i < ARRAY_SIZE(types); i++) {
- Node* n = R.Parameter(types[i]);
- Node* c = R.graph.NewNode(R.javascript.ToBoolean(), n, R.context(),
- R.start(), R.start());
- Node* effect_use = R.UseForEffect(c);
- Node* add = R.graph.NewNode(R.simplified.ReferenceEqual(Type::Any()), n, c);
-
- R.CheckEffectInput(c, effect_use);
- Node* r = R.reduce(c);
-
- if (types[i]->Is(Type::Boolean())) {
- CHECK_EQ(n, r);
- } else {
- CHECK_EQ(IrOpcode::kHeapConstant, r->opcode());
- }
-
- CHECK_EQ(n, add->InputAt(0));
- CHECK_EQ(r, add->InputAt(1));
- R.CheckEffectInput(R.start(), effect_use);
- }
-}
-
-
-TEST(JSToString1) {
- JSTypedLoweringTester R;
-
- for (size_t i = 0; i < ARRAY_SIZE(kStringTypes); i++) {
- Node* r = R.ReduceUnop(R.javascript.ToString(), kStringTypes[i]);
- CHECK_EQ(IrOpcode::kParameter, r->opcode());
- }
-
- Operator* op = R.javascript.ToString();
-
- { // ToString(undefined) => "undefined"
- Node* r = R.ReduceUnop(op, Type::Undefined());
- R.CheckHandle(R.isolate->factory()->undefined_string(), r);
- }
-
- { // ToString(null) => "null"
- Node* r = R.ReduceUnop(op, Type::Null());
- R.CheckHandle(R.isolate->factory()->null_string(), r);
- }
-
- { // ToString(boolean)
- Node* r = R.ReduceUnop(op, Type::Boolean());
- // TODO(titzer): could be a branch
- CHECK_EQ(IrOpcode::kJSToString, r->opcode());
- }
-
- { // ToString(number)
- Node* r = R.ReduceUnop(op, Type::Number());
- // TODO(titzer): could remove effects
- CHECK_EQ(IrOpcode::kJSToString, r->opcode());
- }
-
- { // ToString(string)
- Node* r = R.ReduceUnop(op, Type::String());
- CHECK_EQ(IrOpcode::kParameter, r->opcode()); // No-op
- }
-
- { // ToString(object)
- Node* r = R.ReduceUnop(op, Type::Object());
- CHECK_EQ(IrOpcode::kJSToString, r->opcode()); // No reduction.
- }
-}
-
-
-TEST(JSToString_replacement) {
- JSTypedLoweringTester R;
-
- Type* types[] = {Type::Null(), Type::Undefined(), Type::String()};
-
- for (size_t i = 0; i < ARRAY_SIZE(types); i++) {
- Node* n = R.Parameter(types[i]);
- Node* c = R.graph.NewNode(R.javascript.ToString(), n, R.context(),
- R.start(), R.start());
- Node* effect_use = R.UseForEffect(c);
- Node* add = R.graph.NewNode(R.simplified.ReferenceEqual(Type::Any()), n, c);
-
- R.CheckEffectInput(c, effect_use);
- Node* r = R.reduce(c);
-
- if (types[i]->Is(Type::String())) {
- CHECK_EQ(n, r);
- } else {
- CHECK_EQ(IrOpcode::kHeapConstant, r->opcode());
- }
-
- CHECK_EQ(n, add->InputAt(0));
- CHECK_EQ(r, add->InputAt(1));
- R.CheckEffectInput(R.start(), effect_use);
- }
-}
-
-
-TEST(StringComparison) {
- JSTypedLoweringTester R;
-
- Operator* ops[] = {
- R.javascript.LessThan(), R.simplified.StringLessThan(),
- R.javascript.LessThanOrEqual(), R.simplified.StringLessThanOrEqual(),
- R.javascript.GreaterThan(), R.simplified.StringLessThan(),
- R.javascript.GreaterThanOrEqual(), R.simplified.StringLessThanOrEqual()};
-
- for (size_t i = 0; i < ARRAY_SIZE(kStringTypes); i++) {
- Node* p0 = R.Parameter(kStringTypes[i], 0);
- for (size_t j = 0; j < ARRAY_SIZE(kStringTypes); j++) {
- Node* p1 = R.Parameter(kStringTypes[j], 1);
-
- for (size_t k = 0; k < ARRAY_SIZE(ops); k += 2) {
- Node* cmp = R.Binop(ops[k], p0, p1);
- Node* r = R.reduce(cmp);
-
- R.CheckPureBinop(ops[k + 1], r);
- if (k >= 4) {
- // GreaterThan and GreaterThanOrEqual commute the inputs
- // and use the LessThan and LessThanOrEqual operators.
- CHECK_EQ(p1, r->InputAt(0));
- CHECK_EQ(p0, r->InputAt(1));
- } else {
- CHECK_EQ(p0, r->InputAt(0));
- CHECK_EQ(p1, r->InputAt(1));
- }
- }
- }
- }
-}
-
-
-static void CheckIsConvertedToNumber(Node* val, Node* converted) {
- if (NodeProperties::GetBounds(val).upper->Is(Type::Number())) {
- CHECK_EQ(val, converted);
- } else {
- if (converted->opcode() == IrOpcode::kNumberConstant) return;
- CHECK_EQ(IrOpcode::kJSToNumber, converted->opcode());
- CHECK_EQ(val, converted->InputAt(0));
- }
-}
-
-
-TEST(NumberComparison) {
- JSTypedLoweringTester R;
-
- Operator* ops[] = {
- R.javascript.LessThan(), R.simplified.NumberLessThan(),
- R.javascript.LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
- R.javascript.GreaterThan(), R.simplified.NumberLessThan(),
- R.javascript.GreaterThanOrEqual(), R.simplified.NumberLessThanOrEqual()};
-
- for (size_t i = 0; i < ARRAY_SIZE(kJSTypes); i++) {
- Type* t0 = kJSTypes[i];
- if (t0->Is(Type::String())) continue; // skip Type::String
- Node* p0 = R.Parameter(t0, 0);
-
- for (size_t j = 0; j < ARRAY_SIZE(kJSTypes); j++) {
- Type* t1 = kJSTypes[j];
- if (t1->Is(Type::String())) continue; // skip Type::String
- Node* p1 = R.Parameter(t1, 1);
-
- for (size_t k = 0; k < ARRAY_SIZE(ops); k += 2) {
- Node* cmp = R.Binop(ops[k], p0, p1);
- Node* r = R.reduce(cmp);
-
- R.CheckPureBinop(ops[k + 1], r);
- if (k >= 4) {
- // GreaterThan and GreaterThanOrEqual commute the inputs
- // and use the LessThan and LessThanOrEqual operators.
- CheckIsConvertedToNumber(p1, r->InputAt(0));
- CheckIsConvertedToNumber(p0, r->InputAt(1));
- } else {
- CheckIsConvertedToNumber(p0, r->InputAt(0));
- CheckIsConvertedToNumber(p1, r->InputAt(1));
- }
- }
- }
- }
-}
-
-
-TEST(MixedComparison1) {
- JSTypedLoweringTester R;
-
- Type* types[] = {Type::Number(), Type::String(),
- Type::Union(Type::Number(), Type::String(), R.main_zone())};
-
- for (size_t i = 0; i < ARRAY_SIZE(types); i++) {
- Node* p0 = R.Parameter(types[i], 0);
-
- for (size_t j = 0; j < ARRAY_SIZE(types); j++) {
- Node* p1 = R.Parameter(types[j], 1);
- {
- Node* cmp = R.Binop(R.javascript.LessThan(), 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);
- }
- } else {
- CHECK_EQ(cmp, r); // No reduction of mixed types.
- }
- }
- }
- }
-}
-
-
-TEST(ObjectComparison) {
- JSTypedLoweringTester R;
-
- Node* p0 = R.Parameter(Type::Object(), 0);
- Node* p1 = R.Parameter(Type::Object(), 1);
-
- Node* cmp = R.Binop(R.javascript.LessThan(), p0, p1);
- Node* effect_use = R.UseForEffect(cmp);
-
- R.CheckEffectInput(R.start(), cmp);
- R.CheckEffectInput(cmp, effect_use);
-
- Node* r = R.reduce(cmp);
-
- R.CheckPureBinop(R.simplified.NumberLessThan(), r);
-
- Node* i0 = r->InputAt(0);
- Node* i1 = r->InputAt(1);
-
- CHECK_NE(p0, i0);
- CHECK_NE(p1, i1);
- CHECK_EQ(IrOpcode::kJSToNumber, i0->opcode());
- CHECK_EQ(IrOpcode::kJSToNumber, i1->opcode());
-
- // Check effect chain is correct.
- R.CheckEffectInput(R.start(), i0);
- R.CheckEffectInput(i0, i1);
- R.CheckEffectInput(i1, effect_use);
-}
-
-
-TEST(UnaryNot) {
- JSTypedLoweringTester R;
- Operator* opnot = R.javascript.UnaryNot();
-
- for (size_t i = 0; i < ARRAY_SIZE(kJSTypes); i++) {
- Node* r = R.ReduceUnop(opnot, kJSTypes[i]);
- // TODO(titzer): test will break if/when js-typed-lowering constant folds.
- CHECK_EQ(IrOpcode::kBooleanNot, r->opcode());
- }
-}
-
-
-TEST(RemoveToNumberEffects) {
- JSTypedLoweringTester R;
-
- Node* effect_use = NULL;
- for (int i = 0; i < 10; i++) {
- Node* p0 = R.Parameter(Type::Number());
- Node* ton = R.Unop(R.javascript.ToNumber(), p0);
- effect_use = NULL;
-
- switch (i) {
- case 0:
- effect_use = R.graph.NewNode(R.javascript.ToNumber(), p0, R.context(),
- ton, R.start());
- break;
- case 1:
- effect_use = R.graph.NewNode(R.javascript.ToNumber(), ton, R.context(),
- ton, R.start());
- break;
- case 2:
- effect_use = R.graph.NewNode(R.common.EffectPhi(1), ton, R.start());
- case 3:
- effect_use = R.graph.NewNode(R.javascript.Add(), ton, ton, R.context(),
- ton, R.start());
- break;
- case 4:
- effect_use = R.graph.NewNode(R.javascript.Add(), p0, p0, R.context(),
- ton, R.start());
- break;
- case 5:
- effect_use = R.graph.NewNode(R.common.Return(), p0, ton, R.start());
- break;
- case 6:
- effect_use = R.graph.NewNode(R.common.Return(), ton, ton, R.start());
- }
-
- R.CheckEffectInput(R.start(), ton);
- if (effect_use != NULL) R.CheckEffectInput(ton, effect_use);
-
- Node* r = R.reduce(ton);
- CHECK_EQ(p0, r);
- CHECK_NE(R.start(), r);
-
- if (effect_use != NULL) {
- R.CheckEffectInput(R.start(), effect_use);
- // Check that value uses of ToNumber() do not go to start().
- for (int i = 0; i < effect_use->op()->InputCount(); i++) {
- CHECK_NE(R.start(), effect_use->InputAt(i));
- }
- }
- }
-
- CHECK_EQ(NULL, effect_use); // should have done all cases above.
-}
-
-
-// Helper class for testing the reduction of a single binop.
-class BinopEffectsTester {
- public:
- explicit BinopEffectsTester(Operator* op, Type* t0, Type* t1)
- : R(),
- p0(R.Parameter(t0, 0)),
- p1(R.Parameter(t1, 1)),
- binop(R.Binop(op, p0, p1)),
- effect_use(R.graph.NewNode(R.common.EffectPhi(1), binop, R.start())) {
- // Effects should be ordered start -> binop -> effect_use
- R.CheckEffectInput(R.start(), binop);
- R.CheckEffectInput(binop, effect_use);
- result = R.reduce(binop);
- }
-
- JSTypedLoweringTester R;
- Node* p0;
- Node* p1;
- Node* binop;
- Node* effect_use;
- Node* result;
-
- void CheckEffectsRemoved() { R.CheckEffectInput(R.start(), effect_use); }
-
- void CheckEffectOrdering(Node* n0) {
- R.CheckEffectInput(R.start(), n0);
- R.CheckEffectInput(n0, effect_use);
- }
-
- void CheckEffectOrdering(Node* n0, Node* n1) {
- R.CheckEffectInput(R.start(), n0);
- R.CheckEffectInput(n0, n1);
- R.CheckEffectInput(n1, effect_use);
- }
-
- Node* CheckConvertedInput(IrOpcode::Value opcode, int which, bool effects) {
- return CheckConverted(opcode, result->InputAt(which), effects);
- }
-
- Node* CheckConverted(IrOpcode::Value opcode, Node* node, bool effects) {
- CHECK_EQ(opcode, node->opcode());
- if (effects) {
- CHECK_LT(0, NodeProperties::GetEffectInputCount(node));
- } else {
- CHECK_EQ(0, NodeProperties::GetEffectInputCount(node));
- }
- return node;
- }
-
- Node* CheckNoOp(int which) {
- CHECK_EQ(which == 0 ? p0 : p1, result->InputAt(which));
- return result->InputAt(which);
- }
-};
-
-
-// Helper function for strict and non-strict equality reductions.
-void CheckEqualityReduction(JSTypedLoweringTester* R, bool strict, Node* l,
- Node* r, IrOpcode::Value expected) {
- for (int j = 0; j < 2; j++) {
- Node* p0 = j == 0 ? l : r;
- Node* p1 = j == 1 ? l : r;
-
- {
- Node* eq = strict ? R->graph.NewNode(R->javascript.StrictEqual(), p0, p1)
- : R->Binop(R->javascript.Equal(), p0, p1);
- Node* r = R->reduce(eq);
- R->CheckPureBinop(expected, r);
- }
-
- {
- Node* ne = strict
- ? R->graph.NewNode(R->javascript.StrictNotEqual(), p0, p1)
- : R->Binop(R->javascript.NotEqual(), p0, p1);
- Node* n = R->reduce(ne);
- CHECK_EQ(IrOpcode::kBooleanNot, n->opcode());
- Node* r = n->InputAt(0);
- R->CheckPureBinop(expected, r);
- }
- }
-}
-
-
-TEST(EqualityForNumbers) {
- JSTypedLoweringTester R;
-
- Type* simple_number_types[] = {Type::UnsignedSmall(), Type::SignedSmall(),
- Type::Signed32(), Type::Unsigned32(),
- Type::Number()};
-
-
- for (size_t i = 0; i < ARRAY_SIZE(simple_number_types); ++i) {
- Node* p0 = R.Parameter(simple_number_types[i], 0);
-
- for (size_t j = 0; j < ARRAY_SIZE(simple_number_types); ++j) {
- Node* p1 = R.Parameter(simple_number_types[j], 1);
-
- CheckEqualityReduction(&R, true, p0, p1, IrOpcode::kNumberEqual);
- CheckEqualityReduction(&R, false, p0, p1, IrOpcode::kNumberEqual);
- }
- }
-}
-
-
-TEST(StrictEqualityForRefEqualTypes) {
- JSTypedLoweringTester R;
-
- Type* types[] = {Type::Undefined(), Type::Null(), Type::Boolean(),
- Type::Object(), Type::Receiver()};
-
- Node* p0 = R.Parameter(Type::Any());
- for (size_t i = 0; i < ARRAY_SIZE(types); i++) {
- Node* p1 = R.Parameter(types[i]);
- CheckEqualityReduction(&R, true, p0, p1, IrOpcode::kReferenceEqual);
- }
- // TODO(titzer): Equal(RefEqualTypes)
-}
-
-
-TEST(StringEquality) {
- JSTypedLoweringTester R;
- Node* p0 = R.Parameter(Type::String());
- Node* p1 = R.Parameter(Type::String());
-
- CheckEqualityReduction(&R, true, p0, p1, IrOpcode::kStringEqual);
- CheckEqualityReduction(&R, false, p0, p1, IrOpcode::kStringEqual);
-}
-
-
-TEST(RemovePureNumberBinopEffects) {
- JSTypedLoweringTester R;
-
- Operator* ops[] = {
- R.javascript.Equal(), R.simplified.NumberEqual(),
- R.javascript.Add(), R.simplified.NumberAdd(),
- R.javascript.Subtract(), R.simplified.NumberSubtract(),
- R.javascript.Multiply(), R.simplified.NumberMultiply(),
- R.javascript.Divide(), R.simplified.NumberDivide(),
- R.javascript.Modulus(), R.simplified.NumberModulus(),
- R.javascript.LessThan(), R.simplified.NumberLessThan(),
- R.javascript.LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
- };
-
- for (size_t j = 0; j < ARRAY_SIZE(ops); j += 2) {
- BinopEffectsTester B(ops[j], Type::Number(), Type::Number());
- CHECK_EQ(ops[j + 1]->opcode(), B.result->op()->opcode());
-
- B.R.CheckPureBinop(B.result->opcode(), B.result);
-
- B.CheckNoOp(0);
- B.CheckNoOp(1);
-
- B.CheckEffectsRemoved();
- }
-}
-
-
-TEST(OrderNumberBinopEffects1) {
- JSTypedLoweringTester R;
-
- Operator* ops[] = {
- R.javascript.Subtract(), R.simplified.NumberSubtract(),
- R.javascript.Multiply(), R.simplified.NumberMultiply(),
- R.javascript.Divide(), R.simplified.NumberDivide(),
- R.javascript.Modulus(), R.simplified.NumberModulus(),
- };
-
- for (size_t j = 0; j < ARRAY_SIZE(ops); j += 2) {
- BinopEffectsTester B(ops[j], Type::Object(), Type::String());
- CHECK_EQ(ops[j + 1]->opcode(), B.result->op()->opcode());
-
- Node* i0 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 0, true);
- Node* i1 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 1, true);
-
- CHECK_EQ(B.p0, i0->InputAt(0));
- CHECK_EQ(B.p1, i1->InputAt(0));
-
- // Effects should be ordered start -> i0 -> i1 -> effect_use
- B.CheckEffectOrdering(i0, i1);
- }
-}
-
-
-TEST(OrderNumberBinopEffects2) {
- JSTypedLoweringTester R;
-
- Operator* ops[] = {
- R.javascript.Add(), R.simplified.NumberAdd(),
- R.javascript.Subtract(), R.simplified.NumberSubtract(),
- R.javascript.Multiply(), R.simplified.NumberMultiply(),
- R.javascript.Divide(), R.simplified.NumberDivide(),
- R.javascript.Modulus(), R.simplified.NumberModulus(),
- };
-
- for (size_t j = 0; j < ARRAY_SIZE(ops); j += 2) {
- BinopEffectsTester B(ops[j], Type::Number(), Type::Object());
-
- Node* i0 = B.CheckNoOp(0);
- Node* i1 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 1, true);
-
- CHECK_EQ(B.p0, i0);
- CHECK_EQ(B.p1, i1->InputAt(0));
-
- // Effects should be ordered start -> i1 -> effect_use
- B.CheckEffectOrdering(i1);
- }
-
- for (size_t j = 0; j < ARRAY_SIZE(ops); j += 2) {
- BinopEffectsTester B(ops[j], Type::Object(), Type::Number());
-
- Node* i0 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 0, true);
- Node* i1 = B.CheckNoOp(1);
-
- CHECK_EQ(B.p0, i0->InputAt(0));
- CHECK_EQ(B.p1, i1);
-
- // Effects should be ordered start -> i0 -> effect_use
- B.CheckEffectOrdering(i0);
- }
-}
-
-
-TEST(OrderCompareEffects) {
- JSTypedLoweringTester R;
-
- Operator* ops[] = {
- R.javascript.GreaterThan(), R.simplified.NumberLessThan(),
- R.javascript.GreaterThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
- };
-
- for (size_t j = 0; j < ARRAY_SIZE(ops); j += 2) {
- BinopEffectsTester B(ops[j], Type::Object(), Type::String());
- CHECK_EQ(ops[j + 1]->opcode(), B.result->op()->opcode());
-
- Node* i0 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 0, true);
- Node* i1 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 1, true);
-
- // Inputs should be commuted.
- CHECK_EQ(B.p1, i0->InputAt(0));
- CHECK_EQ(B.p0, i1->InputAt(0));
-
- // But effects should be ordered start -> i1 -> i0 -> effect_use
- B.CheckEffectOrdering(i1, i0);
- }
-
- for (size_t j = 0; j < ARRAY_SIZE(ops); j += 2) {
- BinopEffectsTester B(ops[j], Type::Number(), Type::Object());
-
- Node* i0 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 0, true);
- Node* i1 = B.result->InputAt(1);
-
- CHECK_EQ(B.p1, i0->InputAt(0)); // Should be commuted.
- CHECK_EQ(B.p0, i1);
-
- // Effects should be ordered start -> i1 -> effect_use
- B.CheckEffectOrdering(i0);
- }
-
- for (size_t j = 0; j < ARRAY_SIZE(ops); j += 2) {
- BinopEffectsTester B(ops[j], Type::Object(), Type::Number());
-
- Node* i0 = B.result->InputAt(0);
- Node* i1 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 1, true);
-
- CHECK_EQ(B.p1, i0); // Should be commuted.
- CHECK_EQ(B.p0, i1->InputAt(0));
-
- // Effects should be ordered start -> i0 -> effect_use
- B.CheckEffectOrdering(i1);
- }
-}
-
-
-TEST(Int32BinopEffects) {
- JSBitwiseTypedLoweringTester R;
-
- for (int j = 0; j < R.kNumberOps; j += 2) {
- bool signed_left = R.signedness[j], signed_right = R.signedness[j + 1];
- BinopEffectsTester B(R.ops[j], I32Type(signed_left), I32Type(signed_right));
- CHECK_EQ(R.ops[j + 1]->opcode(), B.result->op()->opcode());
-
- B.R.CheckPureBinop(B.result->opcode(), B.result);
-
- B.CheckNoOp(0);
- B.CheckNoOp(1);
-
- B.CheckEffectsRemoved();
- }
-
- for (int j = 0; j < R.kNumberOps; j += 2) {
- bool signed_left = R.signedness[j], signed_right = R.signedness[j + 1];
- BinopEffectsTester B(R.ops[j], Type::Number(), Type::Number());
- CHECK_EQ(R.ops[j + 1]->opcode(), B.result->op()->opcode());
-
- B.R.CheckPureBinop(B.result->opcode(), B.result);
-
- B.CheckConvertedInput(NumberToI32(signed_left), 0, false);
- B.CheckConvertedInput(NumberToI32(signed_right), 1, false);
-
- B.CheckEffectsRemoved();
- }
-
- for (int j = 0; j < R.kNumberOps; j += 2) {
- bool signed_left = R.signedness[j], signed_right = R.signedness[j + 1];
- BinopEffectsTester B(R.ops[j], Type::Number(), Type::Object());
-
- B.R.CheckPureBinop(B.result->opcode(), B.result);
-
- Node* i0 = B.CheckConvertedInput(NumberToI32(signed_left), 0, false);
- Node* i1 = B.CheckConvertedInput(NumberToI32(signed_right), 1, false);
-
- CHECK_EQ(B.p0, i0->InputAt(0));
- Node* ii1 = B.CheckConverted(IrOpcode::kJSToNumber, i1->InputAt(0), true);
-
- CHECK_EQ(B.p1, ii1->InputAt(0));
-
- B.CheckEffectOrdering(ii1);
- }
-
- for (int j = 0; j < R.kNumberOps; j += 2) {
- bool signed_left = R.signedness[j], signed_right = R.signedness[j + 1];
- BinopEffectsTester B(R.ops[j], Type::Object(), Type::Number());
-
- B.R.CheckPureBinop(B.result->opcode(), B.result);
-
- Node* i0 = B.CheckConvertedInput(NumberToI32(signed_left), 0, false);
- Node* i1 = B.CheckConvertedInput(NumberToI32(signed_right), 1, false);
-
- Node* ii0 = B.CheckConverted(IrOpcode::kJSToNumber, i0->InputAt(0), true);
- CHECK_EQ(B.p1, i1->InputAt(0));
-
- CHECK_EQ(B.p0, ii0->InputAt(0));
-
- B.CheckEffectOrdering(ii0);
- }
-
- for (int j = 0; j < R.kNumberOps; j += 2) {
- bool signed_left = R.signedness[j], signed_right = R.signedness[j + 1];
- BinopEffectsTester B(R.ops[j], Type::Object(), Type::Object());
-
- B.R.CheckPureBinop(B.result->opcode(), B.result);
-
- Node* i0 = B.CheckConvertedInput(NumberToI32(signed_left), 0, false);
- Node* i1 = B.CheckConvertedInput(NumberToI32(signed_right), 1, false);
-
- Node* ii0 = B.CheckConverted(IrOpcode::kJSToNumber, i0->InputAt(0), true);
- Node* ii1 = B.CheckConverted(IrOpcode::kJSToNumber, i1->InputAt(0), true);
-
- CHECK_EQ(B.p0, ii0->InputAt(0));
- CHECK_EQ(B.p1, ii1->InputAt(0));
-
- B.CheckEffectOrdering(ii0, ii1);
- }
-}
-
-
-TEST(UnaryNotEffects) {
- JSTypedLoweringTester R;
- Operator* opnot = R.javascript.UnaryNot();
-
- for (size_t i = 0; i < ARRAY_SIZE(kJSTypes); i++) {
- Node* p0 = R.Parameter(kJSTypes[i], 0);
- Node* orig = R.Unop(opnot, p0);
- Node* effect_use = R.UseForEffect(orig);
- Node* value_use = R.graph.NewNode(R.common.Return(), orig);
- Node* r = R.reduce(orig);
- // TODO(titzer): test will break if/when js-typed-lowering constant folds.
- CHECK_EQ(IrOpcode::kBooleanNot, r->opcode());
-
- CHECK_EQ(r, value_use->InputAt(0));
-
- if (r->InputAt(0) == orig && orig->opcode() == IrOpcode::kJSToBoolean) {
- // The original node was turned into a ToBoolean, which has an effect.
- R.CheckEffectInput(R.start(), orig);
- R.CheckEffectInput(orig, effect_use);
- } else {
- // effect should have been removed from this node.
- R.CheckEffectInput(R.start(), effect_use);
- }
- }
-}
-
-
-TEST(Int32AddNarrowing) {
- {
- JSBitwiseTypedLoweringTester R;
-
- for (int o = 0; o < R.kNumberOps; o += 2) {
- for (size_t i = 0; i < ARRAY_SIZE(kInt32Types); i++) {
- Node* n0 = R.Parameter(kInt32Types[i]);
- for (size_t j = 0; j < ARRAY_SIZE(kInt32Types); j++) {
- Node* n1 = R.Parameter(kInt32Types[j]);
- Node* one = R.graph.NewNode(R.common.NumberConstant(1));
-
- for (int l = 0; l < 2; l++) {
- Node* add_node = R.Binop(R.simplified.NumberAdd(), n0, n1);
- Node* or_node =
- R.Binop(R.ops[o], l ? add_node : one, l ? one : add_node);
- Node* r = R.reduce(or_node);
-
- CHECK_EQ(R.ops[o + 1]->opcode(), r->op()->opcode());
- CHECK_EQ(IrOpcode::kInt32Add, add_node->opcode());
- bool is_signed = l ? R.signedness[o] : R.signedness[o + 1];
-
- Type* add_type = NodeProperties::GetBounds(add_node).upper;
- CHECK(add_type->Is(I32Type(is_signed)));
- }
- }
- }
- }
- }
- {
- JSBitwiseShiftTypedLoweringTester R;
-
- for (int o = 0; o < R.kNumberOps; o += 2) {
- for (size_t i = 0; i < ARRAY_SIZE(kInt32Types); i++) {
- Node* n0 = R.Parameter(kInt32Types[i]);
- for (size_t j = 0; j < ARRAY_SIZE(kInt32Types); j++) {
- Node* n1 = R.Parameter(kInt32Types[j]);
- Node* one = R.graph.NewNode(R.common.NumberConstant(1));
-
- for (int l = 0; l < 2; l++) {
- Node* add_node = R.Binop(R.simplified.NumberAdd(), n0, n1);
- Node* or_node =
- R.Binop(R.ops[o], l ? add_node : one, l ? one : add_node);
- Node* r = R.reduce(or_node);
-
- CHECK_EQ(R.ops[o + 1]->opcode(), r->op()->opcode());
- CHECK_EQ(IrOpcode::kInt32Add, add_node->opcode());
- bool is_signed = l ? R.signedness[o] : R.signedness[o + 1];
-
- Type* add_type = NodeProperties::GetBounds(add_node).upper;
- CHECK(add_type->Is(I32Type(is_signed)));
- }
- }
- }
- }
- }
-}
-
-
-TEST(Int32AddNarrowingNotOwned) {
- JSBitwiseTypedLoweringTester R;
-
- for (int o = 0; o < R.kNumberOps; o += 2) {
- Node* n0 = R.Parameter(I32Type(R.signedness[o]));
- Node* n1 = R.Parameter(I32Type(R.signedness[o + 1]));
- Node* one = R.graph.NewNode(R.common.NumberConstant(1));
-
- Node* add_node = R.Binop(R.simplified.NumberAdd(), n0, n1);
- Node* or_node = R.Binop(R.ops[o], add_node, one);
- Node* other_use = R.Binop(R.simplified.NumberAdd(), add_node, one);
- Node* r = R.reduce(or_node);
- CHECK_EQ(R.ops[o + 1]->opcode(), r->op()->opcode());
- // Should not be reduced to Int32Add because of the other number add.
- CHECK_EQ(IrOpcode::kNumberAdd, add_node->opcode());
- // Conversion to int32 should be done.
- CheckToI32(add_node, r->InputAt(0), R.signedness[o]);
- CheckToI32(one, r->InputAt(1), R.signedness[o + 1]);
- // The other use should also not be touched.
- CHECK_EQ(add_node, other_use->InputAt(0));
- CHECK_EQ(one, other_use->InputAt(1));
- }
-}
-
-
-TEST(Int32Comparisons) {
- JSTypedLoweringTester R;
-
- struct Entry {
- Operator* js_op;
- Operator* uint_op;
- Operator* int_op;
- Operator* num_op;
- bool commute;
- };
-
- Entry ops[] = {
- {R.javascript.LessThan(), R.machine.Uint32LessThan(),
- R.machine.Int32LessThan(), R.simplified.NumberLessThan(), false},
- {R.javascript.LessThanOrEqual(), R.machine.Uint32LessThanOrEqual(),
- R.machine.Int32LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
- false},
- {R.javascript.GreaterThan(), R.machine.Uint32LessThan(),
- R.machine.Int32LessThan(), R.simplified.NumberLessThan(), true},
- {R.javascript.GreaterThanOrEqual(), R.machine.Uint32LessThanOrEqual(),
- R.machine.Int32LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
- true}};
-
- for (size_t o = 0; o < ARRAY_SIZE(ops); o++) {
- for (size_t i = 0; i < ARRAY_SIZE(kNumberTypes); i++) {
- Type* t0 = kNumberTypes[i];
- Node* p0 = R.Parameter(t0, 0);
-
- for (size_t j = 0; j < ARRAY_SIZE(kNumberTypes); j++) {
- Type* t1 = kNumberTypes[j];
- Node* p1 = R.Parameter(t1, 1);
-
- Node* cmp = R.Binop(ops[o].js_op, p0, p1);
- Node* r = R.reduce(cmp);
-
- Operator* expected;
- if (t0->Is(Type::Unsigned32()) && t1->Is(Type::Unsigned32())) {
- expected = ops[o].uint_op;
- } else if (t0->Is(Type::Signed32()) && t1->Is(Type::Signed32())) {
- expected = ops[o].int_op;
- } else {
- expected = ops[o].num_op;
- }
- R.CheckPureBinop(expected, r);
- if (ops[o].commute) {
- CHECK_EQ(p1, r->InputAt(0));
- CHECK_EQ(p0, r->InputAt(1));
- } else {
- CHECK_EQ(p0, r->InputAt(0));
- CHECK_EQ(p1, r->InputAt(1));
- }
- }
- }
- }
-}
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-
-#include "src/compiler.h"
-#include "src/zone.h"
-
-#include "src/compiler/common-operator.h"
-#include "src/compiler/generic-node-inl.h"
-#include "src/compiler/graph.h"
-#include "src/compiler/linkage.h"
-#include "src/compiler/machine-operator.h"
-#include "src/compiler/node.h"
-#include "src/compiler/operator.h"
-#include "src/compiler/pipeline.h"
-#include "src/compiler/schedule.h"
-#include "test/cctest/cctest.h"
-
-#if V8_TURBOFAN_TARGET
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-static SimpleOperator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
- 0, 0, "dummy");
-
-// So we can get a real JS function.
-static Handle<JSFunction> Compile(const char* source) {
- Isolate* isolate = CcTest::i_isolate();
- Handle<String> source_code = isolate->factory()
- ->NewStringFromUtf8(CStrVector(source))
- .ToHandleChecked();
- Handle<SharedFunctionInfo> shared_function = Compiler::CompileScript(
- source_code, Handle<String>(), 0, 0, false,
- Handle<Context>(isolate->native_context()), NULL, NULL,
- v8::ScriptCompiler::kNoCompileOptions, NOT_NATIVES_CODE);
- return isolate->factory()->NewFunctionFromSharedFunctionInfo(
- shared_function, isolate->native_context());
-}
-
-
-TEST(TestLinkageCreate) {
- InitializedHandleScope handles;
- Handle<JSFunction> function = Compile("a + b");
- CompilationInfoWithZone info(function);
- Linkage linkage(&info);
-}
-
-
-TEST(TestLinkageJSFunctionIncoming) {
- InitializedHandleScope handles;
-
- const char* sources[] = {"(function() { })", "(function(a) { })",
- "(function(a,b) { })", "(function(a,b,c) { })"};
-
- for (int i = 0; i < 3; i++) {
- i::HandleScope handles(CcTest::i_isolate());
- Handle<JSFunction> function = v8::Utils::OpenHandle(
- *v8::Handle<v8::Function>::Cast(CompileRun(sources[i])));
- CompilationInfoWithZone info(function);
- Linkage linkage(&info);
-
- CallDescriptor* descriptor = linkage.GetIncomingDescriptor();
- CHECK_NE(NULL, descriptor);
-
- CHECK_EQ(1 + i, descriptor->ParameterCount());
- CHECK_EQ(1, descriptor->ReturnCount());
- CHECK_EQ(Operator::kNoProperties, descriptor->properties());
- CHECK_EQ(true, descriptor->IsJSFunctionCall());
- }
-}
-
-
-TEST(TestLinkageCodeStubIncoming) {
- Isolate* isolate = CcTest::InitIsolateOnce();
- CompilationInfoWithZone info(static_cast<HydrogenCodeStub*>(NULL), isolate);
- Linkage linkage(&info);
- // TODO(titzer): test linkage creation with a bonafide code stub.
- // this just checks current behavior.
- CHECK_EQ(NULL, linkage.GetIncomingDescriptor());
-}
-
-
-TEST(TestLinkageJSCall) {
- HandleAndZoneScope handles;
- Handle<JSFunction> function = Compile("a + c");
- CompilationInfoWithZone info(function);
- Linkage linkage(&info);
-
- for (int i = 0; i < 32; i++) {
- CallDescriptor* descriptor = linkage.GetJSCallDescriptor(i);
- CHECK_NE(NULL, descriptor);
- CHECK_EQ(i, descriptor->ParameterCount());
- CHECK_EQ(1, descriptor->ReturnCount());
- CHECK_EQ(Operator::kNoProperties, descriptor->properties());
- CHECK_EQ(true, descriptor->IsJSFunctionCall());
- }
-}
-
-
-TEST(TestLinkageRuntimeCall) {
- // TODO(titzer): test linkage creation for outgoing runtime calls.
-}
-
-
-TEST(TestLinkageStubCall) {
- // TODO(titzer): test linkage creation for outgoing stub calls.
-}
-
-
-#endif // V8_TURBOFAN_TARGET
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "test/cctest/cctest.h"
-
-#include "src/base/utils/random-number-generator.h"
-#include "src/compiler/graph-inl.h"
-#include "src/compiler/machine-operator-reducer.h"
-#include "test/cctest/compiler/value-helper.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-template <typename T>
-Operator* NewConstantOperator(CommonOperatorBuilder* common, volatile T value);
-
-template <>
-Operator* NewConstantOperator<int32_t>(CommonOperatorBuilder* common,
- volatile int32_t value) {
- return common->Int32Constant(value);
-}
-
-template <>
-Operator* NewConstantOperator<double>(CommonOperatorBuilder* common,
- volatile double value) {
- return common->Float64Constant(value);
-}
-
-
-class ReducerTester : public HandleAndZoneScope {
- public:
- ReducerTester()
- : isolate(main_isolate()),
- binop(NULL),
- unop(NULL),
- machine(main_zone()),
- common(main_zone()),
- graph(main_zone()),
- maxuint32(Constant<int32_t>(kMaxUInt32)) {}
-
- Isolate* isolate;
- Operator* binop;
- Operator* unop;
- MachineOperatorBuilder machine;
- CommonOperatorBuilder common;
- Graph graph;
- Node* maxuint32;
-
- template <typename T>
- Node* Constant(volatile T value) {
- return graph.NewNode(NewConstantOperator<T>(&common, value));
- }
-
- // Check that the reduction of this binop applied to constants {a} and {b}
- // yields the {expect} value.
- template <typename T>
- void CheckFoldBinop(volatile T expect, volatile T a, volatile T b) {
- CheckFoldBinop<T>(expect, Constant<T>(a), Constant<T>(b));
- }
-
- // Check that the reduction of this binop applied to {a} and {b} yields
- // the {expect} value.
- template <typename T>
- void CheckFoldBinop(volatile T expect, Node* a, Node* b) {
- CHECK_NE(NULL, binop);
- Node* n = graph.NewNode(binop, a, b);
- MachineOperatorReducer reducer(&graph);
- Reduction reduction = reducer.Reduce(n);
- CHECK(reduction.Changed());
- CHECK_NE(n, reduction.replacement());
- CHECK_EQ(expect, ValueOf<T>(reduction.replacement()->op()));
- }
-
- // Check that the reduction of this binop applied to {a} and {b} yields
- // the {expect} node.
- void CheckBinop(Node* expect, Node* a, Node* b) {
- CHECK_NE(NULL, binop);
- Node* n = graph.NewNode(binop, a, b);
- MachineOperatorReducer reducer(&graph);
- Reduction reduction = reducer.Reduce(n);
- CHECK(reduction.Changed());
- CHECK_EQ(expect, reduction.replacement());
- }
-
- // Check that the reduction of this binop applied to {left} and {right} yields
- // this binop applied to {left_expect} and {right_expect}.
- void CheckFoldBinop(Node* left_expect, Node* right_expect, Node* left,
- Node* right) {
- CHECK_NE(NULL, binop);
- Node* n = graph.NewNode(binop, left, right);
- MachineOperatorReducer reducer(&graph);
- Reduction reduction = reducer.Reduce(n);
- CHECK(reduction.Changed());
- CHECK_EQ(binop, reduction.replacement()->op());
- CHECK_EQ(left_expect, reduction.replacement()->InputAt(0));
- CHECK_EQ(right_expect, reduction.replacement()->InputAt(1));
- }
-
- // Check that the reduction of this binop applied to {left} and {right} yields
- // the {op_expect} applied to {left_expect} and {right_expect}.
- template <typename T>
- void CheckFoldBinop(volatile T left_expect, Operator* op_expect,
- Node* right_expect, Node* left, Node* right) {
- CHECK_NE(NULL, binop);
- Node* n = graph.NewNode(binop, left, right);
- MachineOperatorReducer reducer(&graph);
- Reduction r = reducer.Reduce(n);
- CHECK(r.Changed());
- CHECK_EQ(op_expect->opcode(), r.replacement()->op()->opcode());
- CHECK_EQ(left_expect, ValueOf<T>(r.replacement()->InputAt(0)->op()));
- CHECK_EQ(right_expect, r.replacement()->InputAt(1));
- }
-
- // Check that the reduction of this binop applied to {left} and {right} yields
- // the {op_expect} applied to {left_expect} and {right_expect}.
- template <typename T>
- void CheckFoldBinop(Node* left_expect, Operator* op_expect,
- volatile T right_expect, Node* left, Node* right) {
- CHECK_NE(NULL, binop);
- Node* n = graph.NewNode(binop, left, right);
- MachineOperatorReducer reducer(&graph);
- Reduction r = reducer.Reduce(n);
- CHECK(r.Changed());
- CHECK_EQ(op_expect->opcode(), r.replacement()->op()->opcode());
- CHECK_EQ(left_expect, r.replacement()->InputAt(0));
- CHECK_EQ(right_expect, ValueOf<T>(r.replacement()->InputAt(1)->op()));
- }
-
- // Check that if the given constant appears on the left, the reducer will
- // swap it to be on the right.
- template <typename T>
- void CheckPutConstantOnRight(volatile T constant) {
- // TODO(titzer): CHECK(binop->HasProperty(Operator::kCommutative));
- Node* p = Parameter();
- Node* k = Constant<T>(constant);
- {
- Node* n = graph.NewNode(binop, k, p);
- MachineOperatorReducer reducer(&graph);
- Reduction reduction = reducer.Reduce(n);
- CHECK(!reduction.Changed() || reduction.replacement() == n);
- CHECK_EQ(p, n->InputAt(0));
- CHECK_EQ(k, n->InputAt(1));
- }
- {
- Node* n = graph.NewNode(binop, p, k);
- MachineOperatorReducer reducer(&graph);
- Reduction reduction = reducer.Reduce(n);
- CHECK(!reduction.Changed());
- CHECK_EQ(p, n->InputAt(0));
- CHECK_EQ(k, n->InputAt(1));
- }
- }
-
- // Check that if the given constant appears on the left, the reducer will
- // *NOT* swap it to be on the right.
- template <typename T>
- void CheckDontPutConstantOnRight(volatile T constant) {
- CHECK(!binop->HasProperty(Operator::kCommutative));
- Node* p = Parameter();
- Node* k = Constant<T>(constant);
- Node* n = graph.NewNode(binop, k, p);
- MachineOperatorReducer reducer(&graph);
- Reduction reduction = reducer.Reduce(n);
- CHECK(!reduction.Changed());
- CHECK_EQ(k, n->InputAt(0));
- CHECK_EQ(p, n->InputAt(1));
- }
-
- Node* Parameter(int32_t index = 0) {
- return graph.NewNode(common.Parameter(index));
- }
-};
-
-
-TEST(ReduceWord32And) {
- ReducerTester R;
- R.binop = R.machine.Word32And();
-
- FOR_INT32_INPUTS(pl) {
- FOR_INT32_INPUTS(pr) {
- int32_t x = *pl, y = *pr;
- R.CheckFoldBinop<int32_t>(x & y, x, y);
- }
- }
-
- R.CheckPutConstantOnRight(33);
- R.CheckPutConstantOnRight(44000);
-
- Node* x = R.Parameter();
- Node* zero = R.Constant<int32_t>(0);
- Node* minus_1 = R.Constant<int32_t>(-1);
-
- R.CheckBinop(zero, x, zero); // x & 0 => 0
- R.CheckBinop(zero, zero, x); // 0 & x => 0
- R.CheckBinop(x, x, minus_1); // x & -1 => 0
- R.CheckBinop(x, minus_1, x); // -1 & x => 0
- R.CheckBinop(x, x, x); // x & x => x
-}
-
-
-TEST(ReduceWord32Or) {
- ReducerTester R;
- R.binop = R.machine.Word32Or();
-
- FOR_INT32_INPUTS(pl) {
- FOR_INT32_INPUTS(pr) {
- int32_t x = *pl, y = *pr;
- R.CheckFoldBinop<int32_t>(x | y, x, y);
- }
- }
-
- R.CheckPutConstantOnRight(36);
- R.CheckPutConstantOnRight(44001);
-
- Node* x = R.Parameter();
- Node* zero = R.Constant<int32_t>(0);
- Node* minus_1 = R.Constant<int32_t>(-1);
-
- R.CheckBinop(x, x, zero); // x & 0 => x
- R.CheckBinop(x, zero, x); // 0 & x => x
- R.CheckBinop(minus_1, x, minus_1); // x & -1 => -1
- R.CheckBinop(minus_1, minus_1, x); // -1 & x => -1
- R.CheckBinop(x, x, x); // x & x => x
-}
-
-
-TEST(ReduceWord32Xor) {
- ReducerTester R;
- R.binop = R.machine.Word32Xor();
-
- FOR_INT32_INPUTS(pl) {
- FOR_INT32_INPUTS(pr) {
- int32_t x = *pl, y = *pr;
- R.CheckFoldBinop<int32_t>(x ^ y, x, y);
- }
- }
-
- R.CheckPutConstantOnRight(39);
- R.CheckPutConstantOnRight(4403);
-
- Node* x = R.Parameter();
- Node* zero = R.Constant<int32_t>(0);
-
- R.CheckBinop(x, x, zero); // x ^ 0 => x
- R.CheckBinop(x, zero, x); // 0 ^ x => x
- R.CheckFoldBinop<int32_t>(0, x, x); // x ^ x => 0
-}
-
-
-TEST(ReduceWord32Shl) {
- ReducerTester R;
- R.binop = R.machine.Word32Shl();
-
- // TODO(titzer): out of range shifts
- FOR_INT32_INPUTS(i) {
- for (int y = 0; y < 32; y++) {
- int32_t x = *i;
- R.CheckFoldBinop<int32_t>(x << y, x, y);
- }
- }
-
- R.CheckDontPutConstantOnRight(44);
-
- Node* x = R.Parameter();
- Node* zero = R.Constant<int32_t>(0);
-
- R.CheckBinop(x, x, zero); // x << 0 => x
-}
-
-
-TEST(ReduceWord32Shr) {
- ReducerTester R;
- R.binop = R.machine.Word32Shr();
-
- // TODO(titzer): test out of range shifts
- FOR_UINT32_INPUTS(i) {
- for (uint32_t y = 0; y < 32; y++) {
- uint32_t x = *i;
- R.CheckFoldBinop<int32_t>(x >> y, x, y);
- }
- }
-
- R.CheckDontPutConstantOnRight(44);
-
- Node* x = R.Parameter();
- Node* zero = R.Constant<int32_t>(0);
-
- R.CheckBinop(x, x, zero); // x >>> 0 => x
-}
-
-
-TEST(ReduceWord32Sar) {
- ReducerTester R;
- R.binop = R.machine.Word32Sar();
-
- // TODO(titzer): test out of range shifts
- FOR_INT32_INPUTS(i) {
- for (int32_t y = 0; y < 32; y++) {
- int32_t x = *i;
- R.CheckFoldBinop<int32_t>(x >> y, x, y);
- }
- }
-
- R.CheckDontPutConstantOnRight(44);
-
- Node* x = R.Parameter();
- Node* zero = R.Constant<int32_t>(0);
-
- R.CheckBinop(x, x, zero); // x >> 0 => x
-}
-
-
-TEST(ReduceWord32Equal) {
- ReducerTester R;
- R.binop = R.machine.Word32Equal();
-
- FOR_INT32_INPUTS(pl) {
- FOR_INT32_INPUTS(pr) {
- int32_t x = *pl, y = *pr;
- R.CheckFoldBinop<int32_t>(x == y ? 1 : 0, x, y);
- }
- }
-
- R.CheckPutConstantOnRight(48);
- R.CheckPutConstantOnRight(-48);
-
- Node* x = R.Parameter(0);
- Node* y = R.Parameter(1);
- Node* zero = R.Constant<int32_t>(0);
- Node* sub = R.graph.NewNode(R.machine.Int32Sub(), x, y);
-
- R.CheckFoldBinop<int32_t>(1, x, x); // x == x => 1
- R.CheckFoldBinop(x, y, sub, zero); // x - y == 0 => x == y
- R.CheckFoldBinop(x, y, zero, sub); // 0 == x - y => x == y
-}
-
-
-TEST(ReduceInt32Add) {
- ReducerTester R;
- R.binop = R.machine.Int32Add();
-
- FOR_INT32_INPUTS(pl) {
- FOR_INT32_INPUTS(pr) {
- int32_t x = *pl, y = *pr;
- R.CheckFoldBinop<int32_t>(x + y, x, y); // TODO(titzer): signed overflow
- }
- }
-
- R.CheckPutConstantOnRight(41);
- R.CheckPutConstantOnRight(4407);
-
- Node* x = R.Parameter();
- Node* zero = R.Constant<int32_t>(0);
-
- R.CheckBinop(x, x, zero); // x + 0 => x
- R.CheckBinop(x, zero, x); // 0 + x => x
-}
-
-
-TEST(ReduceInt32Sub) {
- ReducerTester R;
- R.binop = R.machine.Int32Sub();
-
- FOR_INT32_INPUTS(pl) {
- FOR_INT32_INPUTS(pr) {
- int32_t x = *pl, y = *pr;
- R.CheckFoldBinop<int32_t>(x - y, x, y);
- }
- }
-
- R.CheckDontPutConstantOnRight(412);
-
- Node* x = R.Parameter();
- Node* zero = R.Constant<int32_t>(0);
-
- R.CheckBinop(x, x, zero); // x - 0 => x
-}
-
-
-TEST(ReduceInt32Mul) {
- ReducerTester R;
- R.binop = R.machine.Int32Mul();
-
- FOR_INT32_INPUTS(pl) {
- FOR_INT32_INPUTS(pr) {
- int32_t x = *pl, y = *pr;
- R.CheckFoldBinop<int32_t>(x * y, x, y); // TODO(titzer): signed overflow
- }
- }
-
- R.CheckPutConstantOnRight(4111);
- R.CheckPutConstantOnRight(-4407);
-
- Node* x = R.Parameter();
- Node* zero = R.Constant<int32_t>(0);
- Node* one = R.Constant<int32_t>(1);
- Node* minus_one = R.Constant<int32_t>(-1);
-
- R.CheckBinop(zero, x, zero); // x * 0 => 0
- R.CheckBinop(zero, zero, x); // 0 * x => 0
- R.CheckBinop(x, x, one); // x * 1 => x
- R.CheckBinop(x, one, x); // 1 * x => x
- R.CheckFoldBinop<int32_t>(0, R.machine.Int32Sub(), x, minus_one,
- x); // -1 * x => 0 - x
- R.CheckFoldBinop<int32_t>(0, R.machine.Int32Sub(), x, x,
- minus_one); // x * -1 => 0 - x
-
- for (int32_t n = 1; n < 31; ++n) {
- Node* multiplier = R.Constant<int32_t>(1 << n);
- R.CheckFoldBinop<int32_t>(x, R.machine.Word32Shl(), n, x,
- multiplier); // x * 2^n => x << n
- R.CheckFoldBinop<int32_t>(x, R.machine.Word32Shl(), n, multiplier,
- x); // 2^n * x => x << n
- }
-}
-
-
-TEST(ReduceInt32Div) {
- ReducerTester R;
- R.binop = R.machine.Int32Div();
-
- FOR_INT32_INPUTS(pl) {
- FOR_INT32_INPUTS(pr) {
- int32_t x = *pl, y = *pr;
- if (y == 0) continue; // TODO(titzer): test / 0
- int32_t r = y == -1 ? -x : x / y; // INT_MIN / -1 may explode in C
- R.CheckFoldBinop<int32_t>(r, x, y);
- }
- }
-
- R.CheckDontPutConstantOnRight(41111);
- R.CheckDontPutConstantOnRight(-44071);
-
- Node* x = R.Parameter();
- Node* one = R.Constant<int32_t>(1);
- Node* minus_one = R.Constant<int32_t>(-1);
-
- R.CheckBinop(x, x, one); // x / 1 => x
- // TODO(titzer): // 0 / x => 0 if x != 0
- // TODO(titzer): // x / 2^n => x >> n and round
- R.CheckFoldBinop<int32_t>(0, R.machine.Int32Sub(), x, x,
- minus_one); // x / -1 => 0 - x
-}
-
-
-TEST(ReduceInt32UDiv) {
- ReducerTester R;
- R.binop = R.machine.Int32UDiv();
-
- FOR_UINT32_INPUTS(pl) {
- FOR_UINT32_INPUTS(pr) {
- uint32_t x = *pl, y = *pr;
- if (y == 0) continue; // TODO(titzer): test / 0
- R.CheckFoldBinop<int32_t>(x / y, x, y);
- }
- }
-
- R.CheckDontPutConstantOnRight(41311);
- R.CheckDontPutConstantOnRight(-44371);
-
- Node* x = R.Parameter();
- Node* one = R.Constant<int32_t>(1);
-
- R.CheckBinop(x, x, one); // x / 1 => x
- // TODO(titzer): // 0 / x => 0 if x != 0
-
- for (uint32_t n = 1; n < 32; ++n) {
- Node* divisor = R.Constant<int32_t>(1u << n);
- R.CheckFoldBinop<int32_t>(x, R.machine.Word32Shr(), n, x,
- divisor); // x / 2^n => x >> n
- }
-}
-
-
-TEST(ReduceInt32Mod) {
- ReducerTester R;
- R.binop = R.machine.Int32Mod();
-
- FOR_INT32_INPUTS(pl) {
- FOR_INT32_INPUTS(pr) {
- int32_t x = *pl, y = *pr;
- if (y == 0) continue; // TODO(titzer): test % 0
- int32_t r = y == -1 ? 0 : x % y; // INT_MIN % -1 may explode in C
- R.CheckFoldBinop<int32_t>(r, x, y);
- }
- }
-
- R.CheckDontPutConstantOnRight(413);
- R.CheckDontPutConstantOnRight(-4401);
-
- Node* x = R.Parameter();
- Node* one = R.Constant<int32_t>(1);
-
- R.CheckFoldBinop<int32_t>(0, x, one); // x % 1 => 0
- // TODO(titzer): // x % 2^n => x & 2^n-1 and round
-}
-
-
-TEST(ReduceInt32UMod) {
- ReducerTester R;
- R.binop = R.machine.Int32UMod();
-
- FOR_INT32_INPUTS(pl) {
- FOR_INT32_INPUTS(pr) {
- uint32_t x = *pl, y = *pr;
- if (y == 0) continue; // TODO(titzer): test x % 0
- R.CheckFoldBinop<int32_t>(x % y, x, y);
- }
- }
-
- R.CheckDontPutConstantOnRight(417);
- R.CheckDontPutConstantOnRight(-4371);
-
- Node* x = R.Parameter();
- Node* one = R.Constant<int32_t>(1);
-
- R.CheckFoldBinop<int32_t>(0, x, one); // x % 1 => 0
-
- for (uint32_t n = 1; n < 32; ++n) {
- Node* divisor = R.Constant<int32_t>(1u << n);
- R.CheckFoldBinop<int32_t>(x, R.machine.Word32And(), (1u << n) - 1, x,
- divisor); // x % 2^n => x & 2^n-1
- }
-}
-
-
-TEST(ReduceInt32LessThan) {
- ReducerTester R;
- R.binop = R.machine.Int32LessThan();
-
- FOR_INT32_INPUTS(pl) {
- FOR_INT32_INPUTS(pr) {
- int32_t x = *pl, y = *pr;
- R.CheckFoldBinop<int32_t>(x < y ? 1 : 0, x, y);
- }
- }
-
- R.CheckDontPutConstantOnRight(41399);
- R.CheckDontPutConstantOnRight(-440197);
-
- Node* x = R.Parameter(0);
- Node* y = R.Parameter(1);
- Node* zero = R.Constant<int32_t>(0);
- Node* sub = R.graph.NewNode(R.machine.Int32Sub(), x, y);
-
- R.CheckFoldBinop<int32_t>(0, x, x); // x < x => 0
- R.CheckFoldBinop(x, y, sub, zero); // x - y < 0 => x < y
- R.CheckFoldBinop(y, x, zero, sub); // 0 < x - y => y < x
-}
-
-
-TEST(ReduceInt32LessThanOrEqual) {
- ReducerTester R;
- R.binop = R.machine.Int32LessThanOrEqual();
-
- FOR_INT32_INPUTS(pl) {
- FOR_INT32_INPUTS(pr) {
- int32_t x = *pl, y = *pr;
- R.CheckFoldBinop<int32_t>(x <= y ? 1 : 0, x, y);
- }
- }
-
- FOR_INT32_INPUTS(i) { R.CheckDontPutConstantOnRight<int32_t>(*i); }
-
- Node* x = R.Parameter(0);
- Node* y = R.Parameter(1);
- Node* zero = R.Constant<int32_t>(0);
- Node* sub = R.graph.NewNode(R.machine.Int32Sub(), x, y);
-
- R.CheckFoldBinop<int32_t>(1, x, x); // x <= x => 1
- R.CheckFoldBinop(x, y, sub, zero); // x - y <= 0 => x <= y
- R.CheckFoldBinop(y, x, zero, sub); // 0 <= x - y => y <= x
-}
-
-
-TEST(ReduceUint32LessThan) {
- ReducerTester R;
- R.binop = R.machine.Uint32LessThan();
-
- FOR_UINT32_INPUTS(pl) {
- FOR_UINT32_INPUTS(pr) {
- uint32_t x = *pl, y = *pr;
- R.CheckFoldBinop<int32_t>(x < y ? 1 : 0, x, y);
- }
- }
-
- R.CheckDontPutConstantOnRight(41399);
- R.CheckDontPutConstantOnRight(-440197);
-
- Node* x = R.Parameter();
- Node* max = R.maxuint32;
- Node* zero = R.Constant<int32_t>(0);
-
- R.CheckFoldBinop<int32_t>(0, max, x); // M < x => 0
- R.CheckFoldBinop<int32_t>(0, x, zero); // x < 0 => 0
- R.CheckFoldBinop<int32_t>(0, x, x); // x < x => 0
-}
-
-
-TEST(ReduceUint32LessThanOrEqual) {
- ReducerTester R;
- R.binop = R.machine.Uint32LessThanOrEqual();
-
- FOR_UINT32_INPUTS(pl) {
- FOR_UINT32_INPUTS(pr) {
- uint32_t x = *pl, y = *pr;
- R.CheckFoldBinop<int32_t>(x <= y ? 1 : 0, x, y);
- }
- }
-
- R.CheckDontPutConstantOnRight(41399);
- R.CheckDontPutConstantOnRight(-440197);
-
- Node* x = R.Parameter();
- Node* max = R.maxuint32;
- Node* zero = R.Constant<int32_t>(0);
-
- R.CheckFoldBinop<int32_t>(1, x, max); // x <= M => 1
- R.CheckFoldBinop<int32_t>(1, zero, x); // 0 <= x => 1
- R.CheckFoldBinop<int32_t>(1, x, x); // x <= x => 1
-}
-
-
-TEST(ReduceLoadStore) {
- ReducerTester R;
-
- Node* base = R.Constant<int32_t>(11);
- Node* index = R.Constant<int32_t>(4);
- Node* load = R.graph.NewNode(R.machine.Load(kMachineWord32), base, index);
-
- {
- MachineOperatorReducer reducer(&R.graph);
- Reduction reduction = reducer.Reduce(load);
- CHECK(!reduction.Changed()); // loads should not be reduced.
- }
-
- {
- Node* store =
- R.graph.NewNode(R.machine.Store(kMachineWord32), base, index, load);
- MachineOperatorReducer reducer(&R.graph);
- Reduction reduction = reducer.Reduce(store);
- CHECK(!reduction.Changed()); // stores should not be reduced.
- }
-}
-
-
-static void CheckNans(ReducerTester* R) {
- Node* x = R->Parameter();
- std::vector<double> nans = ValueHelper::nan_vector();
- for (std::vector<double>::const_iterator pl = nans.begin(); pl != nans.end();
- ++pl) {
- for (std::vector<double>::const_iterator pr = nans.begin();
- pr != nans.end(); ++pr) {
- Node* nan1 = R->Constant<double>(*pl);
- Node* nan2 = R->Constant<double>(*pr);
- R->CheckBinop(nan1, x, nan1); // x % NaN => NaN
- R->CheckBinop(nan1, nan1, x); // NaN % x => NaN
- R->CheckBinop(nan1, nan2, nan1); // NaN % NaN => NaN
- }
- }
-}
-
-
-TEST(ReduceFloat64Add) {
- ReducerTester R;
- R.binop = R.machine.Float64Add();
-
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- double x = *pl, y = *pr;
- R.CheckFoldBinop<double>(x + y, x, y);
- }
- }
-
- FOR_FLOAT64_INPUTS(i) { R.CheckPutConstantOnRight(*i); }
- // TODO(titzer): CheckNans(&R);
-}
-
-
-TEST(ReduceFloat64Sub) {
- ReducerTester R;
- R.binop = R.machine.Float64Sub();
-
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- double x = *pl, y = *pr;
- R.CheckFoldBinop<double>(x - y, x, y);
- }
- }
- // TODO(titzer): CheckNans(&R);
-}
-
-
-TEST(ReduceFloat64Mul) {
- ReducerTester R;
- R.binop = R.machine.Float64Mul();
-
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- double x = *pl, y = *pr;
- R.CheckFoldBinop<double>(x * y, x, y);
- }
- }
-
- double inf = V8_INFINITY;
- R.CheckPutConstantOnRight(-inf);
- R.CheckPutConstantOnRight(-0.1);
- R.CheckPutConstantOnRight(0.1);
- R.CheckPutConstantOnRight(inf);
-
- Node* x = R.Parameter();
- Node* one = R.Constant<double>(1.0);
-
- R.CheckBinop(x, x, one); // x * 1.0 => x
- R.CheckBinop(x, one, x); // 1.0 * x => x
-
- CheckNans(&R);
-}
-
-
-TEST(ReduceFloat64Div) {
- ReducerTester R;
- R.binop = R.machine.Float64Div();
-
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- double x = *pl, y = *pr;
- R.CheckFoldBinop<double>(x / y, x, y);
- }
- }
-
- Node* x = R.Parameter();
- Node* one = R.Constant<double>(1.0);
-
- R.CheckBinop(x, x, one); // x / 1.0 => x
-
- CheckNans(&R);
-}
-
-
-TEST(ReduceFloat64Mod) {
- ReducerTester R;
- R.binop = R.machine.Float64Mod();
-
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- double x = *pl, y = *pr;
- R.CheckFoldBinop<double>(modulo(x, y), x, y);
- }
- }
-
- CheckNans(&R);
-}
-
-
-// TODO(titzer): test MachineOperatorReducer for Word64And
-// TODO(titzer): test MachineOperatorReducer for Word64Or
-// TODO(titzer): test MachineOperatorReducer for Word64Xor
-// TODO(titzer): test MachineOperatorReducer for Word64Shl
-// TODO(titzer): test MachineOperatorReducer for Word64Shr
-// TODO(titzer): test MachineOperatorReducer for Word64Sar
-// TODO(titzer): test MachineOperatorReducer for Word64Equal
-// TODO(titzer): test MachineOperatorReducer for Word64Not
-// TODO(titzer): test MachineOperatorReducer for Int64Add
-// TODO(titzer): test MachineOperatorReducer for Int64Sub
-// TODO(titzer): test MachineOperatorReducer for Int64Mul
-// TODO(titzer): test MachineOperatorReducer for Int64UMul
-// TODO(titzer): test MachineOperatorReducer for Int64Div
-// TODO(titzer): test MachineOperatorReducer for Int64UDiv
-// TODO(titzer): test MachineOperatorReducer for Int64Mod
-// TODO(titzer): test MachineOperatorReducer for Int64UMod
-// TODO(titzer): test MachineOperatorReducer for Int64Neg
-// TODO(titzer): test MachineOperatorReducer for ConvertInt32ToFloat64
-// TODO(titzer): test MachineOperatorReducer for ConvertFloat64ToInt32
-// TODO(titzer): test MachineOperatorReducer for Float64Compare
+++ /dev/null
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <vector>
-
-#include "src/v8.h"
-
-#include "graph-tester.h"
-#include "src/compiler/common-operator.h"
-#include "src/compiler/generic-node.h"
-#include "src/compiler/generic-node-inl.h"
-#include "src/compiler/graph.h"
-#include "src/compiler/graph-inl.h"
-#include "src/compiler/graph-visualizer.h"
-#include "src/compiler/operator.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-static SimpleOperator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
- 0, 0, "dummy");
-
-class PreNodeVisitor : public NullNodeVisitor {
- public:
- GenericGraphVisit::Control Pre(Node* node) {
- printf("NODE ID: %d\n", node->id());
- nodes_.push_back(node);
- return GenericGraphVisit::CONTINUE;
- }
- std::vector<Node*> nodes_;
-};
-
-
-class PostNodeVisitor : public NullNodeVisitor {
- public:
- GenericGraphVisit::Control Post(Node* node) {
- printf("NODE ID: %d\n", node->id());
- nodes_.push_back(node);
- return GenericGraphVisit::CONTINUE;
- }
- std::vector<Node*> nodes_;
-};
-
-
-TEST(TestUseNodeVisitEmpty) {
- GraphWithStartNodeTester graph;
-
- PreNodeVisitor node_visitor;
- graph.VisitNodeUsesFromStart(&node_visitor);
-
- CHECK_EQ(1, node_visitor.nodes_.size());
-}
-
-
-TEST(TestUseNodePreOrderVisitSimple) {
- GraphWithStartNodeTester graph;
- Node* n2 = graph.NewNode(&dummy_operator, graph.start());
- Node* n3 = graph.NewNode(&dummy_operator, n2);
- Node* n4 = graph.NewNode(&dummy_operator, n2, n3);
- Node* n5 = graph.NewNode(&dummy_operator, n4, n2);
- graph.SetEnd(n5);
-
- PreNodeVisitor node_visitor;
- graph.VisitNodeUsesFromStart(&node_visitor);
-
- CHECK_EQ(5, node_visitor.nodes_.size());
- CHECK(graph.start()->id() == node_visitor.nodes_[0]->id());
- CHECK(n2->id() == node_visitor.nodes_[1]->id());
- CHECK(n3->id() == node_visitor.nodes_[2]->id());
- CHECK(n4->id() == node_visitor.nodes_[3]->id());
- CHECK(n5->id() == node_visitor.nodes_[4]->id());
-}
-
-
-TEST(TestInputNodePreOrderVisitSimple) {
- GraphWithStartNodeTester graph;
- Node* n2 = graph.NewNode(&dummy_operator, graph.start());
- Node* n3 = graph.NewNode(&dummy_operator, n2);
- Node* n4 = graph.NewNode(&dummy_operator, n2, n3);
- Node* n5 = graph.NewNode(&dummy_operator, n4, n2);
- graph.SetEnd(n5);
-
- PreNodeVisitor node_visitor;
- graph.VisitNodeInputsFromEnd(&node_visitor);
- CHECK_EQ(5, node_visitor.nodes_.size());
- CHECK(n5->id() == node_visitor.nodes_[0]->id());
- CHECK(n4->id() == node_visitor.nodes_[1]->id());
- CHECK(n2->id() == node_visitor.nodes_[2]->id());
- CHECK(graph.start()->id() == node_visitor.nodes_[3]->id());
- CHECK(n3->id() == node_visitor.nodes_[4]->id());
-}
-
-
-TEST(TestUseNodePostOrderVisitSimple) {
- GraphWithStartNodeTester graph;
- Node* n2 = graph.NewNode(&dummy_operator, graph.start());
- Node* n3 = graph.NewNode(&dummy_operator, graph.start());
- Node* n4 = graph.NewNode(&dummy_operator, n2);
- Node* n5 = graph.NewNode(&dummy_operator, n2);
- Node* n6 = graph.NewNode(&dummy_operator, n2);
- Node* n7 = graph.NewNode(&dummy_operator, n3);
- Node* end_dependencies[4] = {n4, n5, n6, n7};
- Node* n8 = graph.NewNode(&dummy_operator, 4, end_dependencies);
- graph.SetEnd(n8);
-
- PostNodeVisitor node_visitor;
- graph.VisitNodeUsesFromStart(&node_visitor);
-
- CHECK_EQ(8, node_visitor.nodes_.size());
- CHECK(graph.end()->id() == node_visitor.nodes_[0]->id());
- CHECK(n4->id() == node_visitor.nodes_[1]->id());
- CHECK(n5->id() == node_visitor.nodes_[2]->id());
- CHECK(n6->id() == node_visitor.nodes_[3]->id());
- CHECK(n2->id() == node_visitor.nodes_[4]->id());
- CHECK(n7->id() == node_visitor.nodes_[5]->id());
- CHECK(n3->id() == node_visitor.nodes_[6]->id());
- CHECK(graph.start()->id() == node_visitor.nodes_[7]->id());
-}
-
-
-TEST(TestUseNodePostOrderVisitLong) {
- GraphWithStartNodeTester graph;
- Node* n2 = graph.NewNode(&dummy_operator, graph.start());
- Node* n3 = graph.NewNode(&dummy_operator, graph.start());
- Node* n4 = graph.NewNode(&dummy_operator, n2);
- Node* n5 = graph.NewNode(&dummy_operator, n2);
- Node* n6 = graph.NewNode(&dummy_operator, n3);
- Node* n7 = graph.NewNode(&dummy_operator, n3);
- Node* n8 = graph.NewNode(&dummy_operator, n5);
- Node* n9 = graph.NewNode(&dummy_operator, n5);
- Node* n10 = graph.NewNode(&dummy_operator, n9);
- Node* n11 = graph.NewNode(&dummy_operator, n9);
- Node* end_dependencies[6] = {n4, n8, n10, n11, n6, n7};
- Node* n12 = graph.NewNode(&dummy_operator, 6, end_dependencies);
- graph.SetEnd(n12);
-
- PostNodeVisitor node_visitor;
- graph.VisitNodeUsesFromStart(&node_visitor);
-
- CHECK_EQ(12, node_visitor.nodes_.size());
- CHECK(graph.end()->id() == node_visitor.nodes_[0]->id());
- CHECK(n4->id() == node_visitor.nodes_[1]->id());
- CHECK(n8->id() == node_visitor.nodes_[2]->id());
- CHECK(n10->id() == node_visitor.nodes_[3]->id());
- CHECK(n11->id() == node_visitor.nodes_[4]->id());
- CHECK(n9->id() == node_visitor.nodes_[5]->id());
- CHECK(n5->id() == node_visitor.nodes_[6]->id());
- CHECK(n2->id() == node_visitor.nodes_[7]->id());
- CHECK(n6->id() == node_visitor.nodes_[8]->id());
- CHECK(n7->id() == node_visitor.nodes_[9]->id());
- CHECK(n3->id() == node_visitor.nodes_[10]->id());
- CHECK(graph.start()->id() == node_visitor.nodes_[11]->id());
-}
-
-
-TEST(TestUseNodePreOrderVisitCycle) {
- GraphWithStartNodeTester graph;
- Node* n0 = graph.start_node();
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n1);
- n0->AppendInput(graph.main_zone(), n2);
- graph.SetStart(n0);
- graph.SetEnd(n2);
-
- PreNodeVisitor node_visitor;
- graph.VisitNodeUsesFromStart(&node_visitor);
-
- CHECK_EQ(3, node_visitor.nodes_.size());
- CHECK(n0->id() == node_visitor.nodes_[0]->id());
- CHECK(n1->id() == node_visitor.nodes_[1]->id());
- CHECK(n2->id() == node_visitor.nodes_[2]->id());
-}
-
-
-struct ReenterNodeVisitor : NullNodeVisitor {
- GenericGraphVisit::Control Pre(Node* node) {
- printf("[%d] PRE NODE: %d\n", static_cast<int>(nodes_.size()), node->id());
- nodes_.push_back(node->id());
- int size = nodes_.size();
- switch (node->id()) {
- case 0:
- return size < 6 ? GenericGraphVisit::REENTER : GenericGraphVisit::SKIP;
- case 1:
- return size < 4 ? GenericGraphVisit::DEFER
- : GenericGraphVisit::CONTINUE;
- default:
- return GenericGraphVisit::REENTER;
- }
- }
-
- GenericGraphVisit::Control Post(Node* node) {
- printf("[%d] POST NODE: %d\n", static_cast<int>(nodes_.size()), node->id());
- nodes_.push_back(-node->id());
- return node->id() == 4 ? GenericGraphVisit::REENTER
- : GenericGraphVisit::CONTINUE;
- }
-
- void PreEdge(Node* from, int index, Node* to) {
- printf("[%d] PRE EDGE: %d-%d\n", static_cast<int>(edges_.size()),
- from->id(), to->id());
- edges_.push_back(std::make_pair(from->id(), to->id()));
- }
-
- void PostEdge(Node* from, int index, Node* to) {
- printf("[%d] POST EDGE: %d-%d\n", static_cast<int>(edges_.size()),
- from->id(), to->id());
- edges_.push_back(std::make_pair(-from->id(), -to->id()));
- }
-
- std::vector<int> nodes_;
- std::vector<std::pair<int, int> > edges_;
-};
-
-
-TEST(TestUseNodeReenterVisit) {
- GraphWithStartNodeTester graph;
- Node* n0 = graph.start_node();
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- Node* n3 = graph.NewNode(&dummy_operator, n2);
- Node* n4 = graph.NewNode(&dummy_operator, n0);
- Node* n5 = graph.NewNode(&dummy_operator, n4);
- n0->AppendInput(graph.main_zone(), n3);
- graph.SetStart(n0);
- graph.SetEnd(n5);
-
- ReenterNodeVisitor visitor;
- graph.VisitNodeUsesFromStart(&visitor);
-
- CHECK_EQ(22, visitor.nodes_.size());
- CHECK_EQ(24, visitor.edges_.size());
-
- CHECK(n0->id() == visitor.nodes_[0]);
- CHECK(n0->id() == visitor.edges_[0].first);
- CHECK(n1->id() == visitor.edges_[0].second);
- CHECK(n1->id() == visitor.nodes_[1]);
- // N1 is deferred.
- CHECK(-n1->id() == visitor.edges_[1].second);
- CHECK(-n0->id() == visitor.edges_[1].first);
- CHECK(n0->id() == visitor.edges_[2].first);
- CHECK(n2->id() == visitor.edges_[2].second);
- CHECK(n2->id() == visitor.nodes_[2]);
- CHECK(n2->id() == visitor.edges_[3].first);
- CHECK(n3->id() == visitor.edges_[3].second);
- CHECK(n3->id() == visitor.nodes_[3]);
- // Circle back to N0, which we may reenter for now.
- CHECK(n3->id() == visitor.edges_[4].first);
- CHECK(n0->id() == visitor.edges_[4].second);
- CHECK(n0->id() == visitor.nodes_[4]);
- CHECK(n0->id() == visitor.edges_[5].first);
- CHECK(n1->id() == visitor.edges_[5].second);
- CHECK(n1->id() == visitor.nodes_[5]);
- // This time N1 is no longer deferred.
- CHECK(-n1->id() == visitor.nodes_[6]);
- CHECK(-n1->id() == visitor.edges_[6].second);
- CHECK(-n0->id() == visitor.edges_[6].first);
- CHECK(n0->id() == visitor.edges_[7].first);
- CHECK(n2->id() == visitor.edges_[7].second);
- CHECK(n2->id() == visitor.nodes_[7]);
- CHECK(n2->id() == visitor.edges_[8].first);
- CHECK(n3->id() == visitor.edges_[8].second);
- CHECK(n3->id() == visitor.nodes_[8]);
- CHECK(n3->id() == visitor.edges_[9].first);
- CHECK(n0->id() == visitor.edges_[9].second);
- CHECK(n0->id() == visitor.nodes_[9]);
- // This time we break at N0 and skip it.
- CHECK(-n0->id() == visitor.edges_[10].second);
- CHECK(-n3->id() == visitor.edges_[10].first);
- CHECK(-n3->id() == visitor.nodes_[10]);
- CHECK(-n3->id() == visitor.edges_[11].second);
- CHECK(-n2->id() == visitor.edges_[11].first);
- CHECK(-n2->id() == visitor.nodes_[11]);
- CHECK(-n2->id() == visitor.edges_[12].second);
- CHECK(-n0->id() == visitor.edges_[12].first);
- CHECK(n0->id() == visitor.edges_[13].first);
- CHECK(n4->id() == visitor.edges_[13].second);
- CHECK(n4->id() == visitor.nodes_[12]);
- CHECK(n4->id() == visitor.edges_[14].first);
- CHECK(n5->id() == visitor.edges_[14].second);
- CHECK(n5->id() == visitor.nodes_[13]);
- CHECK(-n5->id() == visitor.nodes_[14]);
- CHECK(-n5->id() == visitor.edges_[15].second);
- CHECK(-n4->id() == visitor.edges_[15].first);
- CHECK(-n4->id() == visitor.nodes_[15]);
- CHECK(-n4->id() == visitor.edges_[16].second);
- CHECK(-n0->id() == visitor.edges_[16].first);
- CHECK(-n0->id() == visitor.nodes_[16]);
- CHECK(-n0->id() == visitor.edges_[17].second);
- CHECK(-n3->id() == visitor.edges_[17].first);
- CHECK(-n3->id() == visitor.nodes_[17]);
- CHECK(-n3->id() == visitor.edges_[18].second);
- CHECK(-n2->id() == visitor.edges_[18].first);
- CHECK(-n2->id() == visitor.nodes_[18]);
- CHECK(-n2->id() == visitor.edges_[19].second);
- CHECK(-n0->id() == visitor.edges_[19].first);
- // N4 may be reentered.
- CHECK(n0->id() == visitor.edges_[20].first);
- CHECK(n4->id() == visitor.edges_[20].second);
- CHECK(n4->id() == visitor.nodes_[19]);
- CHECK(n4->id() == visitor.edges_[21].first);
- CHECK(n5->id() == visitor.edges_[21].second);
- CHECK(-n5->id() == visitor.edges_[22].second);
- CHECK(-n4->id() == visitor.edges_[22].first);
- CHECK(-n4->id() == visitor.nodes_[20]);
- CHECK(-n4->id() == visitor.edges_[23].second);
- CHECK(-n0->id() == visitor.edges_[23].first);
- CHECK(-n0->id() == visitor.nodes_[21]);
-}
-
-
-TEST(TestPrintNodeGraphToNodeGraphviz) {
- GraphWithStartNodeTester graph;
- Node* n2 = graph.NewNode(&dummy_operator, graph.start());
- Node* n3 = graph.NewNode(&dummy_operator, graph.start());
- Node* n4 = graph.NewNode(&dummy_operator, n2);
- Node* n5 = graph.NewNode(&dummy_operator, n2);
- Node* n6 = graph.NewNode(&dummy_operator, n3);
- Node* n7 = graph.NewNode(&dummy_operator, n3);
- Node* n8 = graph.NewNode(&dummy_operator, n5);
- Node* n9 = graph.NewNode(&dummy_operator, n5);
- Node* n10 = graph.NewNode(&dummy_operator, n9);
- Node* n11 = graph.NewNode(&dummy_operator, n9);
- Node* end_dependencies[6] = {n4, n8, n10, n11, n6, n7};
- Node* n12 = graph.NewNode(&dummy_operator, 6, end_dependencies);
- graph.SetEnd(n12);
-
- OFStream os(stdout);
- os << AsDOT(graph);
-}
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-
-#include "graph-tester.h"
-#include "src/compiler/common-operator.h"
-#include "src/compiler/node-cache.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-TEST(Int32Constant_back_to_back) {
- GraphTester graph;
- Int32NodeCache cache;
-
- for (int i = -2000000000; i < 2000000000; i += 3315177) {
- Node** pos = cache.Find(graph.zone(), i);
- CHECK_NE(NULL, pos);
- for (int j = 0; j < 3; j++) {
- Node** npos = cache.Find(graph.zone(), i);
- CHECK_EQ(pos, npos);
- }
- }
-}
-
-
-TEST(Int32Constant_five) {
- GraphTester graph;
- Int32NodeCache cache;
- CommonOperatorBuilder common(graph.zone());
-
- int32_t constants[] = {static_cast<int32_t>(0x80000000), -77, 0, 1, -1};
-
- Node* nodes[ARRAY_SIZE(constants)];
-
- for (size_t i = 0; i < ARRAY_SIZE(constants); i++) {
- int32_t k = constants[i];
- Node* node = graph.NewNode(common.Int32Constant(k));
- *cache.Find(graph.zone(), k) = nodes[i] = node;
- }
-
- for (size_t i = 0; i < ARRAY_SIZE(constants); i++) {
- int32_t k = constants[i];
- CHECK_EQ(nodes[i], *cache.Find(graph.zone(), k));
- }
-}
-
-
-TEST(Int32Constant_hits) {
- GraphTester graph;
- Int32NodeCache cache;
- const int32_t kSize = 1500;
- Node** nodes = graph.zone()->NewArray<Node*>(kSize);
- CommonOperatorBuilder common(graph.zone());
-
- for (int i = 0; i < kSize; i++) {
- int32_t v = i * -55;
- nodes[i] = graph.NewNode(common.Int32Constant(v));
- *cache.Find(graph.zone(), v) = nodes[i];
- }
-
- int hits = 0;
- for (int i = 0; i < kSize; i++) {
- int32_t v = i * -55;
- Node** pos = cache.Find(graph.zone(), v);
- if (*pos != NULL) {
- CHECK_EQ(nodes[i], *pos);
- hits++;
- }
- }
- CHECK_LT(4, hits);
-}
-
-
-TEST(Int64Constant_back_to_back) {
- GraphTester graph;
- Int64NodeCache cache;
-
- for (int64_t i = -2000000000; i < 2000000000; i += 3315177) {
- Node** pos = cache.Find(graph.zone(), i);
- CHECK_NE(NULL, pos);
- for (int j = 0; j < 3; j++) {
- Node** npos = cache.Find(graph.zone(), i);
- CHECK_EQ(pos, npos);
- }
- }
-}
-
-
-TEST(Int64Constant_hits) {
- GraphTester graph;
- Int64NodeCache cache;
- const int32_t kSize = 1500;
- Node** nodes = graph.zone()->NewArray<Node*>(kSize);
- CommonOperatorBuilder common(graph.zone());
-
- for (int i = 0; i < kSize; i++) {
- int64_t v = static_cast<int64_t>(i) * static_cast<int64_t>(5003001);
- nodes[i] = graph.NewNode(common.Int32Constant(i));
- *cache.Find(graph.zone(), v) = nodes[i];
- }
-
- int hits = 0;
- for (int i = 0; i < kSize; i++) {
- int64_t v = static_cast<int64_t>(i) * static_cast<int64_t>(5003001);
- Node** pos = cache.Find(graph.zone(), v);
- if (*pos != NULL) {
- CHECK_EQ(nodes[i], *pos);
- hits++;
- }
- }
- CHECK_LT(4, hits);
-}
-
-
-TEST(PtrConstant_back_to_back) {
- GraphTester graph;
- PtrNodeCache cache;
- int32_t buffer[50];
-
- for (int32_t* p = buffer;
- (p - buffer) < static_cast<ptrdiff_t>(ARRAY_SIZE(buffer)); p++) {
- Node** pos = cache.Find(graph.zone(), p);
- CHECK_NE(NULL, pos);
- for (int j = 0; j < 3; j++) {
- Node** npos = cache.Find(graph.zone(), p);
- CHECK_EQ(pos, npos);
- }
- }
-}
-
-
-TEST(PtrConstant_hits) {
- GraphTester graph;
- PtrNodeCache cache;
- const int32_t kSize = 50;
- int32_t buffer[kSize];
- Node* nodes[kSize];
- CommonOperatorBuilder common(graph.zone());
-
- for (size_t i = 0; i < ARRAY_SIZE(buffer); i++) {
- int k = static_cast<int>(i);
- int32_t* p = &buffer[i];
- nodes[i] = graph.NewNode(common.Int32Constant(k));
- *cache.Find(graph.zone(), p) = nodes[i];
- }
-
- int hits = 0;
- for (size_t i = 0; i < ARRAY_SIZE(buffer); i++) {
- int32_t* p = &buffer[i];
- Node** pos = cache.Find(graph.zone(), p);
- if (*pos != NULL) {
- CHECK_EQ(nodes[i], *pos);
- hits++;
- }
- }
- CHECK_LT(4, hits);
-}
+++ /dev/null
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-
-#include "graph-tester.h"
-#include "src/compiler/generic-node-inl.h"
-#include "src/compiler/node.h"
-#include "src/compiler/operator.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-static SimpleOperator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
- 0, 0, "dummy");
-
-TEST(NodeAllocation) {
- GraphTester graph;
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
- CHECK(n2->id() != n1->id());
-}
-
-
-TEST(NodeWithOpcode) {
- GraphTester graph;
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
- CHECK(n1->op() == &dummy_operator);
- CHECK(n2->op() == &dummy_operator);
-}
-
-
-TEST(NodeInputs1) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- CHECK_EQ(1, n2->InputCount());
- CHECK(n0 == n2->InputAt(0));
-}
-
-
-TEST(NodeInputs2) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
- CHECK_EQ(2, n2->InputCount());
- CHECK(n0 == n2->InputAt(0));
- CHECK(n1 == n2->InputAt(1));
-}
-
-
-TEST(NodeInputs3) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1, n1);
- CHECK_EQ(3, n2->InputCount());
- CHECK(n0 == n2->InputAt(0));
- CHECK(n1 == n2->InputAt(1));
- CHECK(n1 == n2->InputAt(2));
-}
-
-
-TEST(NodeInputIteratorEmpty) {
- GraphTester graph;
- Node* n1 = graph.NewNode(&dummy_operator);
- Node::Inputs::iterator i(n1->inputs().begin());
- int input_count = 0;
- for (; i != n1->inputs().end(); ++i) {
- input_count++;
- }
- CHECK_EQ(0, input_count);
-}
-
-
-TEST(NodeInputIteratorOne) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node::Inputs::iterator i(n1->inputs().begin());
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(n0, *i);
- ++i;
- CHECK(n1->inputs().end() == i);
-}
-
-
-TEST(NodeUseIteratorEmpty) {
- GraphTester graph;
- Node* n1 = graph.NewNode(&dummy_operator);
- Node::Uses::iterator i(n1->uses().begin());
- int use_count = 0;
- for (; i != n1->uses().end(); ++i) {
- Node::Edge edge(i.edge());
- USE(edge);
- use_count++;
- }
- CHECK_EQ(0, use_count);
-}
-
-
-TEST(NodeUseIteratorOne) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node::Uses::iterator i(n0->uses().begin());
- CHECK_EQ(n1, *i);
- ++i;
- CHECK(n0->uses().end() == i);
-}
-
-
-TEST(NodeUseIteratorReplaceNoUses) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n3 = graph.NewNode(&dummy_operator);
- n0->ReplaceUses(n3);
- CHECK(n0->uses().begin() == n0->uses().end());
-}
-
-
-TEST(NodeUseIteratorReplaceUses) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- Node* n3 = graph.NewNode(&dummy_operator);
- Node::Uses::iterator i1(n0->uses().begin());
- CHECK_EQ(n1, *i1);
- ++i1;
- CHECK_EQ(n2, *i1);
- n0->ReplaceUses(n3);
- Node::Uses::iterator i2(n3->uses().begin());
- CHECK_EQ(n1, *i2);
- ++i2;
- CHECK_EQ(n2, *i2);
- Node::Inputs::iterator i3(n1->inputs().begin());
- CHECK_EQ(n3, *i3);
- ++i3;
- CHECK(n1->inputs().end() == i3);
- Node::Inputs::iterator i4(n2->inputs().begin());
- CHECK_EQ(n3, *i4);
- ++i4;
- CHECK(n2->inputs().end() == i4);
-}
-
-
-TEST(NodeUseIteratorReplaceUsesSelf) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n3 = graph.NewNode(&dummy_operator);
-
- n1->ReplaceInput(0, n1); // Create self-reference.
-
- Node::Uses::iterator i1(n1->uses().begin());
- CHECK_EQ(n1, *i1);
-
- n1->ReplaceUses(n3);
-
- CHECK(n1->uses().begin() == n1->uses().end());
-
- Node::Uses::iterator i2(n3->uses().begin());
- CHECK_EQ(n1, *i2);
- ++i2;
- CHECK(n1->uses().end() == i2);
-}
-
-
-TEST(ReplaceInput) {
- GraphTester graph;
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
- Node* n3 = graph.NewNode(&dummy_operator, n0, n1, n2);
- Node::Inputs::iterator i1(n3->inputs().begin());
- CHECK(n0 == *i1);
- CHECK_EQ(n0, n3->InputAt(0));
- ++i1;
- CHECK_EQ(n1, *i1);
- CHECK_EQ(n1, n3->InputAt(1));
- ++i1;
- CHECK_EQ(n2, *i1);
- CHECK_EQ(n2, n3->InputAt(2));
- ++i1;
- CHECK(i1 == n3->inputs().end());
-
- Node::Uses::iterator i2(n1->uses().begin());
- CHECK_EQ(n3, *i2);
- ++i2;
- CHECK(i2 == n1->uses().end());
-
- Node* n4 = graph.NewNode(&dummy_operator);
- Node::Uses::iterator i3(n4->uses().begin());
- CHECK(i3 == n4->uses().end());
-
- n3->ReplaceInput(1, n4);
-
- Node::Uses::iterator i4(n1->uses().begin());
- CHECK(i4 == n1->uses().end());
-
- Node::Uses::iterator i5(n4->uses().begin());
- CHECK_EQ(n3, *i5);
- ++i5;
- CHECK(i5 == n4->uses().end());
-
- Node::Inputs::iterator i6(n3->inputs().begin());
- CHECK(n0 == *i6);
- CHECK_EQ(n0, n3->InputAt(0));
- ++i6;
- CHECK_EQ(n4, *i6);
- CHECK_EQ(n4, n3->InputAt(1));
- ++i6;
- CHECK_EQ(n2, *i6);
- CHECK_EQ(n2, n3->InputAt(2));
- ++i6;
- CHECK(i6 == n3->inputs().end());
-}
-
-
-TEST(OwnedBy) {
- GraphTester graph;
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
-
- CHECK(!n0->OwnedBy(n1));
- CHECK(!n1->OwnedBy(n0));
-
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- CHECK(n0->OwnedBy(n2));
- CHECK(!n2->OwnedBy(n0));
-
- Node* n3 = graph.NewNode(&dummy_operator, n0);
- CHECK(!n0->OwnedBy(n2));
- CHECK(!n0->OwnedBy(n3));
- CHECK(!n2->OwnedBy(n0));
- CHECK(!n3->OwnedBy(n0));
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- CHECK(n0->OwnedBy(n1));
- CHECK(!n1->OwnedBy(n0));
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- CHECK(!n0->OwnedBy(n1));
- CHECK(!n0->OwnedBy(n2));
- CHECK(!n1->OwnedBy(n0));
- CHECK(!n1->OwnedBy(n2));
- CHECK(!n2->OwnedBy(n0));
- CHECK(!n2->OwnedBy(n1));
-
- Node* n3 = graph.NewNode(&dummy_operator);
- n2->ReplaceInput(0, n3);
-
- CHECK(n0->OwnedBy(n1));
- CHECK(!n1->OwnedBy(n0));
- CHECK(!n1->OwnedBy(n0));
- CHECK(!n1->OwnedBy(n2));
- CHECK(!n2->OwnedBy(n0));
- CHECK(!n2->OwnedBy(n1));
- CHECK(n3->OwnedBy(n2));
- CHECK(!n2->OwnedBy(n3));
- }
-}
-
-
-TEST(Uses) {
- GraphTester graph;
-
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- CHECK_EQ(1, n0->UseCount());
- printf("A: %d vs %d\n", n0->UseAt(0)->id(), n1->id());
- CHECK(n0->UseAt(0) == n1);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- CHECK_EQ(2, n0->UseCount());
- printf("B: %d vs %d\n", n0->UseAt(1)->id(), n2->id());
- CHECK(n0->UseAt(1) == n2);
- Node* n3 = graph.NewNode(&dummy_operator, n0);
- CHECK_EQ(3, n0->UseCount());
- CHECK(n0->UseAt(2) == n3);
-}
-
-
-TEST(Inputs) {
- GraphTester graph;
-
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- Node* n3 = graph.NewNode(&dummy_operator, n0, n1, n2);
- CHECK_EQ(3, n3->InputCount());
- CHECK(n3->InputAt(0) == n0);
- CHECK(n3->InputAt(1) == n1);
- CHECK(n3->InputAt(2) == n2);
- Node* n4 = graph.NewNode(&dummy_operator, n0, n1, n2);
- n3->AppendInput(graph.zone(), n4);
- CHECK_EQ(4, n3->InputCount());
- CHECK(n3->InputAt(0) == n0);
- CHECK(n3->InputAt(1) == n1);
- CHECK(n3->InputAt(2) == n2);
- CHECK(n3->InputAt(3) == n4);
- Node* n5 = graph.NewNode(&dummy_operator, n4);
- n3->AppendInput(graph.zone(), n4);
- CHECK_EQ(5, n3->InputCount());
- CHECK(n3->InputAt(0) == n0);
- CHECK(n3->InputAt(1) == n1);
- CHECK(n3->InputAt(2) == n2);
- CHECK(n3->InputAt(3) == n4);
- CHECK(n3->InputAt(4) == n4);
-
- // Make sure uses have been hooked op correctly.
- Node::Uses uses(n4->uses());
- Node::Uses::iterator current = uses.begin();
- CHECK(current != uses.end());
- CHECK(*current == n3);
- ++current;
- CHECK(current != uses.end());
- CHECK(*current == n5);
- ++current;
- CHECK(current != uses.end());
- CHECK(*current == n3);
- ++current;
- CHECK(current == uses.end());
-}
-
-
-TEST(AppendInputsAndIterator) {
- GraphTester graph;
-
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
-
- Node::Inputs inputs(n2->inputs());
- Node::Inputs::iterator current = inputs.begin();
- CHECK(current != inputs.end());
- CHECK(*current == n0);
- ++current;
- CHECK(current != inputs.end());
- CHECK(*current == n1);
- ++current;
- CHECK(current == inputs.end());
-
- Node* n3 = graph.NewNode(&dummy_operator);
- n2->AppendInput(graph.zone(), n3);
- inputs = n2->inputs();
- current = inputs.begin();
- CHECK(current != inputs.end());
- CHECK(*current == n0);
- CHECK_EQ(0, current.index());
- ++current;
- CHECK(current != inputs.end());
- CHECK(*current == n1);
- CHECK_EQ(1, current.index());
- ++current;
- CHECK(current != inputs.end());
- CHECK(*current == n3);
- CHECK_EQ(2, current.index());
- ++current;
- CHECK(current == inputs.end());
-}
-
-
-TEST(NullInputsSimple) {
- GraphTester graph;
-
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
- CHECK_EQ(2, n2->InputCount());
-
- CHECK(n0 == n2->InputAt(0));
- CHECK(n1 == n2->InputAt(1));
- CHECK_EQ(2, n0->UseCount());
- n2->ReplaceInput(0, NULL);
- CHECK(NULL == n2->InputAt(0));
- CHECK(n1 == n2->InputAt(1));
- CHECK_EQ(1, n0->UseCount());
-}
-
-
-TEST(NullInputsAppended) {
- GraphTester graph;
-
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- Node* n3 = graph.NewNode(&dummy_operator, n0);
- n3->AppendInput(graph.zone(), n1);
- n3->AppendInput(graph.zone(), n2);
- CHECK_EQ(3, n3->InputCount());
-
- CHECK(n0 == n3->InputAt(0));
- CHECK(n1 == n3->InputAt(1));
- CHECK(n2 == n3->InputAt(2));
- CHECK_EQ(1, n1->UseCount());
- n3->ReplaceInput(1, NULL);
- CHECK(n0 == n3->InputAt(0));
- CHECK(NULL == n3->InputAt(1));
- CHECK(n2 == n3->InputAt(2));
- CHECK_EQ(0, n1->UseCount());
-}
-
-
-TEST(ReplaceUsesFromAppendedInputs) {
- GraphTester graph;
-
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- Node* n3 = graph.NewNode(&dummy_operator);
- n2->AppendInput(graph.zone(), n1);
- n2->AppendInput(graph.zone(), n0);
- CHECK_EQ(0, n3->UseCount());
- CHECK_EQ(3, n0->UseCount());
- n0->ReplaceUses(n3);
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(3, n3->UseCount());
-
- Node::Uses uses(n3->uses());
- Node::Uses::iterator current = uses.begin();
- CHECK(current != uses.end());
- CHECK(*current == n1);
- ++current;
- CHECK(current != uses.end());
- CHECK(*current == n2);
- ++current;
- CHECK(current != uses.end());
- CHECK(*current == n2);
- ++current;
- CHECK(current == uses.end());
-}
-
-
-template <bool result>
-struct FixedPredicate {
- bool operator()(const Node* node) const { return result; }
-};
-
-
-TEST(ReplaceUsesIfWithFixedPredicate) {
- GraphTester graph;
-
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- Node* n3 = graph.NewNode(&dummy_operator);
-
- CHECK_EQ(0, n2->UseCount());
- n2->ReplaceUsesIf(FixedPredicate<true>(), n1);
- CHECK_EQ(0, n2->UseCount());
- n2->ReplaceUsesIf(FixedPredicate<false>(), n1);
- CHECK_EQ(0, n2->UseCount());
-
- CHECK_EQ(0, n3->UseCount());
- n3->ReplaceUsesIf(FixedPredicate<true>(), n1);
- CHECK_EQ(0, n3->UseCount());
- n3->ReplaceUsesIf(FixedPredicate<false>(), n1);
- CHECK_EQ(0, n3->UseCount());
-
- CHECK_EQ(2, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- n0->ReplaceUsesIf(FixedPredicate<false>(), n1);
- CHECK_EQ(2, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- n0->ReplaceUsesIf(FixedPredicate<true>(), n1);
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(2, n1->UseCount());
-
- n1->AppendInput(graph.zone(), n1);
- CHECK_EQ(3, n1->UseCount());
- n1->AppendInput(graph.zone(), n3);
- CHECK_EQ(1, n3->UseCount());
- n3->ReplaceUsesIf(FixedPredicate<true>(), n1);
- CHECK_EQ(4, n1->UseCount());
- CHECK_EQ(0, n3->UseCount());
- n1->ReplaceUsesIf(FixedPredicate<false>(), n3);
- CHECK_EQ(4, n1->UseCount());
- CHECK_EQ(0, n3->UseCount());
-}
-
-
-TEST(ReplaceUsesIfWithEqualTo) {
- GraphTester graph;
-
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
-
- CHECK_EQ(0, n2->UseCount());
- n2->ReplaceUsesIf(std::bind1st(std::equal_to<Node*>(), n1), n0);
- CHECK_EQ(0, n2->UseCount());
-
- CHECK_EQ(2, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- n1->ReplaceUsesIf(std::bind1st(std::equal_to<Node*>(), n0), n0);
- CHECK_EQ(2, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- n0->ReplaceUsesIf(std::bind2nd(std::equal_to<Node*>(), n2), n1);
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(2, n1->UseCount());
-}
-
-
-TEST(ReplaceInputMultipleUses) {
- GraphTester graph;
-
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- n2->ReplaceInput(0, n1);
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
-
- Node* n3 = graph.NewNode(&dummy_operator, n0);
- n3->ReplaceInput(0, n1);
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(2, n1->UseCount());
-}
-
-
-TEST(TrimInputCountInline) {
- GraphTester graph;
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- n1->TrimInputCount(1);
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(n0, n1->InputAt(0));
- CHECK_EQ(1, n0->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- n1->TrimInputCount(0);
- CHECK_EQ(0, n1->InputCount());
- CHECK_EQ(0, n0->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
- n2->TrimInputCount(2);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
- n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n1);
- n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n0);
- n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0, n0);
- n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-}
-
-
-TEST(TrimInputCountOutOfLine1) {
- GraphTester graph;
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- n1->AppendInput(graph.zone(), n0);
- n1->TrimInputCount(1);
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(n0, n1->InputAt(0));
- CHECK_EQ(1, n0->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- n1->AppendInput(graph.zone(), n0);
- CHECK_EQ(1, n1->InputCount());
- n1->TrimInputCount(0);
- CHECK_EQ(0, n1->InputCount());
- CHECK_EQ(0, n0->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
- n2->AppendInput(graph.zone(), n0);
- n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
- n2->TrimInputCount(2);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(n0, n2->InputAt(0));
- CHECK_EQ(n1, n2->InputAt(1));
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
- n2->AppendInput(graph.zone(), n0);
- n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
- n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(n0, n2->InputAt(0));
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
- n2->AppendInput(graph.zone(), n0);
- n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
- n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
- n2->AppendInput(graph.zone(), n0);
- n2->AppendInput(graph.zone(), n0);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(2, n0->UseCount());
- n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator);
- n2->AppendInput(graph.zone(), n0);
- n2->AppendInput(graph.zone(), n0);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(2, n0->UseCount());
- n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-}
-
-
-TEST(TrimInputCountOutOfLine2) {
- GraphTester graph;
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
- n2->TrimInputCount(2);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(n0, n2->InputAt(0));
- CHECK_EQ(n1, n2->InputAt(1));
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
- n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(n0, n2->InputAt(0));
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- n2->AppendInput(graph.zone(), n1);
- CHECK_EQ(2, n2->InputCount());
- n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- n2->AppendInput(graph.zone(), n0);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(2, n0->UseCount());
- n2->TrimInputCount(1);
- CHECK_EQ(1, n2->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n2 = graph.NewNode(&dummy_operator, n0);
- n2->AppendInput(graph.zone(), n0);
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(2, n0->UseCount());
- n2->TrimInputCount(0);
- CHECK_EQ(0, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n2->UseCount());
- }
-}
-
-
-TEST(RemoveAllInputs) {
- GraphTester graph;
-
- for (int i = 0; i < 2; i++) {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- Node* n2;
- if (i == 0) {
- n2 = graph.NewNode(&dummy_operator, n0, n1);
- } else {
- n2 = graph.NewNode(&dummy_operator, n0);
- n2->AppendInput(graph.zone(), n1); // with out-of-line input.
- }
-
- n0->RemoveAllInputs();
- CHECK_EQ(0, n0->InputCount());
-
- CHECK_EQ(2, n0->UseCount());
- n1->RemoveAllInputs();
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(1, n0->UseCount());
- CHECK_EQ(NULL, n1->InputAt(0));
-
- CHECK_EQ(1, n1->UseCount());
- n2->RemoveAllInputs();
- CHECK_EQ(2, n2->InputCount());
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(NULL, n2->InputAt(0));
- CHECK_EQ(NULL, n2->InputAt(1));
- }
-
- {
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator, n0);
- n1->ReplaceInput(0, n1); // self-reference.
-
- CHECK_EQ(0, n0->UseCount());
- CHECK_EQ(1, n1->UseCount());
- n1->RemoveAllInputs();
- CHECK_EQ(1, n1->InputCount());
- CHECK_EQ(0, n1->UseCount());
- CHECK_EQ(NULL, n1->InputAt(0));
- }
-}
+++ /dev/null
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-
-#include "src/compiler/operator.h"
-#include "test/cctest/cctest.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-#define NaN (v8::base::OS::nan_value())
-#define Infinity (std::numeric_limits<double>::infinity())
-
-TEST(TestOperatorMnemonic) {
- SimpleOperator op1(10, 0, 0, 0, "ThisOne");
- CHECK_EQ(0, strcmp(op1.mnemonic(), "ThisOne"));
-
- SimpleOperator op2(11, 0, 0, 0, "ThatOne");
- CHECK_EQ(0, strcmp(op2.mnemonic(), "ThatOne"));
-
- Operator1<int> op3(12, 0, 0, 1, "Mnemonic1", 12333);
- CHECK_EQ(0, strcmp(op3.mnemonic(), "Mnemonic1"));
-
- Operator1<double> op4(13, 0, 0, 1, "TheOther", 99.9);
- CHECK_EQ(0, strcmp(op4.mnemonic(), "TheOther"));
-}
-
-
-TEST(TestSimpleOperatorHash) {
- SimpleOperator op1(17, 0, 0, 0, "Another");
- CHECK_EQ(17, op1.HashCode());
-
- SimpleOperator op2(18, 0, 0, 0, "Falsch");
- CHECK_EQ(18, op2.HashCode());
-}
-
-
-TEST(TestSimpleOperatorEquals) {
- SimpleOperator op1a(19, 0, 0, 0, "Another1");
- SimpleOperator op1b(19, 2, 2, 2, "Another2");
-
- CHECK(op1a.Equals(&op1a));
- CHECK(op1a.Equals(&op1b));
- CHECK(op1b.Equals(&op1a));
- CHECK(op1b.Equals(&op1b));
-
- SimpleOperator op2a(20, 0, 0, 0, "Falsch1");
- SimpleOperator op2b(20, 1, 1, 1, "Falsch2");
-
- CHECK(op2a.Equals(&op2a));
- CHECK(op2a.Equals(&op2b));
- CHECK(op2b.Equals(&op2a));
- CHECK(op2b.Equals(&op2b));
-
- CHECK(!op1a.Equals(&op2a));
- CHECK(!op1a.Equals(&op2b));
- CHECK(!op1b.Equals(&op2a));
- CHECK(!op1b.Equals(&op2b));
-
- CHECK(!op2a.Equals(&op1a));
- CHECK(!op2a.Equals(&op1b));
- CHECK(!op2b.Equals(&op1a));
- CHECK(!op2b.Equals(&op1b));
-}
-
-
-static SmartArrayPointer<const char> OperatorToString(Operator* op) {
- OStringStream os;
- os << *op;
- return SmartArrayPointer<const char>(StrDup(os.c_str()));
-}
-
-
-TEST(TestSimpleOperatorPrint) {
- SimpleOperator op1a(19, 0, 0, 0, "Another1");
- SimpleOperator op1b(19, 2, 2, 2, "Another2");
-
- CHECK_EQ("Another1", OperatorToString(&op1a).get());
- CHECK_EQ("Another2", OperatorToString(&op1b).get());
-
- SimpleOperator op2a(20, 0, 0, 0, "Flog1");
- SimpleOperator op2b(20, 1, 1, 1, "Flog2");
-
- CHECK_EQ("Flog1", OperatorToString(&op2a).get());
- CHECK_EQ("Flog2", OperatorToString(&op2b).get());
-}
-
-
-TEST(TestOperator1intHash) {
- Operator1<int> op1a(23, 0, 0, 0, "Wolfie", 11);
- Operator1<int> op1b(23, 2, 2, 2, "Doggie", 11);
-
- CHECK_EQ(op1a.HashCode(), op1b.HashCode());
-
- Operator1<int> op2a(24, 0, 0, 0, "Arfie", 3);
- Operator1<int> op2b(24, 0, 0, 0, "Arfie", 4);
-
- CHECK_NE(op1a.HashCode(), op2a.HashCode());
- CHECK_NE(op2a.HashCode(), op2b.HashCode());
-}
-
-
-TEST(TestOperator1intEquals) {
- Operator1<int> op1a(23, 0, 0, 0, "Scratchy", 11);
- Operator1<int> op1b(23, 2, 2, 2, "Scratchy", 11);
-
- CHECK(op1a.Equals(&op1a));
- CHECK(op1a.Equals(&op1b));
- CHECK(op1b.Equals(&op1a));
- CHECK(op1b.Equals(&op1b));
-
- Operator1<int> op2a(24, 0, 0, 0, "Im", 3);
- Operator1<int> op2b(24, 0, 0, 0, "Im", 4);
-
- CHECK(op2a.Equals(&op2a));
- CHECK(!op2a.Equals(&op2b));
- CHECK(!op2b.Equals(&op2a));
- CHECK(op2b.Equals(&op2b));
-
- CHECK(!op1a.Equals(&op2a));
- CHECK(!op1a.Equals(&op2b));
- CHECK(!op1b.Equals(&op2a));
- CHECK(!op1b.Equals(&op2b));
-
- CHECK(!op2a.Equals(&op1a));
- CHECK(!op2a.Equals(&op1b));
- CHECK(!op2b.Equals(&op1a));
- CHECK(!op2b.Equals(&op1b));
-
- SimpleOperator op3(25, 0, 0, 0, "Weepy");
-
- CHECK(!op1a.Equals(&op3));
- CHECK(!op1b.Equals(&op3));
- CHECK(!op2a.Equals(&op3));
- CHECK(!op2b.Equals(&op3));
-
- CHECK(!op3.Equals(&op1a));
- CHECK(!op3.Equals(&op1b));
- CHECK(!op3.Equals(&op2a));
- CHECK(!op3.Equals(&op2b));
-}
-
-
-TEST(TestOperator1intPrint) {
- Operator1<int> op1(12, 0, 0, 1, "Op1Test", 0);
- CHECK_EQ("Op1Test[0]", OperatorToString(&op1).get());
-
- Operator1<int> op2(12, 0, 0, 1, "Op1Test", 66666666);
- CHECK_EQ("Op1Test[66666666]", OperatorToString(&op2).get());
-
- Operator1<int> op3(12, 0, 0, 1, "FooBar", 2347);
- CHECK_EQ("FooBar[2347]", OperatorToString(&op3).get());
-
- Operator1<int> op4(12, 0, 0, 1, "BarFoo", -879);
- CHECK_EQ("BarFoo[-879]", OperatorToString(&op4).get());
-}
-
-
-TEST(TestOperator1doubleHash) {
- Operator1<double> op1a(23, 0, 0, 0, "Wolfie", 11.77);
- Operator1<double> op1b(23, 2, 2, 2, "Doggie", 11.77);
-
- CHECK_EQ(op1a.HashCode(), op1b.HashCode());
-
- Operator1<double> op2a(24, 0, 0, 0, "Arfie", -6.7);
- Operator1<double> op2b(24, 0, 0, 0, "Arfie", -6.8);
-
- CHECK_NE(op1a.HashCode(), op2a.HashCode());
- CHECK_NE(op2a.HashCode(), op2b.HashCode());
-}
-
-
-TEST(TestOperator1doubleEquals) {
- Operator1<double> op1a(23, 0, 0, 0, "Scratchy", 11.77);
- Operator1<double> op1b(23, 2, 2, 2, "Scratchy", 11.77);
-
- CHECK(op1a.Equals(&op1a));
- CHECK(op1a.Equals(&op1b));
- CHECK(op1b.Equals(&op1a));
- CHECK(op1b.Equals(&op1b));
-
- Operator1<double> op2a(24, 0, 0, 0, "Im", 3.1);
- Operator1<double> op2b(24, 0, 0, 0, "Im", 3.2);
-
- CHECK(op2a.Equals(&op2a));
- CHECK(!op2a.Equals(&op2b));
- CHECK(!op2b.Equals(&op2a));
- CHECK(op2b.Equals(&op2b));
-
- CHECK(!op1a.Equals(&op2a));
- CHECK(!op1a.Equals(&op2b));
- CHECK(!op1b.Equals(&op2a));
- CHECK(!op1b.Equals(&op2b));
-
- CHECK(!op2a.Equals(&op1a));
- CHECK(!op2a.Equals(&op1b));
- CHECK(!op2b.Equals(&op1a));
- CHECK(!op2b.Equals(&op1b));
-
- SimpleOperator op3(25, 0, 0, 0, "Weepy");
-
- CHECK(!op1a.Equals(&op3));
- CHECK(!op1b.Equals(&op3));
- CHECK(!op2a.Equals(&op3));
- CHECK(!op2b.Equals(&op3));
-
- CHECK(!op3.Equals(&op1a));
- CHECK(!op3.Equals(&op1b));
- CHECK(!op3.Equals(&op2a));
- CHECK(!op3.Equals(&op2b));
-
- Operator1<double> op4a(24, 0, 0, 0, "Bashful", NaN);
- Operator1<double> op4b(24, 0, 0, 0, "Bashful", NaN);
-
- CHECK(op4a.Equals(&op4a));
- CHECK(op4a.Equals(&op4b));
- CHECK(op4b.Equals(&op4a));
- CHECK(op4b.Equals(&op4b));
-
- CHECK(!op3.Equals(&op4a));
- CHECK(!op3.Equals(&op4b));
- CHECK(!op3.Equals(&op4a));
- CHECK(!op3.Equals(&op4b));
-}
-
-
-TEST(TestOperator1doublePrint) {
- Operator1<double> op1(12, 0, 0, 1, "Op1Test", 0);
- CHECK_EQ("Op1Test[0]", OperatorToString(&op1).get());
-
- Operator1<double> op2(12, 0, 0, 1, "Op1Test", 7.3);
- CHECK_EQ("Op1Test[7.3]", OperatorToString(&op2).get());
-
- Operator1<double> op3(12, 0, 0, 1, "FooBar", 2e+123);
- CHECK_EQ("FooBar[2e+123]", OperatorToString(&op3).get());
-
- Operator1<double> op4(12, 0, 0, 1, "BarFoo", Infinity);
- CHECK_EQ("BarFoo[inf]", OperatorToString(&op4).get());
-
- Operator1<double> op5(12, 0, 0, 1, "BarFoo", NaN);
- CHECK_EQ("BarFoo[nan]", OperatorToString(&op5).get());
-}
+++ /dev/null
-// 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/common-operator.h"
-#include "src/compiler/graph-inl.h"
-#include "src/compiler/phi-reducer.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-class PhiReducerTester : HandleAndZoneScope {
- public:
- PhiReducerTester()
- : isolate(main_isolate()),
- common(main_zone()),
- graph(main_zone()),
- self(graph.NewNode(common.Start())),
- dead(graph.NewNode(common.Dead())) {}
-
- Isolate* isolate;
- CommonOperatorBuilder common;
- Graph graph;
- Node* self;
- Node* dead;
-
- void CheckReduce(Node* expect, Node* phi) {
- PhiReducer reducer;
- Reduction reduction = reducer.Reduce(phi);
- if (expect == phi) {
- CHECK(!reduction.Changed());
- } else {
- CHECK(reduction.Changed());
- CHECK_EQ(expect, reduction.replacement());
- }
- }
-
- Node* Int32Constant(int32_t val) {
- return graph.NewNode(common.Int32Constant(val));
- }
-
- Node* Float64Constant(double val) {
- return graph.NewNode(common.Float64Constant(val));
- }
-
- Node* Parameter(int32_t index = 0) {
- return graph.NewNode(common.Parameter(index));
- }
-
- Node* Phi(Node* a) {
- return SetSelfReferences(graph.NewNode(common.Phi(1), a));
- }
-
- Node* Phi(Node* a, Node* b) {
- return SetSelfReferences(graph.NewNode(common.Phi(2), a, b));
- }
-
- Node* Phi(Node* a, Node* b, Node* c) {
- return SetSelfReferences(graph.NewNode(common.Phi(3), a, b, c));
- }
-
- Node* Phi(Node* a, Node* b, Node* c, Node* d) {
- return SetSelfReferences(graph.NewNode(common.Phi(4), a, b, c, d));
- }
-
- Node* PhiWithControl(Node* a, Node* control) {
- return SetSelfReferences(graph.NewNode(common.Phi(1), a, control));
- }
-
- Node* PhiWithControl(Node* a, Node* b, Node* control) {
- return SetSelfReferences(graph.NewNode(common.Phi(2), a, b, control));
- }
-
- Node* SetSelfReferences(Node* node) {
- Node::Inputs inputs = node->inputs();
- for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
- ++iter) {
- Node* input = *iter;
- if (input == self) node->ReplaceInput(iter.index(), node);
- }
- return node;
- }
-};
-
-
-TEST(PhiReduce1) {
- PhiReducerTester R;
- Node* zero = R.Int32Constant(0);
- Node* one = R.Int32Constant(1);
- Node* oneish = R.Float64Constant(1.1);
- Node* param = R.Parameter();
-
- Node* singles[] = {zero, one, oneish, param};
- for (size_t i = 0; i < ARRAY_SIZE(singles); i++) {
- R.CheckReduce(singles[i], R.Phi(singles[i]));
- }
-}
-
-
-TEST(PhiReduce2) {
- PhiReducerTester R;
- Node* zero = R.Int32Constant(0);
- Node* one = R.Int32Constant(1);
- Node* oneish = R.Float64Constant(1.1);
- Node* param = R.Parameter();
-
- Node* singles[] = {zero, one, oneish, param};
- for (size_t i = 0; i < ARRAY_SIZE(singles); i++) {
- Node* a = singles[i];
- R.CheckReduce(a, R.Phi(a, a));
- }
-
- for (size_t i = 0; i < ARRAY_SIZE(singles); i++) {
- Node* a = singles[i];
- R.CheckReduce(a, R.Phi(R.self, a));
- R.CheckReduce(a, R.Phi(a, R.self));
- }
-
- for (size_t i = 1; i < ARRAY_SIZE(singles); i++) {
- Node* a = singles[i], *b = singles[0];
- Node* phi1 = R.Phi(b, a);
- R.CheckReduce(phi1, phi1);
-
- Node* phi2 = R.Phi(a, b);
- R.CheckReduce(phi2, phi2);
- }
-}
-
-
-TEST(PhiReduce3) {
- PhiReducerTester R;
- Node* zero = R.Int32Constant(0);
- Node* one = R.Int32Constant(1);
- Node* oneish = R.Float64Constant(1.1);
- Node* param = R.Parameter();
-
- Node* singles[] = {zero, one, oneish, param};
- for (size_t i = 0; i < ARRAY_SIZE(singles); i++) {
- Node* a = singles[i];
- R.CheckReduce(a, R.Phi(a, a, a));
- }
-
- for (size_t i = 0; i < ARRAY_SIZE(singles); i++) {
- Node* a = singles[i];
- R.CheckReduce(a, R.Phi(R.self, a, a));
- R.CheckReduce(a, R.Phi(a, R.self, a));
- R.CheckReduce(a, R.Phi(a, a, R.self));
- }
-
- for (size_t i = 1; i < ARRAY_SIZE(singles); i++) {
- Node* a = singles[i], *b = singles[0];
- Node* phi1 = R.Phi(b, a, a);
- R.CheckReduce(phi1, phi1);
-
- Node* phi2 = R.Phi(a, b, a);
- R.CheckReduce(phi2, phi2);
-
- Node* phi3 = R.Phi(a, a, b);
- R.CheckReduce(phi3, phi3);
- }
-}
-
-
-TEST(PhiReduce4) {
- PhiReducerTester R;
- Node* zero = R.Int32Constant(0);
- Node* one = R.Int32Constant(1);
- Node* oneish = R.Float64Constant(1.1);
- Node* param = R.Parameter();
-
- Node* singles[] = {zero, one, oneish, param};
- for (size_t i = 0; i < ARRAY_SIZE(singles); i++) {
- Node* a = singles[i];
- R.CheckReduce(a, R.Phi(a, a, a, a));
- }
-
- for (size_t i = 0; i < ARRAY_SIZE(singles); i++) {
- Node* a = singles[i];
- R.CheckReduce(a, R.Phi(R.self, a, a, a));
- R.CheckReduce(a, R.Phi(a, R.self, a, a));
- R.CheckReduce(a, R.Phi(a, a, R.self, a));
- R.CheckReduce(a, R.Phi(a, a, a, R.self));
-
- R.CheckReduce(a, R.Phi(R.self, R.self, a, a));
- R.CheckReduce(a, R.Phi(a, R.self, R.self, a));
- R.CheckReduce(a, R.Phi(a, a, R.self, R.self));
- R.CheckReduce(a, R.Phi(R.self, a, a, R.self));
- }
-
- for (size_t i = 1; i < ARRAY_SIZE(singles); i++) {
- Node* a = singles[i], *b = singles[0];
- Node* phi1 = R.Phi(b, a, a, a);
- R.CheckReduce(phi1, phi1);
-
- Node* phi2 = R.Phi(a, b, a, a);
- R.CheckReduce(phi2, phi2);
-
- Node* phi3 = R.Phi(a, a, b, a);
- R.CheckReduce(phi3, phi3);
-
- Node* phi4 = R.Phi(a, a, a, b);
- R.CheckReduce(phi4, phi4);
- }
-}
-
-
-TEST(PhiReduceShouldIgnoreControlNodes) {
- PhiReducerTester R;
- Node* zero = R.Int32Constant(0);
- Node* one = R.Int32Constant(1);
- Node* oneish = R.Float64Constant(1.1);
- Node* param = R.Parameter();
-
- Node* singles[] = {zero, one, oneish, param};
- for (size_t i = 0; i < ARRAY_SIZE(singles); ++i) {
- R.CheckReduce(singles[i], R.PhiWithControl(singles[i], R.dead));
- R.CheckReduce(singles[i], R.PhiWithControl(R.self, singles[i], R.dead));
- R.CheckReduce(singles[i], R.PhiWithControl(singles[i], R.self, R.dead));
- }
-}
+++ /dev/null
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-#include "test/cctest/cctest.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) {
- InitializedHandleScope handles;
- const char* source = "(function(a,b) { return a + b; })";
- Handle<JSFunction> function = v8::Utils::OpenHandle(
- *v8::Handle<v8::Function>::Cast(CompileRun(source)));
- CompilationInfoWithZone info(function);
-
- CHECK(Parser::Parse(&info));
- StrictMode strict_mode = info.function()->strict_mode();
- info.SetStrictMode(strict_mode);
- CHECK(Rewriter::Rewrite(&info));
- CHECK(Scope::Analyze(&info));
- CHECK_NE(NULL, info.scope());
-
- Pipeline pipeline(&info);
- Handle<Code> code = pipeline.GenerateCode();
-#if V8_TURBOFAN_TARGET
- CHECK(Pipeline::SupportedTarget());
- CHECK(!code.is_null());
-#else
- USE(code);
-#endif
-}
+++ /dev/null
-// 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 <limits>
-
-#include "src/v8.h"
-#include "test/cctest/cctest.h"
-#include "test/cctest/compiler/graph-builder-tester.h"
-
-#include "src/compiler/node-matchers.h"
-#include "src/compiler/representation-change.h"
-#include "src/compiler/typer.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-namespace v8 { // for friendiness.
-namespace internal {
-namespace compiler {
-
-class RepresentationChangerTester : public HandleAndZoneScope,
- public GraphAndBuilders {
- public:
- RepresentationChangerTester()
- : GraphAndBuilders(main_zone()),
- typer_(main_zone()),
- jsgraph_(main_graph_, &main_common_, &typer_),
- changer_(&jsgraph_, &main_simplified_, &main_machine_, main_isolate()) {
- }
-
- Typer typer_;
- JSGraph jsgraph_;
- RepresentationChanger changer_;
-
- Isolate* isolate() { return main_isolate(); }
- Graph* graph() { return main_graph_; }
- CommonOperatorBuilder* common() { return &main_common_; }
- JSGraph* jsgraph() { return &jsgraph_; }
- RepresentationChanger* changer() { return &changer_; }
-
- // TODO(titzer): use ValueChecker / ValueUtil
- void CheckInt32Constant(Node* n, int32_t expected) {
- ValueMatcher<int32_t> m(n);
- CHECK(m.HasValue());
- CHECK_EQ(expected, m.Value());
- }
-
- void CheckHeapConstant(Node* n, Object* expected) {
- ValueMatcher<Handle<Object> > m(n);
- CHECK(m.HasValue());
- CHECK_EQ(expected, *m.Value());
- }
-
- void CheckNumberConstant(Node* n, double expected) {
- ValueMatcher<double> m(n);
- CHECK_EQ(IrOpcode::kNumberConstant, n->opcode());
- CHECK(m.HasValue());
- CHECK_EQ(expected, m.Value());
- }
-
- Node* Parameter(int index = 0) {
- return graph()->NewNode(common()->Parameter(index));
- }
-
- void CheckTypeError(RepTypeUnion from, RepTypeUnion to) {
- changer()->testing_type_errors_ = true;
- changer()->type_error_ = false;
- Node* n = Parameter(0);
- Node* c = changer()->GetRepresentationFor(n, from, to);
- CHECK_EQ(n, c);
- CHECK(changer()->type_error_);
- }
-
- void CheckNop(RepTypeUnion from, RepTypeUnion to) {
- Node* n = Parameter(0);
- Node* c = changer()->GetRepresentationFor(n, from, to);
- CHECK_EQ(n, c);
- }
-};
-}
-}
-} // namespace v8::internal::compiler
-
-
-static const RepType all_reps[] = {rBit, rWord32, rWord64, rFloat64, rTagged};
-
-
-// TODO(titzer): lift this to ValueHelper
-static const double double_inputs[] = {
- 0.0, -0.0, 1.0, -1.0, 0.1, 1.4, -1.7,
- 2, 5, 6, 982983, 888, -999.8, 3.1e7,
- -2e66, 2.3e124, -12e73, V8_INFINITY, -V8_INFINITY};
-
-
-static const int32_t int32_inputs[] = {
- 0, 1, -1,
- 2, 5, 6,
- 982983, 888, -999,
- 65535, static_cast<int32_t>(0xFFFFFFFF), static_cast<int32_t>(0x80000000)};
-
-
-static const uint32_t uint32_inputs[] = {
- 0, 1, static_cast<uint32_t>(-1), 2, 5, 6,
- 982983, 888, static_cast<uint32_t>(-999), 65535, 0xFFFFFFFF, 0x80000000};
-
-
-TEST(BoolToBit_constant) {
- RepresentationChangerTester r;
-
- Node* true_node = r.jsgraph()->TrueConstant();
- Node* true_bit = r.changer()->GetRepresentationFor(true_node, rTagged, rBit);
- r.CheckInt32Constant(true_bit, 1);
-
- Node* false_node = r.jsgraph()->FalseConstant();
- Node* false_bit =
- r.changer()->GetRepresentationFor(false_node, rTagged, rBit);
- r.CheckInt32Constant(false_bit, 0);
-}
-
-
-TEST(BitToBool_constant) {
- RepresentationChangerTester r;
-
- for (int i = -5; i < 5; i++) {
- Node* node = r.jsgraph()->Int32Constant(i);
- Node* val = r.changer()->GetRepresentationFor(node, rBit, rTagged);
- r.CheckHeapConstant(val, i == 0 ? r.isolate()->heap()->false_value()
- : r.isolate()->heap()->true_value());
- }
-}
-
-
-TEST(ToTagged_constant) {
- RepresentationChangerTester r;
-
- for (size_t i = 0; i < ARRAY_SIZE(double_inputs); i++) {
- Node* n = r.jsgraph()->Float64Constant(double_inputs[i]);
- Node* c = r.changer()->GetRepresentationFor(n, rFloat64, rTagged);
- r.CheckNumberConstant(c, double_inputs[i]);
- }
-
- for (size_t i = 0; i < ARRAY_SIZE(int32_inputs); i++) {
- Node* n = r.jsgraph()->Int32Constant(int32_inputs[i]);
- Node* c = r.changer()->GetRepresentationFor(n, rWord32 | tInt32, rTagged);
- r.CheckNumberConstant(c, static_cast<double>(int32_inputs[i]));
- }
-
- for (size_t i = 0; i < ARRAY_SIZE(uint32_inputs); i++) {
- Node* n = r.jsgraph()->Int32Constant(uint32_inputs[i]);
- Node* c = r.changer()->GetRepresentationFor(n, rWord32 | tUint32, rTagged);
- r.CheckNumberConstant(c, static_cast<double>(uint32_inputs[i]));
- }
-}
-
-
-static void CheckChange(IrOpcode::Value expected, RepTypeUnion from,
- RepTypeUnion to) {
- RepresentationChangerTester r;
-
- Node* n = r.Parameter();
- Node* c = r.changer()->GetRepresentationFor(n, from, to);
-
- CHECK_NE(c, n);
- CHECK_EQ(expected, c->opcode());
- CHECK_EQ(n, c->InputAt(0));
-}
-
-
-TEST(SingleChanges) {
- CheckChange(IrOpcode::kChangeBoolToBit, rTagged, rBit);
- CheckChange(IrOpcode::kChangeBitToBool, rBit, rTagged);
-
- CheckChange(IrOpcode::kChangeInt32ToTagged, rWord32 | tInt32, rTagged);
- CheckChange(IrOpcode::kChangeUint32ToTagged, rWord32 | tUint32, rTagged);
- CheckChange(IrOpcode::kChangeFloat64ToTagged, rFloat64, rTagged);
-
- CheckChange(IrOpcode::kChangeTaggedToInt32, rTagged | tInt32, rWord32);
- CheckChange(IrOpcode::kChangeTaggedToUint32, rTagged | tUint32, rWord32);
- CheckChange(IrOpcode::kChangeTaggedToFloat64, rTagged, rFloat64);
-
- // Int32,Uint32 <-> Float64 are actually machine conversions.
- CheckChange(IrOpcode::kConvertInt32ToFloat64, rWord32 | tInt32, rFloat64);
- CheckChange(IrOpcode::kConvertUint32ToFloat64, rWord32 | tUint32, rFloat64);
- CheckChange(IrOpcode::kConvertFloat64ToInt32, rFloat64 | tInt32, rWord32);
- CheckChange(IrOpcode::kConvertFloat64ToUint32, rFloat64 | tUint32, rWord32);
-}
-
-
-TEST(SignednessInWord32) {
- RepresentationChangerTester r;
-
- // TODO(titzer): these are currently type errors because the output type is
- // not specified. Maybe the RepresentationChanger should assume anything to or
- // from {rWord32} is {tInt32}, i.e. signed, if not it is explicitly otherwise?
- r.CheckTypeError(rTagged, rWord32 | tInt32);
- r.CheckTypeError(rTagged, rWord32 | tUint32);
- r.CheckTypeError(rWord32, rFloat64);
- r.CheckTypeError(rFloat64, rWord32);
-
- // CheckChange(IrOpcode::kChangeTaggedToInt32, rTagged, rWord32 | tInt32);
- // CheckChange(IrOpcode::kChangeTaggedToUint32, rTagged, rWord32 | tUint32);
- // CheckChange(IrOpcode::kConvertInt32ToFloat64, rWord32, rFloat64);
- // CheckChange(IrOpcode::kConvertFloat64ToInt32, rFloat64, rWord32);
-}
-
-
-TEST(Nops) {
- RepresentationChangerTester r;
-
- // X -> X is always a nop for any single representation X.
- for (size_t i = 0; i < ARRAY_SIZE(all_reps); i++) {
- r.CheckNop(all_reps[i], all_reps[i]);
- }
-
- // 32-bit or 64-bit words can be used as branch conditions (rBit).
- r.CheckNop(rWord32, rBit);
- r.CheckNop(rWord32, rBit | tBool);
- r.CheckNop(rWord64, rBit);
- r.CheckNop(rWord64, rBit | tBool);
-
- // rBit (result of comparison) is implicitly a wordish thing.
- r.CheckNop(rBit, rWord32);
- r.CheckNop(rBit | tBool, rWord32);
- r.CheckNop(rBit, rWord64);
- r.CheckNop(rBit | tBool, rWord64);
-}
-
-
-TEST(TypeErrors) {
- RepresentationChangerTester r;
-
- // Floats cannot be implicitly converted to/from comparison conditions.
- r.CheckTypeError(rFloat64, rBit);
- r.CheckTypeError(rFloat64, rBit | tBool);
- r.CheckTypeError(rBit, rFloat64);
- r.CheckTypeError(rBit | tBool, rFloat64);
-
- // Word64 is internal and shouldn't be implicitly converted.
- r.CheckTypeError(rWord64, rTagged | tBool);
- r.CheckTypeError(rWord64, rTagged);
- r.CheckTypeError(rWord64, rTagged | tBool);
- r.CheckTypeError(rTagged, rWord64);
- r.CheckTypeError(rTagged | tBool, rWord64);
-
- // Word64 / Word32 shouldn't be implicitly converted.
- r.CheckTypeError(rWord64, rWord32);
- r.CheckTypeError(rWord32, rWord64);
- r.CheckTypeError(rWord64, rWord32 | tInt32);
- r.CheckTypeError(rWord32 | tInt32, rWord64);
- r.CheckTypeError(rWord64, rWord32 | tUint32);
- r.CheckTypeError(rWord32 | tUint32, rWord64);
-
- for (size_t i = 0; i < ARRAY_SIZE(all_reps); i++) {
- for (size_t j = 0; j < ARRAY_SIZE(all_reps); j++) {
- if (i == j) continue;
- // Only a single from representation is allowed.
- r.CheckTypeError(all_reps[i] | all_reps[j], rTagged);
- }
- }
-}
-
-
-TEST(CompleteMatrix) {
- // TODO(titzer): test all variants in the matrix.
- // rB
- // tBrB
- // tBrT
- // rW32
- // tIrW32
- // tUrW32
- // rW64
- // tIrW64
- // tUrW64
- // rF64
- // tIrF64
- // tUrF64
- // tArF64
- // rT
- // tArT
-}
+++ /dev/null
-// 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 "v8.h"
-
-#include "function-tester.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-
-TEST(TurboSimpleDeopt) {
- 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; })");
-
- T.CheckCall(T.Val(2), T.Val(1));
-}
-
-
-TEST(TurboTrivialDeopt) {
- FLAG_allow_natives_syntax = true;
- FLAG_turbo_deoptimization = true;
-
- FunctionTester T(
- "(function foo() {"
- "%DeoptimizeFunction(foo);"
- "return 1; })");
-
- T.CheckCall(T.Val(1));
-}
+++ /dev/null
-// 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/compiler/function-tester.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-
-TEST(IsSmi) {
- FunctionTester T("(function(a) { return %_IsSmi(a); })");
-
- 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(IsNonNegativeSmi) {
- FunctionTester T("(function(a) { return %_IsNonNegativeSmi(a); })");
-
- T.CheckTrue(T.Val(1));
- T.CheckFalse(T.Val(1.1));
- T.CheckFalse(T.Val(-0.0));
- T.CheckFalse(T.Val(-2));
- T.CheckFalse(T.Val(-2.3));
- T.CheckFalse(T.undefined());
-}
-
-
-TEST(IsMinusZero) {
- FunctionTester T("(function(a) { return %_IsMinusZero(a); })");
-
- T.CheckFalse(T.Val(1));
- T.CheckFalse(T.Val(1.1));
- T.CheckTrue(T.Val(-0.0));
- T.CheckFalse(T.Val(-2));
- T.CheckFalse(T.Val(-2.3));
- T.CheckFalse(T.undefined());
-}
-
-
-TEST(IsArray) {
- FunctionTester T("(function(a) { return %_IsArray(a); })");
-
- T.CheckFalse(T.NewObject("(function() {})"));
- T.CheckTrue(T.NewObject("([1])"));
- T.CheckFalse(T.NewObject("({})"));
- T.CheckFalse(T.NewObject("(/x/)"));
- T.CheckFalse(T.undefined());
- T.CheckFalse(T.null());
- T.CheckFalse(T.Val("x"));
- T.CheckFalse(T.Val(1));
-}
-
-
-TEST(IsObject) {
- FunctionTester T("(function(a) { return %_IsObject(a); })");
-
- T.CheckFalse(T.NewObject("(function() {})"));
- T.CheckTrue(T.NewObject("([1])"));
- T.CheckTrue(T.NewObject("({})"));
- T.CheckTrue(T.NewObject("(/x/)"));
- T.CheckFalse(T.undefined());
- T.CheckTrue(T.null());
- T.CheckFalse(T.Val("x"));
- T.CheckFalse(T.Val(1));
-}
-
-
-TEST(IsFunction) {
- FunctionTester T("(function(a) { return %_IsFunction(a); })");
-
- T.CheckTrue(T.NewObject("(function() {})"));
- T.CheckFalse(T.NewObject("([1])"));
- T.CheckFalse(T.NewObject("({})"));
- T.CheckFalse(T.NewObject("(/x/)"));
- T.CheckFalse(T.undefined());
- T.CheckFalse(T.null());
- T.CheckFalse(T.Val("x"));
- T.CheckFalse(T.Val(1));
-}
-
-
-TEST(IsRegExp) {
- FunctionTester T("(function(a) { return %_IsRegExp(a); })");
-
- T.CheckFalse(T.NewObject("(function() {})"));
- T.CheckFalse(T.NewObject("([1])"));
- T.CheckFalse(T.NewObject("({})"));
- T.CheckTrue(T.NewObject("(/x/)"));
- T.CheckFalse(T.undefined());
- T.CheckFalse(T.null());
- T.CheckFalse(T.Val("x"));
- T.CheckFalse(T.Val(1));
-}
-
-
-TEST(ClassOf) {
- FunctionTester T("(function(a) { return %_ClassOf(a); })");
-
- T.CheckCall(T.Val("Function"), T.NewObject("(function() {})"));
- T.CheckCall(T.Val("Array"), T.NewObject("([1])"));
- T.CheckCall(T.Val("Object"), T.NewObject("({})"));
- T.CheckCall(T.Val("RegExp"), T.NewObject("(/x/)"));
- T.CheckCall(T.null(), T.undefined());
- T.CheckCall(T.null(), T.null());
- T.CheckCall(T.null(), T.Val("x"));
- T.CheckCall(T.null(), T.Val(1));
-}
-
-
-TEST(ObjectEquals) {
- FunctionTester T("(function(a,b) { return %_ObjectEquals(a,b); })");
- CompileRun("var o = {}");
-
- T.CheckTrue(T.NewObject("(o)"), T.NewObject("(o)"));
- T.CheckTrue(T.Val("internal"), T.Val("internal"));
- T.CheckTrue(T.true_value(), T.true_value());
- T.CheckFalse(T.true_value(), T.false_value());
- T.CheckFalse(T.NewObject("({})"), T.NewObject("({})"));
- T.CheckFalse(T.Val("a"), T.Val("b"));
-}
-
-
-TEST(ValueOf) {
- FunctionTester T("(function(a) { return %_ValueOf(a); })");
-
- T.CheckCall(T.Val("a"), T.Val("a"));
- T.CheckCall(T.Val("b"), T.NewObject("(new String('b'))"));
- T.CheckCall(T.Val(123), T.Val(123));
- T.CheckCall(T.Val(456), T.NewObject("(new Number(456))"));
-}
-
-
-TEST(SetValueOf) {
- FunctionTester T("(function(a,b) { return %_SetValueOf(a,b); })");
-
- T.CheckCall(T.Val("a"), T.NewObject("(new String)"), T.Val("a"));
- T.CheckCall(T.Val(123), T.NewObject("(new Number)"), T.Val(123));
- T.CheckCall(T.Val("x"), T.undefined(), T.Val("x"));
-}
-
-
-TEST(StringCharFromCode) {
- FunctionTester T("(function(a) { return %_StringCharFromCode(a); })");
-
- T.CheckCall(T.Val("a"), T.Val(97));
- T.CheckCall(T.Val("\xE2\x9D\x8A"), T.Val(0x274A));
- T.CheckCall(T.Val(""), T.undefined());
-}
-
-
-TEST(StringCharAt) {
- FunctionTester T("(function(a,b) { return %_StringCharAt(a,b); })");
-
- T.CheckCall(T.Val("e"), T.Val("huge fan!"), T.Val(3));
- T.CheckCall(T.Val("f"), T.Val("\xE2\x9D\x8A fan!"), T.Val(2));
- T.CheckCall(T.Val(""), T.Val("not a fan!"), T.Val(23));
-}
-
-
-TEST(StringCharCodeAt) {
- FunctionTester T("(function(a,b) { return %_StringCharCodeAt(a,b); })");
-
- T.CheckCall(T.Val('e'), T.Val("huge fan!"), T.Val(3));
- T.CheckCall(T.Val('f'), T.Val("\xE2\x9D\x8A fan!"), T.Val(2));
- T.CheckCall(T.nan(), T.Val("not a fan!"), T.Val(23));
-}
-
-
-TEST(StringAdd) {
- FunctionTester T("(function(a,b) { return %_StringAdd(a,b); })");
-
- T.CheckCall(T.Val("aaabbb"), T.Val("aaa"), T.Val("bbb"));
- T.CheckCall(T.Val("aaa"), T.Val("aaa"), T.Val(""));
- T.CheckCall(T.Val("bbb"), T.Val(""), T.Val("bbb"));
-}
-
-
-TEST(StringSubString) {
- FunctionTester T("(function(a,b) { return %_SubString(a,b,b+3); })");
-
- T.CheckCall(T.Val("aaa"), T.Val("aaabbb"), T.Val(0.0));
- T.CheckCall(T.Val("abb"), T.Val("aaabbb"), T.Val(2));
- T.CheckCall(T.Val("aaa"), T.Val("aaa"), T.Val(0.0));
-}
-
-
-TEST(StringCompare) {
- FunctionTester T("(function(a,b) { return %_StringCompare(a,b); })");
-
- T.CheckCall(T.Val(-1), T.Val("aaa"), T.Val("bbb"));
- T.CheckCall(T.Val(0.0), T.Val("bbb"), T.Val("bbb"));
- T.CheckCall(T.Val(+1), T.Val("ccc"), T.Val("bbb"));
-}
-
-
-TEST(CallFunction) {
- FunctionTester T("(function(a,b) { return %_CallFunction(a, 1, 2, 3, b); })");
- CompileRun("function f(a,b,c) { return a + b + c + this.d; }");
-
- T.CheckCall(T.Val(129), T.NewObject("({d:123})"), T.NewObject("f"));
- T.CheckCall(T.Val("6x"), T.NewObject("({d:'x'})"), T.NewObject("f"));
-}
+++ /dev/null
-// 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/compiler/function-tester.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-TEST(Conditional) {
- FunctionTester T("(function(a) { return a ? 23 : 42; })");
-
- T.CheckCall(T.Val(23), T.true_value(), T.undefined());
- T.CheckCall(T.Val(42), T.false_value(), T.undefined());
- T.CheckCall(T.Val(42), T.undefined(), T.undefined());
- T.CheckCall(T.Val(42), T.Val(0.0), T.undefined());
- T.CheckCall(T.Val(23), T.Val(999), T.undefined());
- T.CheckCall(T.Val(23), T.Val("x"), T.undefined());
-}
-
-
-TEST(LogicalAnd) {
- FunctionTester T("(function(a,b) { return a && b; })");
-
- T.CheckCall(T.true_value(), T.true_value(), T.true_value());
- T.CheckCall(T.false_value(), T.false_value(), T.true_value());
- T.CheckCall(T.false_value(), T.true_value(), T.false_value());
- T.CheckCall(T.false_value(), T.false_value(), T.false_value());
-
- T.CheckCall(T.Val(999), T.Val(777), T.Val(999));
- T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(999));
- T.CheckCall(T.Val("b"), T.Val("a"), T.Val("b"));
-}
-
-
-TEST(LogicalOr) {
- FunctionTester T("(function(a,b) { return a || b; })");
-
- T.CheckCall(T.true_value(), T.true_value(), T.true_value());
- T.CheckCall(T.true_value(), T.false_value(), T.true_value());
- T.CheckCall(T.true_value(), T.true_value(), T.false_value());
- T.CheckCall(T.false_value(), T.false_value(), T.false_value());
-
- T.CheckCall(T.Val(777), T.Val(777), T.Val(999));
- T.CheckCall(T.Val(999), T.Val(0.0), T.Val(999));
- T.CheckCall(T.Val("a"), T.Val("a"), T.Val("b"));
-}
-
-
-TEST(LogicalEffect) {
- FunctionTester T("(function(a,b) { a && (b = a); return b; })");
-
- T.CheckCall(T.true_value(), T.true_value(), T.true_value());
- T.CheckCall(T.true_value(), T.false_value(), T.true_value());
- T.CheckCall(T.true_value(), T.true_value(), T.false_value());
- T.CheckCall(T.false_value(), T.false_value(), T.false_value());
-
- T.CheckCall(T.Val(777), T.Val(777), T.Val(999));
- T.CheckCall(T.Val(999), T.Val(0.0), T.Val(999));
- T.CheckCall(T.Val("a"), T.Val("a"), T.Val("b"));
-}
-
-
-TEST(IfStatement) {
- FunctionTester T("(function(a) { if (a) { return 1; } else { return 2; } })");
-
- T.CheckCall(T.Val(1), T.true_value(), T.undefined());
- T.CheckCall(T.Val(2), T.false_value(), T.undefined());
- T.CheckCall(T.Val(2), T.undefined(), T.undefined());
- T.CheckCall(T.Val(2), T.Val(0.0), T.undefined());
- T.CheckCall(T.Val(1), T.Val(999), T.undefined());
- T.CheckCall(T.Val(1), T.Val("x"), T.undefined());
-}
-
-
-TEST(DoWhileStatement) {
- FunctionTester T("(function(a,b) { do { a+=23; } while(a < b) return a; })");
-
- T.CheckCall(T.Val(24), T.Val(1), T.Val(1));
- T.CheckCall(T.Val(24), T.Val(1), T.Val(23));
- T.CheckCall(T.Val(47), T.Val(1), T.Val(25));
- T.CheckCall(T.Val("str23"), T.Val("str"), T.Val("str"));
-}
-
-
-TEST(WhileStatement) {
- FunctionTester T("(function(a,b) { while(a < b) { a+=23; } return a; })");
-
- T.CheckCall(T.Val(1), T.Val(1), T.Val(1));
- T.CheckCall(T.Val(24), T.Val(1), T.Val(23));
- T.CheckCall(T.Val(47), T.Val(1), T.Val(25));
- T.CheckCall(T.Val("str"), T.Val("str"), T.Val("str"));
-}
-
-
-TEST(ForStatement) {
- FunctionTester T("(function(a,b) { for (; a < b; a+=23) {} return a; })");
-
- T.CheckCall(T.Val(1), T.Val(1), T.Val(1));
- T.CheckCall(T.Val(24), T.Val(1), T.Val(23));
- T.CheckCall(T.Val(47), T.Val(1), T.Val(25));
- T.CheckCall(T.Val("str"), T.Val("str"), T.Val("str"));
-}
-
-
-static void TestForIn(const char* code) {
- FunctionTester T(code);
- T.CheckCall(T.undefined(), T.undefined());
- T.CheckCall(T.undefined(), T.null());
- T.CheckCall(T.undefined(), T.NewObject("({})"));
- T.CheckCall(T.undefined(), T.Val(1));
- T.CheckCall(T.Val("2"), T.Val("str"));
- T.CheckCall(T.Val("a"), T.NewObject("({'a' : 1})"));
- T.CheckCall(T.Val("2"), T.NewObject("([1, 2, 3])"));
- T.CheckCall(T.Val("a"), T.NewObject("({'a' : 1, 'b' : 1})"), T.Val("b"));
- T.CheckCall(T.Val("1"), T.NewObject("([1, 2, 3])"), T.Val("2"));
-}
-
-
-TEST(ForInStatement) {
- // Variable assignment.
- TestForIn(
- "(function(a, b) {"
- "var last;"
- "for (var x in a) {"
- " if (b) { delete a[b]; b = undefined; }"
- " last = x;"
- "}"
- "return last;})");
- // Indexed assignment.
- TestForIn(
- "(function(a, b) {"
- "var array = [0, 1, undefined];"
- "for (array[2] in a) {"
- " if (b) { delete a[b]; b = undefined; }"
- "}"
- "return array[2];})");
- // Named assignment.
- TestForIn(
- "(function(a, b) {"
- "var obj = {'a' : undefined};"
- "for (obj.a in a) {"
- " if (b) { delete a[b]; b = undefined; }"
- "}"
- "return obj.a;})");
-}
-
-
-TEST(SwitchStatement) {
- const char* src =
- "(function(a,b) {"
- " var r = '-';"
- " switch (a) {"
- " case 'x' : r += 'X-';"
- " case b + 'b': r += 'B-';"
- " default : r += 'D-';"
- " case 'y' : r += 'Y-';"
- " }"
- " return r;"
- "})";
- FunctionTester T(src);
-
- T.CheckCall(T.Val("-X-B-D-Y-"), T.Val("x"), T.Val("B"));
- T.CheckCall(T.Val("-B-D-Y-"), T.Val("Bb"), T.Val("B"));
- T.CheckCall(T.Val("-D-Y-"), T.Val("z"), T.Val("B"));
- T.CheckCall(T.Val("-Y-"), T.Val("y"), T.Val("B"));
-
- CompileRun("var c = 0; var o = { toString:function(){return c++} };");
- T.CheckCall(T.Val("-D-Y-"), T.Val("1b"), T.NewObject("o"));
- T.CheckCall(T.Val("-B-D-Y-"), T.Val("1b"), T.NewObject("o"));
- T.CheckCall(T.Val("-D-Y-"), T.Val("1b"), T.NewObject("o"));
-}
-
-
-TEST(BlockBreakStatement) {
- FunctionTester T("(function(a,b) { L:{ if (a) break L; b=1; } return b; })");
-
- T.CheckCall(T.Val(7), T.true_value(), T.Val(7));
- T.CheckCall(T.Val(1), T.false_value(), T.Val(7));
-}
-
-
-TEST(BlockReturnStatement) {
- FunctionTester T("(function(a,b) { L:{ if (a) b=1; return b; } })");
-
- T.CheckCall(T.Val(1), T.true_value(), T.Val(7));
- T.CheckCall(T.Val(7), T.false_value(), T.Val(7));
-}
-
-
-TEST(NestedIfConditional) {
- FunctionTester T("(function(a,b) { if (a) { b = (b?b:7) + 1; } return b; })");
-
- T.CheckCall(T.Val(4), T.false_value(), T.Val(4));
- T.CheckCall(T.Val(6), T.true_value(), T.Val(5));
- T.CheckCall(T.Val(8), T.true_value(), T.undefined());
-}
-
-
-TEST(NestedIfLogical) {
- const char* src =
- "(function(a,b) {"
- " if (a || b) { return 1; } else { return 2; }"
- "})";
- FunctionTester T(src);
-
- T.CheckCall(T.Val(1), T.true_value(), T.true_value());
- T.CheckCall(T.Val(1), T.false_value(), T.true_value());
- T.CheckCall(T.Val(1), T.true_value(), T.false_value());
- T.CheckCall(T.Val(2), T.false_value(), T.false_value());
- T.CheckCall(T.Val(1), T.Val(1.0), T.Val(1.0));
- T.CheckCall(T.Val(1), T.Val(0.0), T.Val(1.0));
- T.CheckCall(T.Val(1), T.Val(1.0), T.Val(0.0));
- T.CheckCall(T.Val(2), T.Val(0.0), T.Val(0.0));
-}
-
-
-TEST(NestedIfElseFor) {
- const char* src =
- "(function(a,b) {"
- " if (!a) { return b - 3; } else { for (; a < b; a++); }"
- " return a;"
- "})";
- FunctionTester T(src);
-
- T.CheckCall(T.Val(1), T.false_value(), T.Val(4));
- T.CheckCall(T.Val(2), T.true_value(), T.Val(2));
- T.CheckCall(T.Val(3), T.Val(3), T.Val(1));
-}
-
-
-TEST(NestedWhileWhile) {
- const char* src =
- "(function(a) {"
- " var i = a; while (false) while(false) return i;"
- " return i;"
- "})";
- FunctionTester T(src);
-
- T.CheckCall(T.Val(2.0), T.Val(2.0), T.Val(-1.0));
- T.CheckCall(T.Val(65.0), T.Val(65.0), T.Val(-1.0));
-}
-
-
-TEST(NestedForIf) {
- FunctionTester T("(function(a,b) { for (; a > 1; a--) if (b) return 1; })");
-
- T.CheckCall(T.Val(1), T.Val(3), T.true_value());
- T.CheckCall(T.undefined(), T.Val(2), T.false_value());
- T.CheckCall(T.undefined(), T.Val(1), T.null());
-}
-
-
-TEST(NestedForConditional) {
- FunctionTester T("(function(a,b) { for (; a > 1; a--) return b ? 1 : 2; })");
-
- T.CheckCall(T.Val(1), T.Val(3), T.true_value());
- T.CheckCall(T.Val(2), T.Val(2), T.false_value());
- T.CheckCall(T.undefined(), T.Val(1), T.null());
-}
+++ /dev/null
-// 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/compiler/function-tester.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-TEST(SimpleCall) {
- FunctionTester T("(function(foo,a) { return foo(a); })");
- Handle<JSFunction> foo = T.NewFunction("(function(a) { return a; })");
-
- T.CheckCall(T.Val(3), foo, T.Val(3));
- T.CheckCall(T.Val(3.1), foo, T.Val(3.1));
- T.CheckCall(foo, foo, foo);
- T.CheckCall(T.Val("Abba"), foo, T.Val("Abba"));
-}
-
-
-TEST(SimpleCall2) {
- FunctionTester T("(function(foo,a) { return foo(a); })");
- Handle<JSFunction> foo = T.NewFunction("(function(a) { return a; })");
- T.Compile(foo);
-
- T.CheckCall(T.Val(3), foo, T.Val(3));
- T.CheckCall(T.Val(3.1), foo, T.Val(3.1));
- T.CheckCall(foo, foo, foo);
- T.CheckCall(T.Val("Abba"), foo, T.Val("Abba"));
-}
-
-
-TEST(ConstCall) {
- FunctionTester T("(function(foo,a) { return foo(a,3); })");
- Handle<JSFunction> foo = T.NewFunction("(function(a,b) { return a + b; })");
- T.Compile(foo);
-
- T.CheckCall(T.Val(6), foo, T.Val(3));
- T.CheckCall(T.Val(6.1), foo, T.Val(3.1));
- T.CheckCall(T.Val("function (a,b) { return a + b; }3"), foo, foo);
- T.CheckCall(T.Val("Abba3"), foo, T.Val("Abba"));
-}
-
-
-TEST(ConstCall2) {
- FunctionTester T("(function(foo,a) { return foo(a,\"3\"); })");
- Handle<JSFunction> foo = T.NewFunction("(function(a,b) { return a + b; })");
- T.Compile(foo);
-
- T.CheckCall(T.Val("33"), foo, T.Val(3));
- T.CheckCall(T.Val("3.13"), foo, T.Val(3.1));
- T.CheckCall(T.Val("function (a,b) { return a + b; }3"), foo, foo);
- T.CheckCall(T.Val("Abba3"), foo, T.Val("Abba"));
-}
-
-
-TEST(PropertyNamedCall) {
- FunctionTester T("(function(a,b) { return a.foo(b,23); })");
- CompileRun("function foo(y,z) { return this.x + y + z; }");
-
- T.CheckCall(T.Val(32), T.NewObject("({ foo:foo, x:4 })"), T.Val(5));
- T.CheckCall(T.Val("xy23"), T.NewObject("({ foo:foo, x:'x' })"), T.Val("y"));
- T.CheckCall(T.nan(), T.NewObject("({ foo:foo, y:0 })"), T.Val(3));
-}
-
-
-TEST(PropertyKeyedCall) {
- FunctionTester T("(function(a,b) { var f = 'foo'; return a[f](b,23); })");
- CompileRun("function foo(y,z) { return this.x + y + z; }");
-
- T.CheckCall(T.Val(32), T.NewObject("({ foo:foo, x:4 })"), T.Val(5));
- T.CheckCall(T.Val("xy23"), T.NewObject("({ foo:foo, x:'x' })"), T.Val("y"));
- T.CheckCall(T.nan(), T.NewObject("({ foo:foo, y:0 })"), T.Val(3));
-}
-
-
-TEST(GlobalCall) {
- FunctionTester T("(function(a,b) { return foo(a,b); })");
- CompileRun("function foo(a,b) { return a + b + this.c; }");
- CompileRun("var c = 23;");
-
- T.CheckCall(T.Val(32), T.Val(4), T.Val(5));
- T.CheckCall(T.Val("xy23"), T.Val("x"), T.Val("y"));
- T.CheckCall(T.nan(), T.undefined(), T.Val(3));
-}
-
-
-TEST(LookupCall) {
- FunctionTester T("(function(a,b) { with (a) { return foo(a,b); } })");
-
- CompileRun("function f1(a,b) { return a.val + b; }");
- T.CheckCall(T.Val(5), T.NewObject("({ foo:f1, val:2 })"), T.Val(3));
- T.CheckCall(T.Val("xy"), T.NewObject("({ foo:f1, val:'x' })"), T.Val("y"));
-
- CompileRun("function f2(a,b) { return this.val + b; }");
- T.CheckCall(T.Val(9), T.NewObject("({ foo:f2, val:4 })"), T.Val(5));
- T.CheckCall(T.Val("xy"), T.NewObject("({ foo:f2, val:'x' })"), T.Val("y"));
-}
-
-
-TEST(MismatchCallTooFew) {
- FunctionTester T("(function(a,b) { return foo(a,b); })");
- CompileRun("function foo(a,b,c) { return a + b + c; }");
-
- T.CheckCall(T.nan(), T.Val(23), T.Val(42));
- T.CheckCall(T.nan(), T.Val(4.2), T.Val(2.3));
- T.CheckCall(T.Val("abundefined"), T.Val("a"), T.Val("b"));
-}
-
-
-TEST(MismatchCallTooMany) {
- FunctionTester T("(function(a,b) { return foo(a,b); })");
- CompileRun("function foo(a) { return a; }");
-
- T.CheckCall(T.Val(23), T.Val(23), T.Val(42));
- T.CheckCall(T.Val(4.2), T.Val(4.2), T.Val(2.3));
- T.CheckCall(T.Val("a"), T.Val("a"), T.Val("b"));
-}
-
-
-TEST(ConstructorCall) {
- FunctionTester T("(function(a,b) { return new foo(a,b).value; })");
- CompileRun("function foo(a,b) { return { value: a + b + this.c }; }");
- CompileRun("foo.prototype.c = 23;");
-
- T.CheckCall(T.Val(32), T.Val(4), T.Val(5));
- T.CheckCall(T.Val("xy23"), T.Val("x"), T.Val("y"));
- T.CheckCall(T.nan(), T.undefined(), T.Val(3));
-}
-
-
-// TODO(titzer): factor these out into test-runtime-calls.cc
-TEST(RuntimeCallCPP1) {
- FLAG_allow_natives_syntax = true;
- FunctionTester T("(function(a) { return %ToBool(a); })");
-
- T.CheckCall(T.true_value(), T.Val(23), T.undefined());
- T.CheckCall(T.true_value(), T.Val(4.2), T.undefined());
- T.CheckCall(T.true_value(), T.Val("str"), T.undefined());
- T.CheckCall(T.true_value(), T.true_value(), T.undefined());
- T.CheckCall(T.false_value(), T.false_value(), T.undefined());
- T.CheckCall(T.false_value(), T.undefined(), T.undefined());
- T.CheckCall(T.false_value(), T.Val(0.0), T.undefined());
-}
-
-
-TEST(RuntimeCallCPP2) {
- FLAG_allow_natives_syntax = true;
- FunctionTester T("(function(a,b) { return %NumberAdd(a, b); })");
-
- T.CheckCall(T.Val(65), T.Val(42), T.Val(23));
- T.CheckCall(T.Val(19), T.Val(42), T.Val(-23));
- T.CheckCall(T.Val(6.5), T.Val(4.2), T.Val(2.3));
-}
-
-
-TEST(RuntimeCallJS) {
- FLAG_allow_natives_syntax = true;
- FunctionTester T("(function(a) { return %ToString(a); })");
-
- T.CheckCall(T.Val("23"), T.Val(23), T.undefined());
- T.CheckCall(T.Val("4.2"), T.Val(4.2), T.undefined());
- T.CheckCall(T.Val("str"), T.Val("str"), T.undefined());
- T.CheckCall(T.Val("true"), T.true_value(), T.undefined());
- T.CheckCall(T.Val("false"), T.false_value(), T.undefined());
- T.CheckCall(T.Val("undefined"), T.undefined(), T.undefined());
-}
-
-
-TEST(RuntimeCallInline) {
- FLAG_allow_natives_syntax = true;
- FunctionTester T("(function(a) { return %_IsObject(a); })");
-
- T.CheckCall(T.false_value(), T.Val(23), T.undefined());
- T.CheckCall(T.false_value(), T.Val(4.2), T.undefined());
- T.CheckCall(T.false_value(), T.Val("str"), T.undefined());
- T.CheckCall(T.false_value(), T.true_value(), T.undefined());
- T.CheckCall(T.false_value(), T.false_value(), T.undefined());
- T.CheckCall(T.false_value(), T.undefined(), T.undefined());
- T.CheckCall(T.true_value(), T.NewObject("({})"), T.undefined());
- T.CheckCall(T.true_value(), T.NewObject("([])"), T.undefined());
-}
-
-
-TEST(RuntimeCallBooleanize) {
- // TODO(turbofan): %Booleanize will disappear, don't hesitate to remove this
- // test case, two-argument case is covered by the above test already.
- FLAG_allow_natives_syntax = true;
- FunctionTester T("(function(a,b) { return %Booleanize(a, b); })");
-
- T.CheckCall(T.true_value(), T.Val(-1), T.Val(Token::LT));
- T.CheckCall(T.false_value(), T.Val(-1), T.Val(Token::EQ));
- T.CheckCall(T.false_value(), T.Val(-1), T.Val(Token::GT));
-
- T.CheckCall(T.false_value(), T.Val(0.0), T.Val(Token::LT));
- T.CheckCall(T.true_value(), T.Val(0.0), T.Val(Token::EQ));
- T.CheckCall(T.false_value(), T.Val(0.0), T.Val(Token::GT));
-
- T.CheckCall(T.false_value(), T.Val(1), T.Val(Token::LT));
- T.CheckCall(T.false_value(), T.Val(1), T.Val(Token::EQ));
- T.CheckCall(T.true_value(), T.Val(1), T.Val(Token::GT));
-}
-
-
-TEST(EvalCall) {
- FunctionTester T("(function(a,b) { return eval(a); })");
- Handle<JSObject> g(T.function->context()->global_object()->global_proxy());
-
- T.CheckCall(T.Val(23), T.Val("17 + 6"), T.undefined());
- T.CheckCall(T.Val("'Y'; a"), T.Val("'Y'; a"), T.Val("b-val"));
- T.CheckCall(T.Val("b-val"), T.Val("'Y'; b"), T.Val("b-val"));
- T.CheckCall(g, T.Val("this"), T.undefined());
- T.CheckCall(g, T.Val("'use strict'; this"), T.undefined());
-
- CompileRun("eval = function(x) { return x; }");
- T.CheckCall(T.Val("17 + 6"), T.Val("17 + 6"), T.undefined());
-
- CompileRun("eval = function(x) { return this; }");
- T.CheckCall(g, T.Val("17 + 6"), T.undefined());
-
- CompileRun("eval = function(x) { 'use strict'; return this; }");
- T.CheckCall(T.undefined(), T.Val("17 + 6"), T.undefined());
-}
-
-
-TEST(ReceiverPatching) {
- // TODO(turbofan): Note that this test only checks that the function prologue
- // patches an undefined receiver to the global receiver. If this starts to
- // fail once we fix the calling protocol, just remove this test.
- FunctionTester T("(function(a) { return this; })");
- Handle<JSObject> g(T.function->context()->global_object()->global_proxy());
- T.CheckCall(g, T.undefined());
-}
+++ /dev/null
-// 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/compiler/function-tester.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-TEST(Throw) {
- FunctionTester T("(function(a,b) { if (a) { throw b; } else { return b; }})");
-
- T.CheckThrows(T.true_value(), T.NewObject("new Error"));
- T.CheckCall(T.Val(23), T.false_value(), T.Val(23));
-}
-
-
-TEST(ThrowSourcePosition) {
- static const char* src =
- "(function(a, b) { \n"
- " if (a == 1) throw 1; \n"
- " if (a == 2) {throw 2} \n"
- " if (a == 3) {0;throw 3}\n"
- " throw 4; \n"
- "}) ";
- FunctionTester T(src);
- v8::Handle<v8::Message> message;
-
- message = T.CheckThrowsReturnMessage(T.Val(1), T.undefined());
- CHECK(!message.IsEmpty());
- CHECK_EQ(2, message->GetLineNumber());
- CHECK_EQ(40, message->GetStartPosition());
-
- message = T.CheckThrowsReturnMessage(T.Val(2), T.undefined());
- CHECK(!message.IsEmpty());
- CHECK_EQ(3, message->GetLineNumber());
- CHECK_EQ(67, message->GetStartPosition());
-
- message = T.CheckThrowsReturnMessage(T.Val(3), T.undefined());
- CHECK(!message.IsEmpty());
- CHECK_EQ(4, message->GetLineNumber());
- CHECK_EQ(95, message->GetStartPosition());
-}
+++ /dev/null
-// 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/compiler/function-tester.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-TEST(BinopAdd) {
- FunctionTester T("(function(a,b) { return a + b; })");
-
- T.CheckCall(3, 1, 2);
- T.CheckCall(-11, -2, -9);
- T.CheckCall(-11, -1.5, -9.5);
- T.CheckCall(T.Val("AB"), T.Val("A"), T.Val("B"));
- T.CheckCall(T.Val("A11"), T.Val("A"), T.Val(11));
- T.CheckCall(T.Val("12B"), T.Val(12), T.Val("B"));
- T.CheckCall(T.Val("38"), T.Val("3"), T.Val("8"));
- T.CheckCall(T.Val("31"), T.Val("3"), T.NewObject("([1])"));
- T.CheckCall(T.Val("3[object Object]"), T.Val("3"), T.NewObject("({})"));
-}
-
-
-TEST(BinopSubtract) {
- FunctionTester T("(function(a,b) { return a - b; })");
-
- T.CheckCall(3, 4, 1);
- T.CheckCall(3.0, 4.5, 1.5);
- T.CheckCall(T.Val(-9), T.Val("0"), T.Val(9));
- T.CheckCall(T.Val(-9), T.Val(0.0), T.Val("9"));
- T.CheckCall(T.Val(1), T.Val("3"), T.Val("2"));
- T.CheckCall(T.nan(), T.Val("3"), T.Val("B"));
- T.CheckCall(T.Val(2), T.Val("3"), T.NewObject("([1])"));
- T.CheckCall(T.nan(), T.Val("3"), T.NewObject("({})"));
-}
-
-
-TEST(BinopMultiply) {
- FunctionTester T("(function(a,b) { return a * b; })");
-
- T.CheckCall(6, 3, 2);
- T.CheckCall(4.5, 2.0, 2.25);
- T.CheckCall(T.Val(6), T.Val("3"), T.Val(2));
- T.CheckCall(T.Val(4.5), T.Val(2.0), T.Val("2.25"));
- T.CheckCall(T.Val(6), T.Val("3"), T.Val("2"));
- T.CheckCall(T.nan(), T.Val("3"), T.Val("B"));
- T.CheckCall(T.Val(3), T.Val("3"), T.NewObject("([1])"));
- T.CheckCall(T.nan(), T.Val("3"), T.NewObject("({})"));
-}
-
-
-TEST(BinopDivide) {
- FunctionTester T("(function(a,b) { return a / b; })");
-
- T.CheckCall(2, 8, 4);
- T.CheckCall(2.1, 8.4, 4);
- T.CheckCall(V8_INFINITY, 8, 0);
- T.CheckCall(-V8_INFINITY, -8, 0);
- T.CheckCall(T.infinity(), T.Val(8), T.Val("0"));
- T.CheckCall(T.minus_infinity(), T.Val("-8"), T.Val(0.0));
- T.CheckCall(T.Val(1.5), T.Val("3"), T.Val("2"));
- T.CheckCall(T.nan(), T.Val("3"), T.Val("B"));
- T.CheckCall(T.Val(1.5), T.Val("3"), T.NewObject("([2])"));
- T.CheckCall(T.nan(), T.Val("3"), T.NewObject("({})"));
-}
-
-
-TEST(BinopModulus) {
- FunctionTester T("(function(a,b) { return a % b; })");
-
- T.CheckCall(3, 8, 5);
- T.CheckCall(T.Val(3), T.Val("8"), T.Val(5));
- T.CheckCall(T.Val(3), T.Val(8), T.Val("5"));
- T.CheckCall(T.Val(1), T.Val("3"), T.Val("2"));
- T.CheckCall(T.nan(), T.Val("3"), T.Val("B"));
- T.CheckCall(T.Val(1), T.Val("3"), T.NewObject("([2])"));
- T.CheckCall(T.nan(), T.Val("3"), T.NewObject("({})"));
-}
-
-
-TEST(BinopShiftLeft) {
- FunctionTester T("(function(a,b) { return a << b; })");
-
- T.CheckCall(4, 2, 1);
- T.CheckCall(T.Val(4), T.Val("2"), T.Val(1));
- T.CheckCall(T.Val(4), T.Val(2), T.Val("1"));
-}
-
-
-TEST(BinopShiftRight) {
- FunctionTester T("(function(a,b) { return a >> b; })");
-
- T.CheckCall(4, 8, 1);
- T.CheckCall(-4, -8, 1);
- T.CheckCall(T.Val(4), T.Val("8"), T.Val(1));
- T.CheckCall(T.Val(4), T.Val(8), T.Val("1"));
-}
-
-
-TEST(BinopShiftRightLogical) {
- FunctionTester T("(function(a,b) { return a >>> b; })");
-
- T.CheckCall(4, 8, 1);
- T.CheckCall(0x7ffffffc, -8, 1);
- T.CheckCall(T.Val(4), T.Val("8"), T.Val(1));
- T.CheckCall(T.Val(4), T.Val(8), T.Val("1"));
-}
-
-
-TEST(BinopAnd) {
- FunctionTester T("(function(a,b) { return a & b; })");
-
- T.CheckCall(7, 7, 15);
- T.CheckCall(7, 15, 7);
- T.CheckCall(T.Val(7), T.Val("15"), T.Val(7));
- T.CheckCall(T.Val(7), T.Val(15), T.Val("7"));
-}
-
-
-TEST(BinopOr) {
- FunctionTester T("(function(a,b) { return a | b; })");
-
- T.CheckCall(6, 4, 2);
- T.CheckCall(6, 2, 4);
- T.CheckCall(T.Val(6), T.Val("2"), T.Val(4));
- T.CheckCall(T.Val(6), T.Val(2), T.Val("4"));
-}
-
-
-TEST(BinopXor) {
- FunctionTester T("(function(a,b) { return a ^ b; })");
-
- T.CheckCall(7, 15, 8);
- T.CheckCall(7, 8, 15);
- T.CheckCall(T.Val(7), T.Val("8"), T.Val(15));
- T.CheckCall(T.Val(7), T.Val(8), T.Val("15"));
-}
-
-
-TEST(BinopStrictEqual) {
- FunctionTester T("(function(a,b) { return a === b; })");
-
- T.CheckTrue(7, 7);
- T.CheckFalse(7, 8);
- T.CheckTrue(7.1, 7.1);
- T.CheckFalse(7.1, 8.1);
-
- T.CheckTrue(T.Val("7.1"), T.Val("7.1"));
- T.CheckFalse(T.Val(7.1), T.Val("7.1"));
- T.CheckFalse(T.Val(7), T.undefined());
- T.CheckFalse(T.undefined(), T.Val(7));
-
- CompileRun("var o = { desc : 'I am a singleton' }");
- T.CheckFalse(T.NewObject("([1])"), T.NewObject("([1])"));
- T.CheckFalse(T.NewObject("({})"), T.NewObject("({})"));
- T.CheckTrue(T.NewObject("(o)"), T.NewObject("(o)"));
-}
-
-
-TEST(BinopEqual) {
- FunctionTester T("(function(a,b) { return a == b; })");
-
- T.CheckTrue(7, 7);
- T.CheckFalse(7, 8);
- T.CheckTrue(7.1, 7.1);
- T.CheckFalse(7.1, 8.1);
-
- T.CheckTrue(T.Val("7.1"), T.Val("7.1"));
- T.CheckTrue(T.Val(7.1), T.Val("7.1"));
-
- CompileRun("var o = { desc : 'I am a singleton' }");
- T.CheckFalse(T.NewObject("([1])"), T.NewObject("([1])"));
- T.CheckFalse(T.NewObject("({})"), T.NewObject("({})"));
- T.CheckTrue(T.NewObject("(o)"), T.NewObject("(o)"));
-}
-
-
-TEST(BinopNotEqual) {
- FunctionTester T("(function(a,b) { return a != b; })");
-
- T.CheckFalse(7, 7);
- T.CheckTrue(7, 8);
- T.CheckFalse(7.1, 7.1);
- T.CheckTrue(7.1, 8.1);
-
- T.CheckFalse(T.Val("7.1"), T.Val("7.1"));
- T.CheckFalse(T.Val(7.1), T.Val("7.1"));
-
- CompileRun("var o = { desc : 'I am a singleton' }");
- T.CheckTrue(T.NewObject("([1])"), T.NewObject("([1])"));
- T.CheckTrue(T.NewObject("({})"), T.NewObject("({})"));
- T.CheckFalse(T.NewObject("(o)"), T.NewObject("(o)"));
-}
-
-
-TEST(BinopLessThan) {
- FunctionTester T("(function(a,b) { return a < b; })");
-
- T.CheckTrue(7, 8);
- T.CheckFalse(8, 7);
- T.CheckTrue(-8.1, -8);
- T.CheckFalse(-8, -8.1);
- T.CheckFalse(0.111, 0.111);
-
- T.CheckFalse(T.Val("7.1"), T.Val("7.1"));
- T.CheckFalse(T.Val(7.1), T.Val("6.1"));
- T.CheckFalse(T.Val(7.1), T.Val("7.1"));
- T.CheckTrue(T.Val(7.1), T.Val("8.1"));
-}
-
-
-TEST(BinopLessThanEqual) {
- FunctionTester T("(function(a,b) { return a <= b; })");
-
- T.CheckTrue(7, 8);
- T.CheckFalse(8, 7);
- T.CheckTrue(-8.1, -8);
- T.CheckFalse(-8, -8.1);
- T.CheckTrue(0.111, 0.111);
-
- T.CheckTrue(T.Val("7.1"), T.Val("7.1"));
- T.CheckFalse(T.Val(7.1), T.Val("6.1"));
- T.CheckTrue(T.Val(7.1), T.Val("7.1"));
- T.CheckTrue(T.Val(7.1), T.Val("8.1"));
-}
-
-
-TEST(BinopGreaterThan) {
- FunctionTester T("(function(a,b) { return a > b; })");
-
- T.CheckFalse(7, 8);
- T.CheckTrue(8, 7);
- T.CheckFalse(-8.1, -8);
- T.CheckTrue(-8, -8.1);
- T.CheckFalse(0.111, 0.111);
-
- T.CheckFalse(T.Val("7.1"), T.Val("7.1"));
- T.CheckTrue(T.Val(7.1), T.Val("6.1"));
- T.CheckFalse(T.Val(7.1), T.Val("7.1"));
- T.CheckFalse(T.Val(7.1), T.Val("8.1"));
-}
-
-
-TEST(BinopGreaterThanOrEqual) {
- FunctionTester T("(function(a,b) { return a >= b; })");
-
- T.CheckFalse(7, 8);
- T.CheckTrue(8, 7);
- T.CheckFalse(-8.1, -8);
- T.CheckTrue(-8, -8.1);
- T.CheckTrue(0.111, 0.111);
-
- T.CheckTrue(T.Val("7.1"), T.Val("7.1"));
- T.CheckTrue(T.Val(7.1), T.Val("6.1"));
- T.CheckTrue(T.Val(7.1), T.Val("7.1"));
- T.CheckFalse(T.Val(7.1), T.Val("8.1"));
-}
-
-
-TEST(BinopIn) {
- FunctionTester T("(function(a,b) { return a in b; })");
-
- T.CheckTrue(T.Val("x"), T.NewObject("({x:23})"));
- T.CheckFalse(T.Val("y"), T.NewObject("({x:42})"));
- T.CheckFalse(T.Val(123), T.NewObject("({x:65})"));
- T.CheckTrue(T.Val(1), T.NewObject("([1,2,3])"));
-}
-
-
-TEST(BinopInstanceOf) {
- FunctionTester T("(function(a,b) { return a instanceof b; })");
-
- T.CheckTrue(T.NewObject("(new Number(23))"), T.NewObject("Number"));
- T.CheckFalse(T.NewObject("(new Number(23))"), T.NewObject("String"));
- T.CheckFalse(T.NewObject("(new String('a'))"), T.NewObject("Number"));
- T.CheckTrue(T.NewObject("(new String('b'))"), T.NewObject("String"));
- T.CheckFalse(T.Val(1), T.NewObject("Number"));
- T.CheckFalse(T.Val("abc"), T.NewObject("String"));
-
- CompileRun("var bound = (function() {}).bind(undefined)");
- T.CheckTrue(T.NewObject("(new bound())"), T.NewObject("bound"));
- T.CheckTrue(T.NewObject("(new bound())"), T.NewObject("Object"));
- T.CheckFalse(T.NewObject("(new bound())"), T.NewObject("Number"));
-}
-
-
-TEST(UnopNot) {
- FunctionTester T("(function(a) { return !a; })");
-
- T.CheckCall(T.true_value(), T.false_value(), T.undefined());
- T.CheckCall(T.false_value(), T.true_value(), T.undefined());
- T.CheckCall(T.true_value(), T.Val(0.0), T.undefined());
- T.CheckCall(T.false_value(), T.Val(123), T.undefined());
- T.CheckCall(T.false_value(), T.Val("x"), T.undefined());
- T.CheckCall(T.true_value(), T.undefined(), T.undefined());
- T.CheckCall(T.true_value(), T.nan(), T.undefined());
-}
-
-
-TEST(UnopCountPost) {
- FunctionTester T("(function(a) { return a++; })");
-
- T.CheckCall(T.Val(0.0), T.Val(0.0), T.undefined());
- T.CheckCall(T.Val(2.3), T.Val(2.3), T.undefined());
- T.CheckCall(T.Val(123), T.Val(123), T.undefined());
- T.CheckCall(T.Val(7), T.Val("7"), T.undefined());
- T.CheckCall(T.nan(), T.Val("x"), T.undefined());
- T.CheckCall(T.nan(), T.undefined(), T.undefined());
- T.CheckCall(T.Val(1.0), T.true_value(), T.undefined());
- T.CheckCall(T.Val(0.0), T.false_value(), T.undefined());
- T.CheckCall(T.nan(), T.nan(), T.undefined());
-}
-
-
-TEST(UnopCountPre) {
- FunctionTester T("(function(a) { return ++a; })");
-
- T.CheckCall(T.Val(1.0), T.Val(0.0), T.undefined());
- T.CheckCall(T.Val(3.3), T.Val(2.3), T.undefined());
- T.CheckCall(T.Val(124), T.Val(123), T.undefined());
- T.CheckCall(T.Val(8), T.Val("7"), T.undefined());
- T.CheckCall(T.nan(), T.Val("x"), T.undefined());
- T.CheckCall(T.nan(), T.undefined(), T.undefined());
- T.CheckCall(T.Val(2.0), T.true_value(), T.undefined());
- T.CheckCall(T.Val(1.0), T.false_value(), T.undefined());
- T.CheckCall(T.nan(), T.nan(), T.undefined());
-}
-
-
-TEST(PropertyNamedLoad) {
- FunctionTester T("(function(a,b) { return a.x; })");
-
- T.CheckCall(T.Val(23), T.NewObject("({x:23})"), T.undefined());
- T.CheckCall(T.undefined(), T.NewObject("({y:23})"), T.undefined());
-}
-
-
-TEST(PropertyKeyedLoad) {
- FunctionTester T("(function(a,b) { return a[b]; })");
-
- T.CheckCall(T.Val(23), T.NewObject("({x:23})"), T.Val("x"));
- T.CheckCall(T.Val(42), T.NewObject("([23,42,65])"), T.Val(1));
- T.CheckCall(T.undefined(), T.NewObject("({x:23})"), T.Val("y"));
- T.CheckCall(T.undefined(), T.NewObject("([23,42,65])"), T.Val(4));
-}
-
-
-TEST(PropertyNamedStore) {
- FunctionTester T("(function(a) { a.x = 7; return a.x; })");
-
- T.CheckCall(T.Val(7), T.NewObject("({})"), T.undefined());
- T.CheckCall(T.Val(7), T.NewObject("({x:23})"), T.undefined());
-}
-
-
-TEST(PropertyKeyedStore) {
- FunctionTester T("(function(a,b) { a[b] = 7; return a.x; })");
-
- T.CheckCall(T.Val(7), T.NewObject("({})"), T.Val("x"));
- T.CheckCall(T.Val(7), T.NewObject("({x:23})"), T.Val("x"));
- T.CheckCall(T.Val(9), T.NewObject("({x:9})"), T.Val("y"));
-}
-
-
-TEST(PropertyNamedDelete) {
- FunctionTester T("(function(a) { return delete a.x; })");
-
- CompileRun("var o = Object.create({}, { x: { value:23 } });");
- T.CheckTrue(T.NewObject("({x:42})"), T.undefined());
- T.CheckTrue(T.NewObject("({})"), T.undefined());
- T.CheckFalse(T.NewObject("(o)"), T.undefined());
-}
-
-
-TEST(PropertyKeyedDelete) {
- FunctionTester T("(function(a, b) { return delete a[b]; })");
-
- CompileRun("function getX() { return 'x'; }");
- CompileRun("var o = Object.create({}, { x: { value:23 } });");
- T.CheckTrue(T.NewObject("({x:42})"), T.Val("x"));
- T.CheckFalse(T.NewObject("(o)"), T.Val("x"));
- T.CheckFalse(T.NewObject("(o)"), T.NewObject("({toString:getX})"));
-}
-
-
-TEST(GlobalLoad) {
- FunctionTester T("(function() { return g; })");
-
- T.CheckThrows(T.undefined(), T.undefined());
- CompileRun("var g = 23;");
- T.CheckCall(T.Val(23));
-}
-
-
-TEST(GlobalStoreSloppy) {
- FunctionTester T("(function(a,b) { g = a + b; return g; })");
-
- T.CheckCall(T.Val(33), T.Val(22), T.Val(11));
- CompileRun("delete g");
- CompileRun("const g = 23");
- T.CheckCall(T.Val(23), T.Val(55), T.Val(44));
-}
-
-
-TEST(GlobalStoreStrict) {
- FunctionTester T("(function(a,b) { 'use strict'; g = a + b; return g; })");
-
- T.CheckThrows(T.Val(22), T.Val(11));
- CompileRun("var g = 'a global variable';");
- T.CheckCall(T.Val(33), T.Val(22), T.Val(11));
-}
-
-
-TEST(ContextLoad) {
- FunctionTester T("(function(a,b) { (function(){a}); return a + b; })");
-
- T.CheckCall(T.Val(65), T.Val(23), T.Val(42));
- T.CheckCall(T.Val("ab"), T.Val("a"), T.Val("b"));
-}
-
-
-TEST(ContextStore) {
- FunctionTester T("(function(a,b) { (function(){x}); var x = a; return x; })");
-
- T.CheckCall(T.Val(23), T.Val(23), T.undefined());
- T.CheckCall(T.Val("a"), T.Val("a"), T.undefined());
-}
-
-
-TEST(LookupLoad) {
- FunctionTester T("(function(a,b) { with(a) { return x + b; } })");
-
- T.CheckCall(T.Val(24), T.NewObject("({x:23})"), T.Val(1));
- T.CheckCall(T.Val(32), T.NewObject("({x:23, b:9})"), T.Val(2));
- T.CheckCall(T.Val(45), T.NewObject("({__proto__:{x:42}})"), T.Val(3));
- T.CheckCall(T.Val(69), T.NewObject("({get x() { return 65; }})"), T.Val(4));
-}
-
-
-TEST(LookupStore) {
- FunctionTester T("(function(a,b) { var x; with(a) { x = b; } return x; })");
-
- T.CheckCall(T.undefined(), T.NewObject("({x:23})"), T.Val(1));
- T.CheckCall(T.Val(2), T.NewObject("({y:23})"), T.Val(2));
- T.CheckCall(T.Val(23), T.NewObject("({b:23})"), T.Val(3));
- T.CheckCall(T.undefined(), T.NewObject("({__proto__:{x:42}})"), T.Val(4));
-}
-
-
-TEST(BlockLoadStore) {
- FLAG_harmony_scoping = true;
- FunctionTester T("(function(a) { 'use strict'; { let x = a+a; return x; }})");
-
- T.CheckCall(T.Val(46), T.Val(23));
- T.CheckCall(T.Val("aa"), T.Val("a"));
-}
-
-
-TEST(BlockLoadStoreNested) {
- FLAG_harmony_scoping = true;
- const char* src =
- "(function(a,b) {"
- "'use strict';"
- "{ let x = a, y = a;"
- " { let y = b;"
- " return x + y;"
- " }"
- "}})";
- FunctionTester T(src);
-
- T.CheckCall(T.Val(65), T.Val(23), T.Val(42));
- T.CheckCall(T.Val("ab"), T.Val("a"), T.Val("b"));
-}
-
-
-TEST(ObjectLiteralComputed) {
- FunctionTester T("(function(a,b) { o = { x:a+b }; return o.x; })");
-
- T.CheckCall(T.Val(65), T.Val(23), T.Val(42));
- T.CheckCall(T.Val("ab"), T.Val("a"), T.Val("b"));
-}
-
-
-TEST(ObjectLiteralNonString) {
- FunctionTester T("(function(a,b) { o = { 7:a+b }; return o[7]; })");
-
- T.CheckCall(T.Val(65), T.Val(23), T.Val(42));
- T.CheckCall(T.Val("ab"), T.Val("a"), T.Val("b"));
-}
-
-
-TEST(ObjectLiteralPrototype) {
- FunctionTester T("(function(a) { o = { __proto__:a }; return o.x; })");
-
- T.CheckCall(T.Val(23), T.NewObject("({x:23})"), T.undefined());
- T.CheckCall(T.undefined(), T.NewObject("({y:42})"), T.undefined());
-}
-
-
-TEST(ObjectLiteralGetter) {
- FunctionTester T("(function(a) { o = { get x() {return a} }; return o.x; })");
-
- T.CheckCall(T.Val(23), T.Val(23), T.undefined());
- T.CheckCall(T.Val("x"), T.Val("x"), T.undefined());
-}
-
-
-TEST(ArrayLiteral) {
- FunctionTester T("(function(a,b) { o = [1, a + b, 3]; return o[1]; })");
-
- T.CheckCall(T.Val(65), T.Val(23), T.Val(42));
- T.CheckCall(T.Val("ab"), T.Val("a"), T.Val("b"));
-}
-
-
-TEST(RegExpLiteral) {
- FunctionTester T("(function(a) { o = /b/; return o.test(a); })");
-
- T.CheckTrue(T.Val("abc"));
- T.CheckFalse(T.Val("xyz"));
-}
+++ /dev/null
-// 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 <limits>
-#include "src/v8.h"
-
-#include "test/cctest/cctest.h"
-#include "test/cctest/compiler/codegen-tester.h"
-#include "test/cctest/compiler/value-helper.h"
-
-#if V8_TURBOFAN_TARGET
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-typedef RawMachineAssembler::Label MLabel;
-
-TEST(RunInt32Add) {
- RawMachineAssemblerTester<int32_t> m;
- Node* add = m.Int32Add(m.Int32Constant(0), m.Int32Constant(1));
- m.Return(add);
- CHECK_EQ(1, m.Call());
-}
-
-
-static Node* Int32Input(RawMachineAssemblerTester<int32_t>* m, int index) {
- switch (index) {
- case 0:
- return m->Parameter(0);
- case 1:
- return m->Parameter(1);
- case 2:
- return m->Int32Constant(0);
- case 3:
- return m->Int32Constant(1);
- case 4:
- return m->Int32Constant(-1);
- case 5:
- return m->Int32Constant(0xff);
- case 6:
- return m->Int32Constant(0x01234567);
- case 7:
- return m->Load(kMachineWord32, m->PointerConstant(NULL));
- default:
- return NULL;
- }
-}
-
-
-TEST(CodeGenInt32Binop) {
- RawMachineAssemblerTester<void> m;
-
- Operator* ops[] = {
- m.machine()->Word32And(), m.machine()->Word32Or(),
- m.machine()->Word32Xor(), m.machine()->Word32Shl(),
- m.machine()->Word32Shr(), m.machine()->Word32Sar(),
- m.machine()->Word32Equal(), m.machine()->Int32Add(),
- m.machine()->Int32Sub(), m.machine()->Int32Mul(),
- m.machine()->Int32Div(), m.machine()->Int32UDiv(),
- m.machine()->Int32Mod(), m.machine()->Int32UMod(),
- m.machine()->Int32LessThan(), m.machine()->Int32LessThanOrEqual(),
- m.machine()->Uint32LessThan(), m.machine()->Uint32LessThanOrEqual(),
- NULL};
-
- for (int i = 0; ops[i] != NULL; i++) {
- for (int j = 0; j < 8; j++) {
- for (int k = 0; k < 8; k++) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
- Node* a = Int32Input(&m, j);
- Node* b = Int32Input(&m, k);
- m.Return(m.NewNode(ops[i], a, b));
- m.GenerateCode();
- }
- }
- }
-}
-
-
-TEST(RunGoto) {
- RawMachineAssemblerTester<int32_t> m;
- int constant = 99999;
-
- MLabel next;
- m.Goto(&next);
- m.Bind(&next);
- m.Return(m.Int32Constant(constant));
-
- CHECK_EQ(constant, m.Call());
-}
-
-
-TEST(RunGotoMultiple) {
- RawMachineAssemblerTester<int32_t> m;
- int constant = 9999977;
-
- MLabel labels[10];
- for (size_t i = 0; i < ARRAY_SIZE(labels); i++) {
- m.Goto(&labels[i]);
- m.Bind(&labels[i]);
- }
- m.Return(m.Int32Constant(constant));
-
- CHECK_EQ(constant, m.Call());
-}
-
-
-TEST(RunBranch) {
- RawMachineAssemblerTester<int32_t> m;
- int constant = 999777;
-
- MLabel blocka, blockb;
- m.Branch(m.Int32Constant(0), &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(0 - constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(constant));
-
- CHECK_EQ(constant, m.Call());
-}
-
-
-TEST(RunRedundantBranch1) {
- RawMachineAssemblerTester<int32_t> m;
- int constant = 944777;
-
- MLabel blocka;
- m.Branch(m.Int32Constant(0), &blocka, &blocka);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
-
- CHECK_EQ(constant, m.Call());
-}
-
-
-TEST(RunRedundantBranch2) {
- RawMachineAssemblerTester<int32_t> m;
- int constant = 955777;
-
- MLabel blocka, blockb;
- m.Branch(m.Int32Constant(0), &blocka, &blocka);
- m.Bind(&blockb);
- m.Goto(&blocka);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
-
- CHECK_EQ(constant, m.Call());
-}
-
-
-TEST(RunRedundantBranch3) {
- RawMachineAssemblerTester<int32_t> m;
- int constant = 966777;
-
- MLabel blocka, blockb, blockc;
- m.Branch(m.Int32Constant(0), &blocka, &blockc);
- m.Bind(&blocka);
- m.Branch(m.Int32Constant(0), &blockb, &blockb);
- m.Bind(&blockc);
- m.Goto(&blockb);
- m.Bind(&blockb);
- m.Return(m.Int32Constant(constant));
-
- CHECK_EQ(constant, m.Call());
-}
-
-
-TEST(RunDiamond2) {
- RawMachineAssemblerTester<int32_t> m;
-
- int constant = 995666;
-
- MLabel blocka, blockb, end;
- m.Branch(m.Int32Constant(0), &blocka, &blockb);
- m.Bind(&blocka);
- m.Goto(&end);
- m.Bind(&blockb);
- m.Goto(&end);
- m.Bind(&end);
- m.Return(m.Int32Constant(constant));
-
- CHECK_EQ(constant, m.Call());
-}
-
-
-TEST(RunLoop) {
- RawMachineAssemblerTester<int32_t> m;
- int constant = 999555;
-
- MLabel header, body, exit;
- m.Goto(&header);
- m.Bind(&header);
- m.Branch(m.Int32Constant(0), &body, &exit);
- m.Bind(&body);
- m.Goto(&header);
- m.Bind(&exit);
- m.Return(m.Int32Constant(constant));
-
- CHECK_EQ(constant, m.Call());
-}
-
-
-template <typename R>
-static void BuildDiamondPhi(RawMachineAssemblerTester<R>* m, Node* cond_node,
- Node* true_node, Node* false_node) {
- MLabel blocka, blockb;
- MLabel* end = m->Exit();
- m->Branch(cond_node, &blocka, &blockb);
- m->Bind(&blocka);
- m->Goto(end);
- m->Bind(&blockb);
- m->Goto(end);
-
- m->Bind(end);
- Node* phi = m->Phi(true_node, false_node);
- m->Return(phi);
-}
-
-
-TEST(RunDiamondPhiConst) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- int false_val = 0xFF666;
- int true_val = 0x00DDD;
- Node* true_node = m.Int32Constant(true_val);
- Node* false_node = m.Int32Constant(false_val);
- BuildDiamondPhi(&m, m.Parameter(0), true_node, false_node);
- CHECK_EQ(false_val, m.Call(0));
- CHECK_EQ(true_val, m.Call(1));
-}
-
-
-TEST(RunDiamondPhiNumber) {
- RawMachineAssemblerTester<Object*> m(kMachineWord32);
- double false_val = -11.1;
- double true_val = 200.1;
- Node* true_node = m.NumberConstant(true_val);
- Node* false_node = m.NumberConstant(false_val);
- BuildDiamondPhi(&m, m.Parameter(0), true_node, false_node);
- m.CheckNumber(false_val, m.Call(0));
- m.CheckNumber(true_val, m.Call(1));
-}
-
-
-TEST(RunDiamondPhiString) {
- RawMachineAssemblerTester<Object*> m(kMachineWord32);
- const char* false_val = "false";
- const char* true_val = "true";
- Node* true_node = m.StringConstant(true_val);
- Node* false_node = m.StringConstant(false_val);
- BuildDiamondPhi(&m, m.Parameter(0), true_node, false_node);
- m.CheckString(false_val, m.Call(0));
- m.CheckString(true_val, m.Call(1));
-}
-
-
-TEST(RunDiamondPhiParam) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- BuildDiamondPhi(&m, m.Parameter(0), m.Parameter(1), m.Parameter(2));
- int32_t c1 = 0x260cb75a;
- int32_t c2 = 0xcd3e9c8b;
- int result = m.Call(0, c1, c2);
- CHECK_EQ(c2, result);
- result = m.Call(1, c1, c2);
- CHECK_EQ(c1, result);
-}
-
-
-TEST(RunLoopPhiConst) {
- RawMachineAssemblerTester<int32_t> m;
- int true_val = 0x44000;
- int false_val = 0x00888;
-
- Node* cond_node = m.Int32Constant(0);
- Node* true_node = m.Int32Constant(true_val);
- Node* false_node = m.Int32Constant(false_val);
-
- // x = false_val; while(false) { x = true_val; } return x;
- MLabel body, header;
- MLabel* end = m.Exit();
-
- m.Goto(&header);
- m.Bind(&header);
- Node* phi = m.Phi(false_node, true_node);
- m.Branch(cond_node, &body, end);
- m.Bind(&body);
- m.Goto(&header);
- m.Bind(end);
- m.Return(phi);
-
- CHECK_EQ(false_val, m.Call());
-}
-
-
-TEST(RunLoopPhiParam) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
-
- MLabel blocka, blockb;
- MLabel* end = m.Exit();
-
- m.Goto(&blocka);
-
- m.Bind(&blocka);
- Node* phi = m.Phi(m.Parameter(1), m.Parameter(2));
- Node* cond = m.Phi(m.Parameter(0), m.Int32Constant(0));
- m.Branch(cond, &blockb, end);
-
- m.Bind(&blockb);
- m.Goto(&blocka);
-
- m.Bind(end);
- m.Return(phi);
-
- int32_t c1 = 0xa81903b4;
- int32_t c2 = 0x5a1207da;
- int result = m.Call(0, c1, c2);
- CHECK_EQ(c1, result);
- result = m.Call(1, c1, c2);
- CHECK_EQ(c2, result);
-}
-
-
-TEST(RunLoopPhiInduction) {
- RawMachineAssemblerTester<int32_t> m;
-
- int false_val = 0x10777;
-
- // x = false_val; while(false) { x++; } return x;
- MLabel header, body;
- MLabel* end = m.Exit();
- Node* false_node = m.Int32Constant(false_val);
-
- m.Goto(&header);
-
- m.Bind(&header);
- Node* phi = m.Phi(false_node, false_node);
- m.Branch(m.Int32Constant(0), &body, end);
-
- m.Bind(&body);
- Node* add = m.Int32Add(phi, m.Int32Constant(1));
- phi->ReplaceInput(1, add);
- m.Goto(&header);
-
- m.Bind(end);
- m.Return(phi);
-
- CHECK_EQ(false_val, m.Call());
-}
-
-
-TEST(RunLoopIncrement) {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
-
- // x = 0; while(x ^ param) { x++; } return x;
- MLabel header, body;
- MLabel* end = m.Exit();
- Node* zero = m.Int32Constant(0);
-
- m.Goto(&header);
-
- m.Bind(&header);
- Node* phi = m.Phi(zero, zero);
- m.Branch(m.WordXor(phi, bt.param0), &body, end);
-
- m.Bind(&body);
- phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1)));
- m.Goto(&header);
-
- m.Bind(end);
- bt.AddReturn(phi);
-
- CHECK_EQ(11, bt.call(11, 0));
- CHECK_EQ(110, bt.call(110, 0));
- CHECK_EQ(176, bt.call(176, 0));
-}
-
-
-TEST(RunLoopIncrement2) {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
-
- // x = 0; while(x < param) { x++; } return x;
- MLabel header, body;
- MLabel* end = m.Exit();
- Node* zero = m.Int32Constant(0);
-
- m.Goto(&header);
-
- m.Bind(&header);
- Node* phi = m.Phi(zero, zero);
- m.Branch(m.Int32LessThan(phi, bt.param0), &body, end);
-
- m.Bind(&body);
- phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1)));
- m.Goto(&header);
-
- m.Bind(end);
- bt.AddReturn(phi);
-
- CHECK_EQ(11, bt.call(11, 0));
- CHECK_EQ(110, bt.call(110, 0));
- CHECK_EQ(176, bt.call(176, 0));
- CHECK_EQ(0, bt.call(-200, 0));
-}
-
-
-TEST(RunLoopIncrement3) {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
-
- // x = 0; while(x < param) { x++; } return x;
- MLabel header, body;
- MLabel* end = m.Exit();
- Node* zero = m.Int32Constant(0);
-
- m.Goto(&header);
-
- m.Bind(&header);
- Node* phi = m.Phi(zero, zero);
- m.Branch(m.Uint32LessThan(phi, bt.param0), &body, end);
-
- m.Bind(&body);
- phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1)));
- m.Goto(&header);
-
- m.Bind(end);
- bt.AddReturn(phi);
-
- CHECK_EQ(11, bt.call(11, 0));
- CHECK_EQ(110, bt.call(110, 0));
- CHECK_EQ(176, bt.call(176, 0));
- CHECK_EQ(200, bt.call(200, 0));
-}
-
-
-TEST(RunLoopDecrement) {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
-
- // x = param; while(x) { x--; } return x;
- MLabel header, body;
- MLabel* end = m.Exit();
-
- m.Goto(&header);
-
- m.Bind(&header);
- Node* phi = m.Phi(bt.param0, m.Int32Constant(0));
- m.Branch(phi, &body, end);
-
- m.Bind(&body);
- phi->ReplaceInput(1, m.Int32Sub(phi, m.Int32Constant(1)));
- m.Goto(&header);
-
- m.Bind(end);
- bt.AddReturn(phi);
-
- CHECK_EQ(0, bt.call(11, 0));
- CHECK_EQ(0, bt.call(110, 0));
- CHECK_EQ(0, bt.call(197, 0));
-}
-
-
-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();
- Node* minus_3 = m.Float64Constant(-3.0);
- Node* ten = m.Float64Constant(10.0);
-
- m.Goto(&header);
-
- m.Bind(&header);
- Node* phi = m.Phi(minus_3, ten);
- m.Branch(m.Float64LessThan(phi, ten), &body, end);
-
- m.Bind(&body);
- phi->ReplaceInput(1, m.Float64Add(phi, m.Float64Constant(0.5)));
- m.Goto(&header);
-
- m.Bind(end);
- m.Return(m.ConvertFloat64ToInt32(phi));
-
- CHECK_EQ(10, m.Call());
-}
-
-
-TEST(RunLoadInt32) {
- RawMachineAssemblerTester<int32_t> m;
-
- int32_t p1 = 0; // loads directly from this location.
- m.Return(m.LoadFromPointer(&p1, kMachineWord32));
-
- FOR_INT32_INPUTS(i) {
- p1 = *i;
- CHECK_EQ(p1, m.Call());
- }
-}
-
-
-TEST(RunLoadInt32Offset) {
- int32_t p1 = 0; // loads directly from this location.
-
- int32_t offsets[] = {-2000000, -100, -101, 1, 3,
- 7, 120, 2000, 2000000000, 0xff};
-
- for (size_t i = 0; i < ARRAY_SIZE(offsets); i++) {
- RawMachineAssemblerTester<int32_t> m;
- int32_t offset = offsets[i];
- byte* pointer = reinterpret_cast<byte*>(&p1) - offset;
- // generate load [#base + #index]
- m.Return(m.LoadFromPointer(pointer, kMachineWord32, offset));
-
- FOR_INT32_INPUTS(j) {
- p1 = *j;
- CHECK_EQ(p1, m.Call());
- }
- }
-}
-
-
-TEST(RunLoadStoreFloat64Offset) {
- double p1 = 0; // loads directly from this location.
- double p2 = 0; // and stores directly into this location.
-
- FOR_INT32_INPUTS(i) {
- int32_t magic = 0x2342aabb + *i * 3;
- RawMachineAssemblerTester<int32_t> m;
- int32_t offset = *i;
- byte* from = reinterpret_cast<byte*>(&p1) - offset;
- byte* to = reinterpret_cast<byte*>(&p2) - offset;
- // generate load [#base + #index]
- Node* load = m.Load(kMachineFloat64, m.PointerConstant(from),
- m.Int32Constant(offset));
- m.Store(kMachineFloat64, m.PointerConstant(to), m.Int32Constant(offset),
- load);
- m.Return(m.Int32Constant(magic));
-
- FOR_FLOAT64_INPUTS(j) {
- p1 = *j;
- p2 = *j - 5;
- CHECK_EQ(magic, m.Call());
- CHECK_EQ(p1, p2);
- }
- }
-}
-
-
-TEST(RunInt32AddP) {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
-
- bt.AddReturn(m.Int32Add(bt.param0, bt.param1));
-
- FOR_INT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- // Use uint32_t because signed overflow is UB in C.
- int expected = static_cast<int32_t>(*i + *j);
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
-}
-
-
-TEST(RunInt32AddAndWord32SarP) {
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Int32Add(m.Parameter(0),
- m.Word32Sar(m.Parameter(1), m.Parameter(2))));
- FOR_UINT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- // Use uint32_t because signed overflow is UB in C.
- int32_t expected = *i + (*j >> shift);
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Int32Add(m.Word32Sar(m.Parameter(0), m.Parameter(1)),
- m.Parameter(2)));
- FOR_INT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *j & 0x1F;
- // Use uint32_t because signed overflow is UB in C.
- int32_t expected = (*i >> shift) + *k;
- CHECK_EQ(expected, m.Call(*i, shift, *k));
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32AddAndWord32ShlP) {
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Int32Add(m.Parameter(0),
- m.Word32Shl(m.Parameter(1), m.Parameter(2))));
- FOR_UINT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- // Use uint32_t because signed overflow is UB in C.
- int32_t expected = *i + (*j << shift);
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Int32Add(m.Word32Shl(m.Parameter(0), m.Parameter(1)),
- m.Parameter(2)));
- FOR_INT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *j & 0x1F;
- // Use uint32_t because signed overflow is UB in C.
- int32_t expected = (*i << shift) + *k;
- CHECK_EQ(expected, m.Call(*i, shift, *k));
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32AddAndWord32ShrP) {
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Int32Add(m.Parameter(0),
- m.Word32Shr(m.Parameter(1), m.Parameter(2))));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- // Use uint32_t because signed overflow is UB in C.
- int32_t expected = *i + (*j >> shift);
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Int32Add(m.Word32Shr(m.Parameter(0), m.Parameter(1)),
- m.Parameter(2)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *j & 0x1F;
- // Use uint32_t because signed overflow is UB in C.
- int32_t expected = (*i >> shift) + *k;
- CHECK_EQ(expected, m.Call(*i, shift, *k));
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32AddInBranch) {
- static const int32_t constant = 987654321;
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- MLabel blocka, blockb;
- m.Branch(
- m.Word32Equal(m.Int32Add(bt.param0, bt.param1), m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- bt.AddReturn(m.Int32Constant(constant));
- m.Bind(&blockb);
- bt.AddReturn(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i + *j) == 0 ? constant : 0 - constant;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- MLabel blocka, blockb;
- m.Branch(
- m.Word32NotEqual(m.Int32Add(bt.param0, bt.param1), m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- bt.AddReturn(m.Int32Constant(constant));
- m.Bind(&blockb);
- bt.AddReturn(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i + *j) != 0 ? constant : 0 - constant;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(m.Int32Add(m.Int32Constant(*i), m.Parameter(0)),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i + *j) == 0 ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(m.Word32NotEqual(m.Int32Add(m.Int32Constant(*i), m.Parameter(0)),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i + *j) != 0 ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- RawMachineAssemblerTester<void> m;
- Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(),
- m.machine()->Word32Shr()};
- for (size_t n = 0; n < ARRAY_SIZE(shops); n++) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(m.Int32Add(m.Parameter(0),
- m.NewNode(shops[n], m.Parameter(1),
- m.Parameter(2))),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- int32_t right;
- switch (shops[n]->opcode()) {
- default:
- UNREACHABLE();
- case IrOpcode::kWord32Sar:
- right = *j >> shift;
- break;
- case IrOpcode::kWord32Shl:
- right = *j << shift;
- break;
- case IrOpcode::kWord32Shr:
- right = static_cast<uint32_t>(*j) >> shift;
- break;
- }
- int32_t expected = ((*i + right) == 0) ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32AddInComparison) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Word32Equal(m.Int32Add(bt.param0, bt.param1), m.Int32Constant(0)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i + *j) == 0;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Word32Equal(m.Int32Constant(0), m.Int32Add(bt.param0, bt.param1)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i + *j) == 0;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Equal(m.Int32Add(m.Int32Constant(*i), m.Parameter(0)),
- m.Int32Constant(0)));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i + *j) == 0;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Equal(m.Int32Add(m.Parameter(0), m.Int32Constant(*i)),
- m.Int32Constant(0)));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*j + *i) == 0;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- RawMachineAssemblerTester<void> m;
- Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(),
- m.machine()->Word32Shr()};
- for (size_t n = 0; n < ARRAY_SIZE(shops); n++) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Word32Equal(
- m.Int32Add(m.Parameter(0),
- m.NewNode(shops[n], m.Parameter(1), m.Parameter(2))),
- m.Int32Constant(0)));
- FOR_UINT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- int32_t right;
- switch (shops[n]->opcode()) {
- default:
- UNREACHABLE();
- case IrOpcode::kWord32Sar:
- right = *j >> shift;
- break;
- case IrOpcode::kWord32Shl:
- right = *j << shift;
- break;
- case IrOpcode::kWord32Shr:
- right = static_cast<uint32_t>(*j) >> shift;
- break;
- }
- int32_t expected = (*i + right) == 0;
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32SubP) {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
-
- m.Return(m.Int32Sub(bt.param0, bt.param1));
-
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- // Use uint32_t because signed overflow is UB in C.
- int expected = static_cast<int32_t>(*i - *j);
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
-}
-
-
-TEST(RunInt32SubImm) {
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)));
- FOR_UINT32_INPUTS(j) {
- // Use uint32_t because signed overflow is UB in C.
- int32_t expected = static_cast<int32_t>(*i - *j);
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Int32Sub(m.Parameter(0), m.Int32Constant(*i)));
- FOR_UINT32_INPUTS(j) {
- // Use uint32_t because signed overflow is UB in C.
- int32_t expected = static_cast<int32_t>(*j - *i);
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
-}
-
-
-TEST(RunInt32SubAndWord32SarP) {
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Int32Sub(m.Parameter(0),
- m.Word32Sar(m.Parameter(1), m.Parameter(2))));
- FOR_UINT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- // Use uint32_t because signed overflow is UB in C.
- int32_t expected = *i - (*j >> shift);
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Int32Sub(m.Word32Sar(m.Parameter(0), m.Parameter(1)),
- m.Parameter(2)));
- FOR_INT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *j & 0x1F;
- // Use uint32_t because signed overflow is UB in C.
- int32_t expected = (*i >> shift) - *k;
- CHECK_EQ(expected, m.Call(*i, shift, *k));
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32SubAndWord32ShlP) {
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Int32Sub(m.Parameter(0),
- m.Word32Shl(m.Parameter(1), m.Parameter(2))));
- FOR_UINT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- // Use uint32_t because signed overflow is UB in C.
- int32_t expected = *i - (*j << shift);
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Int32Sub(m.Word32Shl(m.Parameter(0), m.Parameter(1)),
- m.Parameter(2)));
- FOR_INT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *j & 0x1F;
- // Use uint32_t because signed overflow is UB in C.
- int32_t expected = (*i << shift) - *k;
- CHECK_EQ(expected, m.Call(*i, shift, *k));
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32SubAndWord32ShrP) {
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Int32Sub(m.Parameter(0),
- m.Word32Shr(m.Parameter(1), m.Parameter(2))));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- // Use uint32_t because signed overflow is UB in C.
- int32_t expected = *i - (*j >> shift);
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Int32Sub(m.Word32Shr(m.Parameter(0), m.Parameter(1)),
- m.Parameter(2)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *j & 0x1F;
- // Use uint32_t because signed overflow is UB in C.
- int32_t expected = (*i >> shift) - *k;
- CHECK_EQ(expected, m.Call(*i, shift, *k));
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32SubInBranch) {
- static const int constant = 987654321;
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- MLabel blocka, blockb;
- m.Branch(
- m.Word32Equal(m.Int32Sub(bt.param0, bt.param1), m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- bt.AddReturn(m.Int32Constant(constant));
- m.Bind(&blockb);
- bt.AddReturn(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i - *j) == 0 ? constant : 0 - constant;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- MLabel blocka, blockb;
- m.Branch(
- m.Word32NotEqual(m.Int32Sub(bt.param0, bt.param1), m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- bt.AddReturn(m.Int32Constant(constant));
- m.Bind(&blockb);
- bt.AddReturn(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i - *j) != 0 ? constant : 0 - constant;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i - *j) == 0 ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(m.Word32NotEqual(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i - *j) != 0 ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- RawMachineAssemblerTester<void> m;
- Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(),
- m.machine()->Word32Shr()};
- for (size_t n = 0; n < ARRAY_SIZE(shops); n++) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(m.Int32Sub(m.Parameter(0),
- m.NewNode(shops[n], m.Parameter(1),
- m.Parameter(2))),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- int32_t right;
- switch (shops[n]->opcode()) {
- default:
- UNREACHABLE();
- case IrOpcode::kWord32Sar:
- right = *j >> shift;
- break;
- case IrOpcode::kWord32Shl:
- right = *j << shift;
- break;
- case IrOpcode::kWord32Shr:
- right = static_cast<uint32_t>(*j) >> shift;
- break;
- }
- int32_t expected = ((*i - right) == 0) ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32SubInComparison) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Word32Equal(m.Int32Sub(bt.param0, bt.param1), m.Int32Constant(0)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i - *j) == 0;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Word32Equal(m.Int32Constant(0), m.Int32Sub(bt.param0, bt.param1)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i - *j) == 0;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Equal(m.Int32Sub(m.Int32Constant(*i), m.Parameter(0)),
- m.Int32Constant(0)));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i - *j) == 0;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Equal(m.Int32Sub(m.Parameter(0), m.Int32Constant(*i)),
- m.Int32Constant(0)));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*j - *i) == 0;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- RawMachineAssemblerTester<void> m;
- Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(),
- m.machine()->Word32Shr()};
- for (size_t n = 0; n < ARRAY_SIZE(shops); n++) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Word32Equal(
- m.Int32Sub(m.Parameter(0),
- m.NewNode(shops[n], m.Parameter(1), m.Parameter(2))),
- m.Int32Constant(0)));
- FOR_UINT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- int32_t right;
- switch (shops[n]->opcode()) {
- default:
- UNREACHABLE();
- case IrOpcode::kWord32Sar:
- right = *j >> shift;
- break;
- case IrOpcode::kWord32Shl:
- right = *j << shift;
- break;
- case IrOpcode::kWord32Shr:
- right = static_cast<uint32_t>(*j) >> shift;
- break;
- }
- int32_t expected = (*i - right) == 0;
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32MulP) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Int32Mul(bt.param0, bt.param1));
- FOR_INT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- int expected = static_cast<int32_t>(*i * *j);
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Int32Mul(bt.param0, bt.param1));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int expected = static_cast<int32_t>(*i * *j);
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
-}
-
-
-TEST(RunInt32MulImm) {
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Int32Mul(m.Int32Constant(*i), m.Parameter(0)));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = static_cast<int32_t>(*i * *j);
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant(*i)));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = static_cast<int32_t>(*j * *i);
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
-}
-
-
-TEST(RunInt32MulAndInt32AddP) {
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(
- m.Int32Add(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
- FOR_INT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_INT32_INPUTS(k) {
- int32_t p0 = *i;
- int32_t p1 = *j;
- int32_t p2 = *k;
- int expected = p0 + static_cast<int32_t>(p1 * p2);
- CHECK_EQ(expected, m.Call(p0, p1, p2));
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(
- m.Int32Add(m.Int32Mul(m.Parameter(0), m.Parameter(1)), m.Parameter(2)));
- FOR_INT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_INT32_INPUTS(k) {
- int32_t p0 = *i;
- int32_t p1 = *j;
- int32_t p2 = *k;
- int expected = static_cast<int32_t>(p0 * p1) + p2;
- CHECK_EQ(expected, m.Call(p0, p1, p2));
- }
- }
- }
- }
- {
- FOR_INT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Int32Add(m.Int32Constant(*i), m.Int32Mul(bt.param0, bt.param1)));
- FOR_INT32_INPUTS(j) {
- FOR_INT32_INPUTS(k) {
- int32_t p0 = *j;
- int32_t p1 = *k;
- int expected = *i + static_cast<int32_t>(p0 * p1);
- CHECK_EQ(expected, bt.call(p0, p1));
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32MulAndInt32SubP) {
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(
- m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2))));
- FOR_UINT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_INT32_INPUTS(k) {
- uint32_t p0 = *i;
- int32_t p1 = *j;
- int32_t p2 = *k;
- // Use uint32_t because signed overflow is UB in C.
- int expected = p0 - static_cast<uint32_t>(p1 * p2);
- CHECK_EQ(expected, m.Call(p0, p1, p2));
- }
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Int32Sub(m.Int32Constant(*i), m.Int32Mul(bt.param0, bt.param1)));
- FOR_INT32_INPUTS(j) {
- FOR_INT32_INPUTS(k) {
- int32_t p0 = *j;
- int32_t p1 = *k;
- // Use uint32_t because signed overflow is UB in C.
- int expected = *i - static_cast<uint32_t>(p0 * p1);
- CHECK_EQ(expected, bt.call(p0, p1));
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32DivP) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Int32Div(bt.param0, bt.param1));
- FOR_INT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- int p0 = *i;
- int p1 = *j;
- if (p1 != 0 && (static_cast<uint32_t>(p0) != 0x80000000 || p1 != -1)) {
- int expected = static_cast<int32_t>(p0 / p1);
- CHECK_EQ(expected, bt.call(p0, p1));
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Int32Add(bt.param0, m.Int32Div(bt.param0, bt.param1)));
- FOR_INT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- int p0 = *i;
- int p1 = *j;
- if (p1 != 0 && (static_cast<uint32_t>(p0) != 0x80000000 || p1 != -1)) {
- int expected = static_cast<int32_t>(p0 + (p0 / p1));
- CHECK_EQ(expected, bt.call(p0, p1));
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32UDivP) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Int32UDiv(bt.param0, bt.param1));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t p0 = *i;
- uint32_t p1 = *j;
- if (p1 != 0) {
- uint32_t expected = static_cast<uint32_t>(p0 / p1);
- CHECK_EQ(expected, bt.call(p0, p1));
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Int32Add(bt.param0, m.Int32UDiv(bt.param0, bt.param1)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t p0 = *i;
- uint32_t p1 = *j;
- if (p1 != 0) {
- uint32_t expected = static_cast<uint32_t>(p0 + (p0 / p1));
- CHECK_EQ(expected, bt.call(p0, p1));
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32ModP) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Int32Mod(bt.param0, bt.param1));
- FOR_INT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- int p0 = *i;
- int p1 = *j;
- if (p1 != 0 && (static_cast<uint32_t>(p0) != 0x80000000 || p1 != -1)) {
- int expected = static_cast<int32_t>(p0 % p1);
- CHECK_EQ(expected, bt.call(p0, p1));
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Int32Add(bt.param0, m.Int32Mod(bt.param0, bt.param1)));
- FOR_INT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- int p0 = *i;
- int p1 = *j;
- if (p1 != 0 && (static_cast<uint32_t>(p0) != 0x80000000 || p1 != -1)) {
- int expected = static_cast<int32_t>(p0 + (p0 % p1));
- CHECK_EQ(expected, bt.call(p0, p1));
- }
- }
- }
- }
-}
-
-
-TEST(RunInt32UModP) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Int32UMod(bt.param0, bt.param1));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t p0 = *i;
- uint32_t p1 = *j;
- if (p1 != 0) {
- uint32_t expected = static_cast<uint32_t>(p0 % p1);
- CHECK_EQ(expected, bt.call(p0, p1));
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Int32Add(bt.param0, m.Int32UMod(bt.param0, bt.param1)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t p0 = *i;
- uint32_t p1 = *j;
- if (p1 != 0) {
- uint32_t expected = static_cast<uint32_t>(p0 + (p0 % p1));
- CHECK_EQ(expected, bt.call(p0, p1));
- }
- }
- }
- }
-}
-
-
-TEST(RunWord32AndP) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Word32And(bt.param0, bt.param1));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i & *j;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Word32And(bt.param0, m.Word32Not(bt.param1)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i & ~(*j);
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Word32And(m.Word32Not(bt.param0), bt.param1));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = ~(*i) & *j;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
-}
-
-
-TEST(RunWord32AndAndWord32ShlP) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Word32Shl(bt.param0, m.Word32And(bt.param1, m.Int32Constant(0x1f))));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i << (*j & 0x1f);
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Word32Shl(bt.param0, m.Word32And(m.Int32Constant(0x1f), bt.param1)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i << (0x1f & *j);
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
-}
-
-
-TEST(RunWord32AndAndWord32ShrP) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Word32Shr(bt.param0, m.Word32And(bt.param1, m.Int32Constant(0x1f))));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i >> (*j & 0x1f);
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Word32Shr(bt.param0, m.Word32And(m.Int32Constant(0x1f), bt.param1)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i >> (0x1f & *j);
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
-}
-
-
-TEST(RunWord32AndAndWord32SarP) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Word32Sar(bt.param0, m.Word32And(bt.param1, m.Int32Constant(0x1f))));
- FOR_INT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i >> (*j & 0x1f);
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Word32Sar(bt.param0, m.Word32And(m.Int32Constant(0x1f), bt.param1)));
- FOR_INT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i >> (0x1f & *j);
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
-}
-
-
-TEST(RunWord32AndImm) {
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32And(m.Int32Constant(*i), m.Parameter(0)));
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i & *j;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32And(m.Int32Constant(*i), m.Word32Not(m.Parameter(0))));
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i & ~(*j);
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
-}
-
-
-TEST(RunWord32AndInBranch) {
- static const int constant = 987654321;
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- MLabel blocka, blockb;
- m.Branch(
- m.Word32Equal(m.Word32And(bt.param0, bt.param1), m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- bt.AddReturn(m.Int32Constant(constant));
- m.Bind(&blockb);
- bt.AddReturn(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i & *j) == 0 ? constant : 0 - constant;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- MLabel blocka, blockb;
- m.Branch(
- m.Word32NotEqual(m.Word32And(bt.param0, bt.param1), m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- bt.AddReturn(m.Int32Constant(constant));
- m.Bind(&blockb);
- bt.AddReturn(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i & *j) != 0 ? constant : 0 - constant;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(m.Word32And(m.Int32Constant(*i), m.Parameter(0)),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i & *j) == 0 ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(
- m.Word32NotEqual(m.Word32And(m.Int32Constant(*i), m.Parameter(0)),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i & *j) != 0 ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- RawMachineAssemblerTester<void> m;
- Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(),
- m.machine()->Word32Shr()};
- for (size_t n = 0; n < ARRAY_SIZE(shops); n++) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(m.Word32And(m.Parameter(0),
- m.NewNode(shops[n], m.Parameter(1),
- m.Parameter(2))),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- int32_t right;
- switch (shops[n]->opcode()) {
- default:
- UNREACHABLE();
- case IrOpcode::kWord32Sar:
- right = *j >> shift;
- break;
- case IrOpcode::kWord32Shl:
- right = *j << shift;
- break;
- case IrOpcode::kWord32Shr:
- right = static_cast<uint32_t>(*j) >> shift;
- break;
- }
- int32_t expected = ((*i & right) == 0) ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- }
-}
-
-
-TEST(RunWord32AndInComparison) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Word32Equal(m.Word32And(bt.param0, bt.param1), m.Int32Constant(0)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i & *j) == 0;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Word32Equal(m.Int32Constant(0), m.Word32And(bt.param0, bt.param1)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i & *j) == 0;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Equal(m.Word32And(m.Int32Constant(*i), m.Parameter(0)),
- m.Int32Constant(0)));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i & *j) == 0;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Equal(m.Word32And(m.Parameter(0), m.Int32Constant(*i)),
- m.Int32Constant(0)));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*j & *i) == 0;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
-}
-
-
-TEST(RunWord32OrP) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Word32Or(bt.param0, bt.param1));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i | *j;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Word32Or(bt.param0, m.Word32Not(bt.param1)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i | ~(*j);
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Word32Or(m.Word32Not(bt.param0), bt.param1));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = ~(*i) | *j;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
-}
-
-
-TEST(RunWord32OrImm) {
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Or(m.Int32Constant(*i), m.Parameter(0)));
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i | *j;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Or(m.Int32Constant(*i), m.Word32Not(m.Parameter(0))));
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i | ~(*j);
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
-}
-
-
-TEST(RunWord32OrInBranch) {
- static const int constant = 987654321;
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- MLabel blocka, blockb;
- m.Branch(
- m.Word32Equal(m.Word32Or(bt.param0, bt.param1), m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- bt.AddReturn(m.Int32Constant(constant));
- m.Bind(&blockb);
- bt.AddReturn(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i | *j) == 0 ? constant : 0 - constant;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- MLabel blocka, blockb;
- m.Branch(
- m.Word32NotEqual(m.Word32Or(bt.param0, bt.param1), m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- bt.AddReturn(m.Int32Constant(constant));
- m.Bind(&blockb);
- bt.AddReturn(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i | *j) != 0 ? constant : 0 - constant;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(m.Word32Or(m.Int32Constant(*i), m.Parameter(0)),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i | *j) == 0 ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(m.Word32NotEqual(m.Word32Or(m.Int32Constant(*i), m.Parameter(0)),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i | *j) != 0 ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- RawMachineAssemblerTester<void> m;
- Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(),
- m.machine()->Word32Shr()};
- for (size_t n = 0; n < ARRAY_SIZE(shops); n++) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(m.Word32Or(m.Parameter(0),
- m.NewNode(shops[n], m.Parameter(1),
- m.Parameter(2))),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- int32_t right;
- switch (shops[n]->opcode()) {
- default:
- UNREACHABLE();
- case IrOpcode::kWord32Sar:
- right = *j >> shift;
- break;
- case IrOpcode::kWord32Shl:
- right = *j << shift;
- break;
- case IrOpcode::kWord32Shr:
- right = static_cast<uint32_t>(*j) >> shift;
- break;
- }
- int32_t expected = ((*i | right) == 0) ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- }
-}
-
-
-TEST(RunWord32OrInComparison) {
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Word32Equal(m.Word32Or(bt.param0, bt.param1), m.Int32Constant(0)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i | *j) == 0;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(
- m.Word32Equal(m.Int32Constant(0), m.Word32Or(bt.param0, bt.param1)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i | *j) == 0;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Equal(m.Word32Or(m.Int32Constant(*i), m.Parameter(0)),
- m.Int32Constant(0)));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i | *j) == 0;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Equal(m.Word32Or(m.Parameter(0), m.Int32Constant(*i)),
- m.Int32Constant(0)));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*j | *i) == 0;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
-}
-
-
-TEST(RunWord32XorP) {
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Xor(m.Int32Constant(*i), m.Parameter(0)));
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i ^ *j;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Word32Xor(bt.param0, bt.param1));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i ^ *j;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Word32Xor(bt.param0, m.Word32Not(bt.param1)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i ^ ~(*j);
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Word32Xor(m.Word32Not(bt.param0), bt.param1));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = ~(*i) ^ *j;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Xor(m.Int32Constant(*i), m.Word32Not(m.Parameter(0))));
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *i ^ ~(*j);
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
-}
-
-
-TEST(RunWord32XorInBranch) {
- static const int constant = 987654321;
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- MLabel blocka, blockb;
- m.Branch(
- m.Word32Equal(m.Word32Xor(bt.param0, bt.param1), m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- bt.AddReturn(m.Int32Constant(constant));
- m.Bind(&blockb);
- bt.AddReturn(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i ^ *j) == 0 ? constant : 0 - constant;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- MLabel blocka, blockb;
- m.Branch(
- m.Word32NotEqual(m.Word32Xor(bt.param0, bt.param1), m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- bt.AddReturn(m.Int32Constant(constant));
- m.Bind(&blockb);
- bt.AddReturn(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i ^ *j) != 0 ? constant : 0 - constant;
- CHECK_EQ(expected, bt.call(*i, *j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(m.Word32Xor(m.Int32Constant(*i), m.Parameter(0)),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i ^ *j) == 0 ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- FOR_UINT32_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(
- m.Word32NotEqual(m.Word32Xor(m.Int32Constant(*i), m.Parameter(0)),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(j) {
- int32_t expected = (*i ^ *j) != 0 ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- RawMachineAssemblerTester<void> m;
- Operator* shops[] = {m.machine()->Word32Sar(), m.machine()->Word32Shl(),
- m.machine()->Word32Shr()};
- for (size_t n = 0; n < ARRAY_SIZE(shops); n++) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- MLabel blocka, blockb;
- m.Branch(m.Word32Equal(m.Word32Xor(m.Parameter(0),
- m.NewNode(shops[n], m.Parameter(1),
- m.Parameter(2))),
- m.Int32Constant(0)),
- &blocka, &blockb);
- m.Bind(&blocka);
- m.Return(m.Int32Constant(constant));
- m.Bind(&blockb);
- m.Return(m.Int32Constant(0 - constant));
- FOR_UINT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- int32_t right;
- switch (shops[n]->opcode()) {
- default:
- UNREACHABLE();
- case IrOpcode::kWord32Sar:
- right = *j >> shift;
- break;
- case IrOpcode::kWord32Shl:
- right = *j << shift;
- break;
- case IrOpcode::kWord32Shr:
- right = static_cast<uint32_t>(*j) >> shift;
- break;
- }
- int32_t expected = ((*i ^ right) == 0) ? constant : 0 - constant;
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- }
-}
-
-
-TEST(RunWord32ShlP) {
- {
- FOR_UINT32_INPUTS(i) {
- uint32_t shift = *i & 0x1F;
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Shl(m.Parameter(0), m.Int32Constant(shift)));
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *j << shift;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Word32Shl(bt.param0, bt.param1));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t shift = *j & 0x1F;
- uint32_t expected = *i << shift;
- CHECK_EQ(expected, bt.call(*i, shift));
- }
- }
- }
-}
-
-
-TEST(RunWord32ShrP) {
- {
- FOR_UINT32_INPUTS(i) {
- uint32_t shift = *i & 0x1F;
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)));
- FOR_UINT32_INPUTS(j) {
- uint32_t expected = *j >> shift;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Word32Shr(bt.param0, bt.param1));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- uint32_t shift = *j & 0x1F;
- uint32_t expected = *i >> shift;
- CHECK_EQ(expected, bt.call(*i, shift));
- }
- }
- CHECK_EQ(0x00010000, bt.call(0x80000000, 15));
- }
-}
-
-
-TEST(RunWord32SarP) {
- {
- FOR_INT32_INPUTS(i) {
- int32_t shift = *i & 0x1F;
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Sar(m.Parameter(0), m.Int32Constant(shift)));
- FOR_INT32_INPUTS(j) {
- int32_t expected = *j >> shift;
- CHECK_EQ(expected, m.Call(*j));
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Int32BinopTester bt(&m);
- bt.AddReturn(m.Word32Sar(bt.param0, bt.param1));
- FOR_INT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- int32_t shift = *j & 0x1F;
- int32_t expected = *i >> shift;
- CHECK_EQ(expected, bt.call(*i, shift));
- }
- }
- CHECK_EQ(0xFFFF0000, bt.call(0x80000000, 15));
- }
-}
-
-
-TEST(RunWord32NotP) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Word32Not(m.Parameter(0)));
- FOR_UINT32_INPUTS(i) {
- int expected = ~(*i);
- CHECK_EQ(expected, m.Call(*i));
- }
-}
-
-
-TEST(RunInt32NegP) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- m.Return(m.Int32Neg(m.Parameter(0)));
- FOR_INT32_INPUTS(i) {
- int expected = -*i;
- CHECK_EQ(expected, m.Call(*i));
- }
-}
-
-
-TEST(RunWord32EqualAndWord32SarP) {
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Word32Equal(m.Parameter(0),
- m.Word32Sar(m.Parameter(1), m.Parameter(2))));
- FOR_INT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- int32_t expected = (*i == (*j >> shift));
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Word32Equal(m.Word32Sar(m.Parameter(0), m.Parameter(1)),
- m.Parameter(2)));
- FOR_INT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- FOR_INT32_INPUTS(k) {
- uint32_t shift = *j & 0x1F;
- int32_t expected = ((*i >> shift) == *k);
- CHECK_EQ(expected, m.Call(*i, shift, *k));
- }
- }
- }
- }
-}
-
-
-TEST(RunWord32EqualAndWord32ShlP) {
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Word32Equal(m.Parameter(0),
- m.Word32Shl(m.Parameter(1), m.Parameter(2))));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- int32_t expected = (*i == (*j << shift));
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Word32Equal(m.Word32Shl(m.Parameter(0), m.Parameter(1)),
- m.Parameter(2)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *j & 0x1F;
- int32_t expected = ((*i << shift) == *k);
- CHECK_EQ(expected, m.Call(*i, shift, *k));
- }
- }
- }
- }
-}
-
-
-TEST(RunWord32EqualAndWord32ShrP) {
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Word32Equal(m.Parameter(0),
- m.Word32Shr(m.Parameter(1), m.Parameter(2))));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *k & 0x1F;
- int32_t expected = (*i == (*j >> shift));
- CHECK_EQ(expected, m.Call(*i, *j, shift));
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32,
- kMachineWord32);
- m.Return(m.Word32Equal(m.Word32Shr(m.Parameter(0), m.Parameter(1)),
- m.Parameter(2)));
- FOR_UINT32_INPUTS(i) {
- FOR_UINT32_INPUTS(j) {
- FOR_UINT32_INPUTS(k) {
- uint32_t shift = *j & 0x1F;
- int32_t expected = ((*i >> shift) == *k);
- CHECK_EQ(expected, m.Call(*i, shift, *k));
- }
- }
- }
- }
-}
-
-
-TEST(RunDeadNodes) {
- for (int i = 0; true; i++) {
- RawMachineAssemblerTester<int32_t> m(i == 5 ? kMachineWord32
- : kMachineLast);
- int constant = 0x55 + i;
- switch (i) {
- case 0:
- m.Int32Constant(44);
- break;
- case 1:
- m.StringConstant("unused");
- break;
- case 2:
- m.NumberConstant(11.1);
- break;
- case 3:
- m.PointerConstant(&constant);
- break;
- case 4:
- m.LoadFromPointer(&constant, kMachineWord32);
- break;
- case 5:
- m.Parameter(0);
- break;
- default:
- return;
- }
- m.Return(m.Int32Constant(constant));
- if (i != 5) {
- CHECK_EQ(constant, m.Call());
- } else {
- CHECK_EQ(constant, m.Call(0));
- }
- }
-}
-
-
-TEST(RunDeadInt32Binops) {
- RawMachineAssemblerTester<int32_t> m;
-
- Operator* ops[] = {
- m.machine()->Word32And(), m.machine()->Word32Or(),
- m.machine()->Word32Xor(), m.machine()->Word32Shl(),
- m.machine()->Word32Shr(), m.machine()->Word32Sar(),
- m.machine()->Word32Equal(), m.machine()->Int32Add(),
- m.machine()->Int32Sub(), m.machine()->Int32Mul(),
- m.machine()->Int32Div(), m.machine()->Int32UDiv(),
- m.machine()->Int32Mod(), m.machine()->Int32UMod(),
- m.machine()->Int32LessThan(), m.machine()->Int32LessThanOrEqual(),
- m.machine()->Uint32LessThan(), m.machine()->Uint32LessThanOrEqual(),
- NULL};
-
- for (int i = 0; ops[i] != NULL; i++) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
- int constant = 0x55555 + i;
- m.NewNode(ops[i], m.Parameter(0), m.Parameter(1));
- m.Return(m.Int32Constant(constant));
-
- CHECK_EQ(constant, m.Call(1, 1));
- }
-}
-
-
-template <typename CType>
-static void RunLoadImmIndex(MachineRepresentation rep) {
- const int kNumElems = 3;
- CType buffer[kNumElems];
-
- // initialize the buffer with raw data.
- byte* raw = reinterpret_cast<byte*>(buffer);
- for (size_t i = 0; i < sizeof(buffer); i++) {
- raw[i] = (i + sizeof(buffer)) ^ 0xAA;
- }
-
- // Test with various large and small offsets.
- for (int offset = -1; offset <= 200000; offset *= -5) {
- for (int i = 0; i < kNumElems; i++) {
- RawMachineAssemblerTester<CType> m;
- Node* base = m.PointerConstant(buffer - offset);
- Node* index = m.Int32Constant((offset + i) * sizeof(buffer[0]));
- m.Return(m.Load(rep, base, index));
-
- CHECK_EQ(buffer[i], m.Call());
- printf("XXX\n");
- }
- }
-}
-
-
-TEST(RunLoadImmIndex) {
- RunLoadImmIndex<int8_t>(kMachineWord8);
- RunLoadImmIndex<int16_t>(kMachineWord16);
- RunLoadImmIndex<int32_t>(kMachineWord32);
- RunLoadImmIndex<int32_t*>(kMachineTagged);
-
- // TODO(titzer): test kMachineFloat64 loads
- // TODO(titzer): test various indexing modes.
-}
-
-
-template <typename CType>
-static void RunLoadStore(MachineRepresentation rep) {
- const int kNumElems = 4;
- CType buffer[kNumElems];
-
- for (int32_t x = 0; x < kNumElems; x++) {
- int32_t y = kNumElems - x - 1;
- // initialize the buffer with raw data.
- byte* raw = reinterpret_cast<byte*>(buffer);
- for (size_t i = 0; i < sizeof(buffer); i++) {
- raw[i] = (i + sizeof(buffer)) ^ 0xAA;
- }
-
- RawMachineAssemblerTester<int32_t> m;
- int32_t OK = 0x29000 + x;
- Node* base = m.PointerConstant(buffer);
- Node* index0 = m.Int32Constant(x * sizeof(buffer[0]));
- Node* load = m.Load(rep, base, index0);
- Node* index1 = m.Int32Constant(y * sizeof(buffer[0]));
- m.Store(rep, base, index1, load);
- m.Return(m.Int32Constant(OK));
-
- CHECK_NE(buffer[x], buffer[y]);
- CHECK_EQ(OK, m.Call());
- CHECK_EQ(buffer[x], buffer[y]);
- }
-}
-
-
-TEST(RunLoadStore) {
- RunLoadStore<int8_t>(kMachineWord8);
- RunLoadStore<int16_t>(kMachineWord16);
- RunLoadStore<int32_t>(kMachineWord32);
- RunLoadStore<void*>(kMachineTagged);
- RunLoadStore<double>(kMachineFloat64);
-}
-
-
-TEST(RunFloat64Binop) {
- RawMachineAssemblerTester<int32_t> m;
- double result;
-
- Operator* ops[] = {m.machine()->Float64Add(), m.machine()->Float64Sub(),
- m.machine()->Float64Mul(), m.machine()->Float64Div(),
- m.machine()->Float64Mod(), NULL};
-
- double inf = V8_INFINITY;
- Operator* inputs[] = {
- m.common()->Float64Constant(0), m.common()->Float64Constant(1),
- m.common()->Float64Constant(1), m.common()->Float64Constant(0),
- m.common()->Float64Constant(0), m.common()->Float64Constant(-1),
- m.common()->Float64Constant(-1), m.common()->Float64Constant(0),
- m.common()->Float64Constant(0.22), m.common()->Float64Constant(-1.22),
- m.common()->Float64Constant(-1.22), m.common()->Float64Constant(0.22),
- m.common()->Float64Constant(inf), m.common()->Float64Constant(0.22),
- m.common()->Float64Constant(inf), m.common()->Float64Constant(-inf),
- NULL};
-
- for (int i = 0; ops[i] != NULL; i++) {
- for (int j = 0; inputs[j] != NULL; j += 2) {
- RawMachineAssemblerTester<int32_t> m;
- Node* a = m.NewNode(inputs[j]);
- Node* b = m.NewNode(inputs[j + 1]);
- Node* binop = m.NewNode(ops[i], a, b);
- Node* base = m.PointerConstant(&result);
- Node* zero = m.Int32Constant(0);
- m.Store(kMachineFloat64, base, zero, binop);
- m.Return(m.Int32Constant(i + j));
- CHECK_EQ(i + j, m.Call());
- }
- }
-}
-
-
-TEST(RunDeadFloat64Binops) {
- RawMachineAssemblerTester<int32_t> m;
-
- Operator* ops[] = {m.machine()->Float64Add(), m.machine()->Float64Sub(),
- m.machine()->Float64Mul(), m.machine()->Float64Div(),
- m.machine()->Float64Mod(), NULL};
-
- for (int i = 0; ops[i] != NULL; i++) {
- RawMachineAssemblerTester<int32_t> m;
- int constant = 0x53355 + i;
- m.NewNode(ops[i], m.Float64Constant(0.1), m.Float64Constant(1.11));
- m.Return(m.Int32Constant(constant));
- CHECK_EQ(constant, m.Call());
- }
-}
-
-
-TEST(RunFloat64AddP) {
- RawMachineAssemblerTester<int32_t> m;
- Float64BinopTester bt(&m);
-
- bt.AddReturn(m.Float64Add(bt.param0, bt.param1));
-
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- double expected = *pl + *pr;
- CHECK_EQ(expected, bt.call(*pl, *pr));
- }
- }
-}
-
-
-TEST(RunFloat64SubP) {
- RawMachineAssemblerTester<int32_t> m;
- Float64BinopTester bt(&m);
-
- bt.AddReturn(m.Float64Sub(bt.param0, bt.param1));
-
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- double expected = *pl - *pr;
- CHECK_EQ(expected, bt.call(*pl, *pr));
- }
- }
-}
-
-
-TEST(RunFloat64SubImm1) {
- double input = 0.0;
- double output = 0.0;
-
- FOR_FLOAT64_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m;
- Node* t0 = m.LoadFromPointer(&input, kMachineFloat64);
- Node* t1 = m.Float64Sub(m.Float64Constant(*i), t0);
- m.StoreToPointer(&output, kMachineFloat64, t1);
- m.Return(m.Int32Constant(0));
- FOR_FLOAT64_INPUTS(j) {
- input = *j;
- double expected = *i - input;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, output);
- }
- }
-}
-
-
-TEST(RunFloat64SubImm2) {
- double input = 0.0;
- double output = 0.0;
-
- FOR_FLOAT64_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m;
- Node* t0 = m.LoadFromPointer(&input, kMachineFloat64);
- Node* t1 = m.Float64Sub(t0, m.Float64Constant(*i));
- m.StoreToPointer(&output, kMachineFloat64, t1);
- m.Return(m.Int32Constant(0));
- FOR_FLOAT64_INPUTS(j) {
- input = *j;
- double expected = input - *i;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, output);
- }
- }
-}
-
-
-TEST(RunFloat64MulP) {
- RawMachineAssemblerTester<int32_t> m;
- Float64BinopTester bt(&m);
-
- bt.AddReturn(m.Float64Mul(bt.param0, bt.param1));
-
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- double expected = *pl * *pr;
- CHECK_EQ(expected, bt.call(*pl, *pr));
- }
- }
-}
-
-
-TEST(RunFloat64MulAndFloat64AddP) {
- double input_a = 0.0;
- double input_b = 0.0;
- double input_c = 0.0;
- double output = 0.0;
-
- {
- RawMachineAssemblerTester<int32_t> m;
- Node* a = m.LoadFromPointer(&input_a, kMachineFloat64);
- Node* b = m.LoadFromPointer(&input_b, kMachineFloat64);
- Node* c = m.LoadFromPointer(&input_c, kMachineFloat64);
- m.StoreToPointer(&output, kMachineFloat64,
- m.Float64Add(m.Float64Mul(a, b), c));
- m.Return(m.Int32Constant(0));
- FOR_FLOAT64_INPUTS(i) {
- FOR_FLOAT64_INPUTS(j) {
- FOR_FLOAT64_INPUTS(k) {
- input_a = *i;
- input_b = *j;
- input_c = *k;
- volatile double temp = input_a * input_b;
- volatile double expected = temp + input_c;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, output);
- }
- }
- }
- }
- {
- RawMachineAssemblerTester<int32_t> m;
- Node* a = m.LoadFromPointer(&input_a, kMachineFloat64);
- Node* b = m.LoadFromPointer(&input_b, kMachineFloat64);
- Node* c = m.LoadFromPointer(&input_c, kMachineFloat64);
- m.StoreToPointer(&output, kMachineFloat64,
- m.Float64Add(a, m.Float64Mul(b, c)));
- m.Return(m.Int32Constant(0));
- FOR_FLOAT64_INPUTS(i) {
- FOR_FLOAT64_INPUTS(j) {
- FOR_FLOAT64_INPUTS(k) {
- input_a = *i;
- input_b = *j;
- input_c = *k;
- volatile double temp = input_b * input_c;
- volatile double expected = input_a + temp;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, output);
- }
- }
- }
- }
-}
-
-
-TEST(RunFloat64MulAndFloat64SubP) {
- double input_a = 0.0;
- double input_b = 0.0;
- double input_c = 0.0;
- double output = 0.0;
-
- RawMachineAssemblerTester<int32_t> m;
- Node* a = m.LoadFromPointer(&input_a, kMachineFloat64);
- Node* b = m.LoadFromPointer(&input_b, kMachineFloat64);
- Node* c = m.LoadFromPointer(&input_c, kMachineFloat64);
- m.StoreToPointer(&output, kMachineFloat64,
- m.Float64Sub(a, m.Float64Mul(b, c)));
- m.Return(m.Int32Constant(0));
-
- FOR_FLOAT64_INPUTS(i) {
- FOR_FLOAT64_INPUTS(j) {
- FOR_FLOAT64_INPUTS(k) {
- input_a = *i;
- input_b = *j;
- input_c = *k;
- volatile double temp = input_b * input_c;
- volatile double expected = input_a - temp;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, output);
- }
- }
- }
-}
-
-
-TEST(RunFloat64MulImm) {
- double input = 0.0;
- double output = 0.0;
-
- {
- FOR_FLOAT64_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m;
- Node* t0 = m.LoadFromPointer(&input, kMachineFloat64);
- Node* t1 = m.Float64Mul(m.Float64Constant(*i), t0);
- m.StoreToPointer(&output, kMachineFloat64, t1);
- m.Return(m.Int32Constant(0));
- FOR_FLOAT64_INPUTS(j) {
- input = *j;
- double expected = *i * input;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, output);
- }
- }
- }
- {
- FOR_FLOAT64_INPUTS(i) {
- RawMachineAssemblerTester<int32_t> m;
- Node* t0 = m.LoadFromPointer(&input, kMachineFloat64);
- Node* t1 = m.Float64Mul(t0, m.Float64Constant(*i));
- m.StoreToPointer(&output, kMachineFloat64, t1);
- m.Return(m.Int32Constant(0));
- FOR_FLOAT64_INPUTS(j) {
- input = *j;
- double expected = input * *i;
- CHECK_EQ(0, m.Call());
- CHECK_EQ(expected, output);
- }
- }
- }
-}
-
-
-TEST(RunFloat64DivP) {
- RawMachineAssemblerTester<int32_t> m;
- Float64BinopTester bt(&m);
-
- bt.AddReturn(m.Float64Div(bt.param0, bt.param1));
-
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- double expected = *pl / *pr;
- CHECK_EQ(expected, bt.call(*pl, *pr));
- }
- }
-}
-
-
-TEST(RunFloat64ModP) {
- RawMachineAssemblerTester<int32_t> m;
- Float64BinopTester bt(&m);
-
- bt.AddReturn(m.Float64Mod(bt.param0, bt.param1));
-
- FOR_FLOAT64_INPUTS(i) {
- FOR_FLOAT64_INPUTS(j) {
- double expected = modulo(*i, *j);
- double found = bt.call(*i, *j);
- CHECK_EQ(expected, found);
- }
- }
-}
-
-
-TEST(RunConvertInt32ToFloat64_A) {
- RawMachineAssemblerTester<int32_t> m;
- int32_t magic = 0x986234;
- double result = 0;
-
- Node* convert = m.ConvertInt32ToFloat64(m.Int32Constant(magic));
- m.Store(kMachineFloat64, m.PointerConstant(&result), m.Int32Constant(0),
- convert);
- m.Return(m.Int32Constant(magic));
-
- CHECK_EQ(magic, m.Call());
- CHECK_EQ(static_cast<double>(magic), result);
-}
-
-
-TEST(RunConvertInt32ToFloat64_B) {
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- double output = 0;
-
- Node* convert = m.ConvertInt32ToFloat64(m.Parameter(0));
- m.Store(kMachineFloat64, m.PointerConstant(&output), m.Int32Constant(0),
- convert);
- m.Return(m.Parameter(0));
-
- FOR_INT32_INPUTS(i) {
- int32_t expect = *i;
- CHECK_EQ(expect, m.Call(expect));
- CHECK_EQ(static_cast<double>(expect), output);
- }
-}
-
-
-// TODO(titzer): Test ConvertUint32ToFloat64
-
-
-TEST(RunConvertFloat64ToInt32_A) {
- RawMachineAssemblerTester<int32_t> m;
- int32_t magic = 0x786234;
- double input = 11.1;
- int32_t result = 0;
-
- m.Store(kMachineWord32, m.PointerConstant(&result), m.Int32Constant(0),
- m.ConvertFloat64ToInt32(m.Float64Constant(input)));
- m.Return(m.Int32Constant(magic));
-
- CHECK_EQ(magic, m.Call());
- CHECK_EQ(static_cast<int32_t>(input), result);
-}
-
-
-TEST(RunConvertFloat64ToInt32_B) {
- RawMachineAssemblerTester<int32_t> m;
- double input = 0;
- int32_t output = 0;
-
- Node* load =
- m.Load(kMachineFloat64, m.PointerConstant(&input), m.Int32Constant(0));
- Node* convert = m.ConvertFloat64ToInt32(load);
- m.Store(kMachineWord32, m.PointerConstant(&output), m.Int32Constant(0),
- convert);
- m.Return(convert);
-
- {
- FOR_INT32_INPUTS(i) {
- input = *i;
- int expect = *i;
- CHECK_EQ(expect, m.Call());
- CHECK_EQ(expect, output);
- }
- }
-
- {
- FOR_FLOAT64_INPUTS(i) {
- input = *i;
- // TODO(titzer): float64 -> int32 outside of the int32 range; the machine
- // backends are all wrong in different ways, and they certainly don't
- // implement the JavaScript conversions correctly.
- if (std::isnan(input) || input > INT_MAX || input < INT_MIN) {
- continue;
- }
- int32_t expect = static_cast<int32_t>(input);
- CHECK_EQ(expect, m.Call());
- CHECK_EQ(expect, output);
- }
- }
-}
-
-
-// TODO(titzer): test ConvertFloat64ToUint32
-
-
-TEST(RunConvertFloat64ToInt32_truncation) {
- RawMachineAssemblerTester<int32_t> m;
- int32_t magic = 0x786234;
- double input = 3.9;
- int32_t result = 0;
-
- Node* input_node =
- m.Load(kMachineFloat64, m.PointerConstant(&input), m.Int32Constant(0));
- m.Store(kMachineWord32, m.PointerConstant(&result), m.Int32Constant(0),
- m.ConvertFloat64ToInt32(input_node));
- m.Return(m.Int32Constant(magic));
-
- for (int i = -200; i < 200; i++) {
- input = i + (i < 0 ? -0.9 : 0.9);
- CHECK_EQ(magic, m.Call());
- CHECK_EQ(i, result);
- }
-}
-
-
-TEST(RunConvertFloat64ToInt32_spilled) {
- RawMachineAssemblerTester<int32_t> m;
- const int kNumInputs = 32;
- int32_t magic = 0x786234;
- double input[kNumInputs];
- int32_t result[kNumInputs];
- Node* input_node[kNumInputs];
-
- for (int i = 0; i < kNumInputs; i++) {
- input_node[i] = m.Load(kMachineFloat64, m.PointerConstant(&input),
- m.Int32Constant(i * 8));
- }
-
- for (int i = 0; i < kNumInputs; i++) {
- m.Store(kMachineWord32, m.PointerConstant(&result), m.Int32Constant(i * 4),
- m.ConvertFloat64ToInt32(input_node[i]));
- }
-
- m.Return(m.Int32Constant(magic));
-
- for (int i = 0; i < kNumInputs; i++) {
- input[i] = 100.9 + i;
- }
-
- CHECK_EQ(magic, m.Call());
-
- for (int i = 0; i < kNumInputs; i++) {
- CHECK_EQ(result[i], 100 + i);
- }
-}
-
-
-TEST(RunDeadConvertFloat64ToInt32) {
- RawMachineAssemblerTester<int32_t> m;
- const int magic = 0x88abcda4;
- m.ConvertFloat64ToInt32(m.Float64Constant(999.78));
- m.Return(m.Int32Constant(magic));
- CHECK_EQ(magic, m.Call());
-}
-
-
-TEST(RunDeadConvertInt32ToFloat64) {
- RawMachineAssemblerTester<int32_t> m;
- const int magic = 0x8834abcd;
- m.ConvertInt32ToFloat64(m.Int32Constant(magic - 6888));
- m.Return(m.Int32Constant(magic));
- CHECK_EQ(magic, m.Call());
-}
-
-
-TEST(RunLoopPhiInduction2) {
- RawMachineAssemblerTester<int32_t> m;
-
- int false_val = 0x10777;
-
- // x = false_val; while(false) { x++; } return x;
- MLabel header, body, end;
- Node* false_node = m.Int32Constant(false_val);
- m.Goto(&header);
- m.Bind(&header);
- Node* phi = m.Phi(false_node, false_node);
- m.Branch(m.Int32Constant(0), &body, &end);
- m.Bind(&body);
- Node* add = m.Int32Add(phi, m.Int32Constant(1));
- phi->ReplaceInput(1, add);
- m.Goto(&header);
- m.Bind(&end);
- m.Return(phi);
-
- CHECK_EQ(false_val, m.Call());
-}
-
-
-TEST(RunDoubleDiamond) {
- RawMachineAssemblerTester<int32_t> m;
-
- const int magic = 99645;
- double buffer = 0.1;
- double constant = 99.99;
-
- MLabel blocka, blockb, end;
- Node* k1 = m.Float64Constant(constant);
- Node* k2 = m.Float64Constant(0 - constant);
- m.Branch(m.Int32Constant(0), &blocka, &blockb);
- m.Bind(&blocka);
- m.Goto(&end);
- m.Bind(&blockb);
- m.Goto(&end);
- m.Bind(&end);
- Node* phi = m.Phi(k2, k1);
- m.Store(kMachineFloat64, m.PointerConstant(&buffer), m.Int32Constant(0), phi);
- m.Return(m.Int32Constant(magic));
-
- CHECK_EQ(magic, m.Call());
- CHECK_EQ(constant, buffer);
-}
-
-
-TEST(RunRefDiamond) {
- RawMachineAssemblerTester<int32_t> m;
-
- const int magic = 99644;
- Handle<String> rexpected =
- CcTest::i_isolate()->factory()->InternalizeUtf8String("A");
- String* buffer;
-
- MLabel blocka, blockb, end;
- Node* k1 = m.StringConstant("A");
- Node* k2 = m.StringConstant("B");
- m.Branch(m.Int32Constant(0), &blocka, &blockb);
- m.Bind(&blocka);
- m.Goto(&end);
- m.Bind(&blockb);
- m.Goto(&end);
- m.Bind(&end);
- Node* phi = m.Phi(k2, k1);
- m.Store(kMachineTagged, m.PointerConstant(&buffer), m.Int32Constant(0), phi);
- m.Return(m.Int32Constant(magic));
-
- CHECK_EQ(magic, m.Call());
- CHECK(rexpected->SameValue(buffer));
-}
-
-
-TEST(RunDoubleRefDiamond) {
- RawMachineAssemblerTester<int32_t> m;
-
- const int magic = 99648;
- double dbuffer = 0.1;
- double dconstant = 99.99;
- Handle<String> rexpected =
- CcTest::i_isolate()->factory()->InternalizeUtf8String("AX");
- String* rbuffer;
-
- MLabel blocka, blockb, end;
- Node* d1 = m.Float64Constant(dconstant);
- Node* d2 = m.Float64Constant(0 - dconstant);
- Node* r1 = m.StringConstant("AX");
- Node* r2 = m.StringConstant("BX");
- m.Branch(m.Int32Constant(0), &blocka, &blockb);
- m.Bind(&blocka);
- m.Goto(&end);
- m.Bind(&blockb);
- m.Goto(&end);
- m.Bind(&end);
- Node* dphi = m.Phi(d2, d1);
- Node* rphi = m.Phi(r2, r1);
- m.Store(kMachineFloat64, m.PointerConstant(&dbuffer), m.Int32Constant(0),
- dphi);
- m.Store(kMachineTagged, m.PointerConstant(&rbuffer), m.Int32Constant(0),
- rphi);
- m.Return(m.Int32Constant(magic));
-
- CHECK_EQ(magic, m.Call());
- CHECK_EQ(dconstant, dbuffer);
- CHECK(rexpected->SameValue(rbuffer));
-}
-
-
-TEST(RunDoubleRefDoubleDiamond) {
- RawMachineAssemblerTester<int32_t> m;
-
- const int magic = 99649;
- double dbuffer = 0.1;
- double dconstant = 99.997;
- Handle<String> rexpected =
- CcTest::i_isolate()->factory()->InternalizeUtf8String("AD");
- String* rbuffer;
-
- MLabel blocka, blockb, mid, blockd, blocke, end;
- Node* d1 = m.Float64Constant(dconstant);
- Node* d2 = m.Float64Constant(0 - dconstant);
- Node* r1 = m.StringConstant("AD");
- Node* r2 = m.StringConstant("BD");
- m.Branch(m.Int32Constant(0), &blocka, &blockb);
- m.Bind(&blocka);
- m.Goto(&mid);
- m.Bind(&blockb);
- m.Goto(&mid);
- m.Bind(&mid);
- Node* dphi1 = m.Phi(d2, d1);
- Node* rphi1 = m.Phi(r2, r1);
- m.Branch(m.Int32Constant(0), &blockd, &blocke);
-
- m.Bind(&blockd);
- m.Goto(&end);
- m.Bind(&blocke);
- m.Goto(&end);
- m.Bind(&end);
- Node* dphi2 = m.Phi(d1, dphi1);
- Node* rphi2 = m.Phi(r1, rphi1);
-
- m.Store(kMachineFloat64, m.PointerConstant(&dbuffer), m.Int32Constant(0),
- dphi2);
- m.Store(kMachineTagged, m.PointerConstant(&rbuffer), m.Int32Constant(0),
- rphi2);
- m.Return(m.Int32Constant(magic));
-
- CHECK_EQ(magic, m.Call());
- CHECK_EQ(dconstant, dbuffer);
- CHECK(rexpected->SameValue(rbuffer));
-}
-
-
-TEST(RunDoubleLoopPhi) {
- RawMachineAssemblerTester<int32_t> m;
- MLabel header, body, end;
-
- int magic = 99773;
- double buffer = 0.99;
- double dconstant = 777.1;
-
- Node* zero = m.Int32Constant(0);
- Node* dk = m.Float64Constant(dconstant);
-
- m.Goto(&header);
- m.Bind(&header);
- Node* phi = m.Phi(dk, dk);
- phi->ReplaceInput(1, phi);
- m.Branch(zero, &body, &end);
- m.Bind(&body);
- m.Goto(&header);
- m.Bind(&end);
- m.Store(kMachineFloat64, m.PointerConstant(&buffer), m.Int32Constant(0), phi);
- m.Return(m.Int32Constant(magic));
-
- CHECK_EQ(magic, m.Call());
-}
-
-
-TEST(RunCountToTenAccRaw) {
- RawMachineAssemblerTester<int32_t> m;
-
- Node* zero = m.Int32Constant(0);
- Node* ten = m.Int32Constant(10);
- Node* one = m.Int32Constant(1);
-
- MLabel header, body, body_cont, end;
-
- m.Goto(&header);
-
- m.Bind(&header);
- Node* i = m.Phi(zero, zero);
- Node* j = m.Phi(zero, zero);
- m.Goto(&body);
-
- m.Bind(&body);
- Node* next_i = m.Int32Add(i, one);
- Node* next_j = m.Int32Add(j, one);
- m.Branch(m.Word32Equal(next_i, ten), &end, &body_cont);
-
- m.Bind(&body_cont);
- i->ReplaceInput(1, next_i);
- j->ReplaceInput(1, next_j);
- m.Goto(&header);
-
- m.Bind(&end);
- m.Return(ten);
-
- CHECK_EQ(10, m.Call());
-}
-
-
-TEST(RunCountToTenAccRaw2) {
- RawMachineAssemblerTester<int32_t> m;
-
- Node* zero = m.Int32Constant(0);
- Node* ten = m.Int32Constant(10);
- Node* one = m.Int32Constant(1);
-
- MLabel header, body, body_cont, end;
-
- m.Goto(&header);
-
- m.Bind(&header);
- Node* i = m.Phi(zero, zero);
- Node* j = m.Phi(zero, zero);
- Node* k = m.Phi(zero, zero);
- m.Goto(&body);
-
- m.Bind(&body);
- Node* next_i = m.Int32Add(i, one);
- Node* next_j = m.Int32Add(j, one);
- Node* next_k = m.Int32Add(j, one);
- m.Branch(m.Word32Equal(next_i, ten), &end, &body_cont);
-
- m.Bind(&body_cont);
- i->ReplaceInput(1, next_i);
- j->ReplaceInput(1, next_j);
- k->ReplaceInput(1, next_k);
- m.Goto(&header);
-
- m.Bind(&end);
- m.Return(ten);
-
- CHECK_EQ(10, m.Call());
-}
-
-
-TEST(RunAddTree) {
- RawMachineAssemblerTester<int32_t> m;
- int32_t inputs[] = {11, 12, 13, 14, 15, 16, 17, 18};
-
- Node* base = m.PointerConstant(inputs);
- Node* n0 = m.Load(kMachineWord32, base, m.Int32Constant(0 * sizeof(int32_t)));
- Node* n1 = m.Load(kMachineWord32, base, m.Int32Constant(1 * sizeof(int32_t)));
- Node* n2 = m.Load(kMachineWord32, base, m.Int32Constant(2 * sizeof(int32_t)));
- Node* n3 = m.Load(kMachineWord32, base, m.Int32Constant(3 * sizeof(int32_t)));
- Node* n4 = m.Load(kMachineWord32, base, m.Int32Constant(4 * sizeof(int32_t)));
- Node* n5 = m.Load(kMachineWord32, base, m.Int32Constant(5 * sizeof(int32_t)));
- Node* n6 = m.Load(kMachineWord32, base, m.Int32Constant(6 * sizeof(int32_t)));
- Node* n7 = m.Load(kMachineWord32, base, m.Int32Constant(7 * sizeof(int32_t)));
-
- Node* i1 = m.Int32Add(n0, n1);
- Node* i2 = m.Int32Add(n2, n3);
- Node* i3 = m.Int32Add(n4, n5);
- Node* i4 = m.Int32Add(n6, n7);
-
- Node* i5 = m.Int32Add(i1, i2);
- Node* i6 = m.Int32Add(i3, i4);
-
- Node* i7 = m.Int32Add(i5, i6);
-
- m.Return(i7);
-
- CHECK_EQ(116, m.Call());
-}
-
-
-#if MACHINE_ASSEMBLER_SUPPORTS_CALL_C
-
-static int Seven() { return 7; }
-static int UnaryMinus(int a) { return -a; }
-static int APlusTwoB(int a, int b) { return a + 2 * b; }
-
-
-TEST(RunCallSeven) {
- for (int i = 0; i < 2; i++) {
- bool call_direct = i == 0;
- void* function_address =
- reinterpret_cast<void*>(reinterpret_cast<intptr_t>(&Seven));
-
- RawMachineAssemblerTester<int32_t> m;
- Node** args = NULL;
- MachineRepresentation* arg_types = NULL;
- Node* function =
- call_direct ? m.PointerConstant(function_address)
- : m.LoadFromPointer(&function_address,
- MachineOperatorBuilder::pointer_rep());
- m.Return(m.CallC(function, kMachineWord32, arg_types, args, 0));
-
- CHECK_EQ(7, m.Call());
- }
-}
-
-
-TEST(RunCallUnaryMinus) {
- for (int i = 0; i < 2; i++) {
- bool call_direct = i == 0;
- void* function_address =
- reinterpret_cast<void*>(reinterpret_cast<intptr_t>(&UnaryMinus));
-
- RawMachineAssemblerTester<int32_t> m(kMachineWord32);
- Node* args[] = {m.Parameter(0)};
- MachineRepresentation arg_types[] = {kMachineWord32};
- Node* function =
- call_direct ? m.PointerConstant(function_address)
- : m.LoadFromPointer(&function_address,
- MachineOperatorBuilder::pointer_rep());
- m.Return(m.CallC(function, kMachineWord32, arg_types, args, 1));
-
- FOR_INT32_INPUTS(i) {
- int a = *i;
- CHECK_EQ(-a, m.Call(a));
- }
- }
-}
-
-
-TEST(RunCallAPlusTwoB) {
- for (int i = 0; i < 2; i++) {
- bool call_direct = i == 0;
- void* function_address =
- reinterpret_cast<void*>(reinterpret_cast<intptr_t>(&APlusTwoB));
-
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
- Node* args[] = {m.Parameter(0), m.Parameter(1)};
- MachineRepresentation arg_types[] = {kMachineWord32, kMachineWord32};
- Node* function =
- call_direct ? m.PointerConstant(function_address)
- : m.LoadFromPointer(&function_address,
- MachineOperatorBuilder::pointer_rep());
- m.Return(m.CallC(function, kMachineWord32, arg_types, args, 2));
-
- FOR_INT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- int a = *i;
- int b = *j;
- int result = m.Call(a, b);
- CHECK_EQ(a + 2 * b, result);
- }
- }
- }
-}
-
-#endif // MACHINE_ASSEMBLER_SUPPORTS_CALL_C
-
-
-static const int kFloat64CompareHelperTestCases = 15;
-static const int kFloat64CompareHelperNodeType = 4;
-
-static int Float64CompareHelper(RawMachineAssemblerTester<int32_t>* m,
- int test_case, int node_type, double x,
- double y) {
- static double buffer[2];
- buffer[0] = x;
- buffer[1] = y;
- CHECK(0 <= test_case && test_case < kFloat64CompareHelperTestCases);
- CHECK(0 <= node_type && node_type < kFloat64CompareHelperNodeType);
- CHECK(x < y);
- bool load_a = node_type / 2 == 1;
- bool load_b = node_type % 2 == 1;
- Node* a = load_a ? m->Load(kMachineFloat64, m->PointerConstant(&buffer[0]))
- : m->Float64Constant(x);
- Node* b = load_b ? m->Load(kMachineFloat64, m->PointerConstant(&buffer[1]))
- : m->Float64Constant(y);
- Node* cmp = NULL;
- bool expected = false;
- switch (test_case) {
- // Equal tests.
- case 0:
- cmp = m->Float64Equal(a, b);
- expected = false;
- break;
- case 1:
- cmp = m->Float64Equal(a, a);
- expected = true;
- break;
- // LessThan tests.
- case 2:
- cmp = m->Float64LessThan(a, b);
- expected = true;
- break;
- case 3:
- cmp = m->Float64LessThan(b, a);
- expected = false;
- break;
- case 4:
- cmp = m->Float64LessThan(a, a);
- expected = false;
- break;
- // LessThanOrEqual tests.
- case 5:
- cmp = m->Float64LessThanOrEqual(a, b);
- expected = true;
- break;
- case 6:
- cmp = m->Float64LessThanOrEqual(b, a);
- expected = false;
- break;
- case 7:
- cmp = m->Float64LessThanOrEqual(a, a);
- expected = true;
- break;
- // NotEqual tests.
- case 8:
- cmp = m->Float64NotEqual(a, b);
- expected = true;
- break;
- case 9:
- cmp = m->Float64NotEqual(b, a);
- expected = true;
- break;
- case 10:
- cmp = m->Float64NotEqual(a, a);
- expected = false;
- break;
- // GreaterThan tests.
- case 11:
- cmp = m->Float64GreaterThan(a, a);
- expected = false;
- break;
- case 12:
- cmp = m->Float64GreaterThan(a, b);
- expected = false;
- break;
- // GreaterThanOrEqual tests.
- case 13:
- cmp = m->Float64GreaterThanOrEqual(a, a);
- expected = true;
- break;
- case 14:
- cmp = m->Float64GreaterThanOrEqual(b, a);
- expected = true;
- break;
- default:
- UNREACHABLE();
- }
- m->Return(cmp);
- return expected;
-}
-
-
-TEST(RunFloat64Compare) {
- double inf = V8_INFINITY;
- // All pairs (a1, a2) are of the form a1 < a2.
- double inputs[] = {0.0, 1.0, -1.0, 0.22, -1.22, 0.22,
- -inf, 0.22, 0.22, inf, -inf, inf};
-
- for (int test = 0; test < kFloat64CompareHelperTestCases; test++) {
- for (int node_type = 0; node_type < kFloat64CompareHelperNodeType;
- node_type++) {
- for (size_t input = 0; input < ARRAY_SIZE(inputs); input += 2) {
- RawMachineAssemblerTester<int32_t> m;
- int expected = Float64CompareHelper(&m, test, node_type, inputs[input],
- inputs[input + 1]);
- CHECK_EQ(expected, m.Call());
- }
- }
- }
-}
-
-
-TEST(RunFloat64UnorderedCompare) {
- RawMachineAssemblerTester<int32_t> m;
-
- Operator* operators[] = {m.machine()->Float64Equal(),
- m.machine()->Float64LessThan(),
- m.machine()->Float64LessThanOrEqual()};
-
- double nan = v8::base::OS::nan_value();
-
- FOR_FLOAT64_INPUTS(i) {
- for (size_t o = 0; o < ARRAY_SIZE(operators); ++o) {
- for (int j = 0; j < 2; j++) {
- RawMachineAssemblerTester<int32_t> m;
- Node* a = m.Float64Constant(*i);
- Node* b = m.Float64Constant(nan);
- if (j == 1) std::swap(a, b);
- m.Return(m.NewNode(operators[o], a, b));
- CHECK_EQ(0, m.Call());
- }
- }
- }
-}
-
-
-TEST(RunFloat64Equal) {
- double input_a = 0.0;
- double input_b = 0.0;
-
- RawMachineAssemblerTester<int32_t> m;
- Node* a = m.LoadFromPointer(&input_a, kMachineFloat64);
- Node* b = m.LoadFromPointer(&input_b, kMachineFloat64);
- m.Return(m.Float64Equal(a, b));
-
- CompareWrapper cmp(IrOpcode::kFloat64Equal);
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- input_a = *pl;
- input_b = *pr;
- int32_t expected = cmp.Float64Compare(input_a, input_b) ? 1 : 0;
- CHECK_EQ(expected, m.Call());
- }
- }
-}
-
-
-TEST(RunFloat64LessThan) {
- double input_a = 0.0;
- double input_b = 0.0;
-
- RawMachineAssemblerTester<int32_t> m;
- Node* a = m.LoadFromPointer(&input_a, kMachineFloat64);
- Node* b = m.LoadFromPointer(&input_b, kMachineFloat64);
- m.Return(m.Float64LessThan(a, b));
-
- CompareWrapper cmp(IrOpcode::kFloat64LessThan);
- FOR_FLOAT64_INPUTS(pl) {
- FOR_FLOAT64_INPUTS(pr) {
- input_a = *pl;
- input_b = *pr;
- int32_t expected = cmp.Float64Compare(input_a, input_b) ? 1 : 0;
- CHECK_EQ(expected, m.Call());
- }
- }
-}
-
-
-template <typename IntType, MachineRepresentation kRepresentation>
-static void LoadStoreTruncation() {
- IntType input;
-
- RawMachineAssemblerTester<int32_t> m;
- Node* a = m.LoadFromPointer(&input, kRepresentation);
- Node* ap1 = m.Int32Add(a, m.Int32Constant(1));
- m.StoreToPointer(&input, kRepresentation, ap1);
- m.Return(ap1);
-
- const IntType max = std::numeric_limits<IntType>::max();
- const IntType min = std::numeric_limits<IntType>::min();
-
- // Test upper bound.
- input = max;
- CHECK_EQ(max + 1, m.Call());
- CHECK_EQ(min, input);
-
- // Test lower bound.
- input = min;
- CHECK_EQ(max + 2, m.Call());
- CHECK_EQ(min + 1, input);
-
- // Test all one byte values that are not one byte bounds.
- for (int i = -127; i < 127; i++) {
- input = i;
- int expected = i >= 0 ? i + 1 : max + (i - min) + 2;
- CHECK_EQ(expected, m.Call());
- CHECK_EQ(i + 1, input);
- }
-}
-
-
-TEST(RunLoadStoreTruncation) {
- LoadStoreTruncation<int8_t, kMachineWord8>();
- LoadStoreTruncation<int16_t, kMachineWord16>();
-}
-
-
-static void IntPtrCompare(intptr_t left, intptr_t right) {
- for (int test = 0; test < 7; test++) {
- RawMachineAssemblerTester<bool> m(MachineOperatorBuilder::pointer_rep(),
- MachineOperatorBuilder::pointer_rep());
- Node* p0 = m.Parameter(0);
- Node* p1 = m.Parameter(1);
- Node* res = NULL;
- bool expected = false;
- switch (test) {
- case 0:
- res = m.IntPtrLessThan(p0, p1);
- expected = true;
- break;
- case 1:
- res = m.IntPtrLessThanOrEqual(p0, p1);
- expected = true;
- break;
- case 2:
- res = m.IntPtrEqual(p0, p1);
- expected = false;
- break;
- case 3:
- res = m.IntPtrGreaterThanOrEqual(p0, p1);
- expected = false;
- break;
- case 4:
- res = m.IntPtrGreaterThan(p0, p1);
- expected = false;
- break;
- case 5:
- res = m.IntPtrEqual(p0, p0);
- expected = true;
- break;
- case 6:
- res = m.IntPtrNotEqual(p0, p1);
- expected = true;
- break;
- default:
- UNREACHABLE();
- break;
- }
- m.Return(res);
- CHECK_EQ(expected, m.Call(reinterpret_cast<int32_t*>(left),
- reinterpret_cast<int32_t*>(right)));
- }
-}
-
-
-TEST(RunIntPtrCompare) {
- intptr_t min = std::numeric_limits<intptr_t>::min();
- intptr_t max = std::numeric_limits<intptr_t>::max();
- // An ascending chain of intptr_t
- intptr_t inputs[] = {min, min / 2, -1, 0, 1, max / 2, max};
- for (size_t i = 0; i < ARRAY_SIZE(inputs) - 1; i++) {
- IntPtrCompare(inputs[i], inputs[i + 1]);
- }
-}
-
-
-TEST(RunTestIntPtrArithmetic) {
- static const int kInputSize = 10;
- int32_t inputs[kInputSize];
- int32_t outputs[kInputSize];
- for (int i = 0; i < kInputSize; i++) {
- inputs[i] = i;
- outputs[i] = -1;
- }
- 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])));
- for (int i = 0; i < kInputSize; i++) {
- m.Store(kMachineWord32, output, m.Load(kMachineWord32, input));
- input = m.IntPtrAdd(input, elem_size);
- output = m.IntPtrSub(output, elem_size);
- }
- m.Return(input);
- CHECK_EQ(&inputs[kInputSize], m.Call());
- for (int i = 0; i < kInputSize; i++) {
- CHECK_EQ(i, inputs[i]);
- CHECK_EQ(kInputSize - i - 1, outputs[i]);
- }
-}
-
-
-TEST(RunSpillLotsOfThings) {
- static const int kInputSize = 1000;
- RawMachineAssemblerTester<void> m;
- Node* accs[kInputSize];
- int32_t outputs[kInputSize];
- Node* one = m.Int32Constant(1);
- Node* acc = one;
- for (int i = 0; i < kInputSize; i++) {
- acc = m.Int32Add(acc, one);
- accs[i] = acc;
- }
- for (int i = 0; i < kInputSize; i++) {
- m.StoreToPointer(&outputs[i], kMachineWord32, accs[i]);
- }
- m.Return(one);
- m.Call();
- for (int i = 0; i < kInputSize; i++) {
- CHECK_EQ(outputs[i], i + 2);
- }
-}
-
-
-TEST(RunSpillConstantsAndParameters) {
- static const size_t kInputSize = 1000;
- static const int32_t kBase = 987;
- RawMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
- int32_t outputs[kInputSize];
- Node* csts[kInputSize];
- Node* accs[kInputSize];
- Node* acc = m.Int32Constant(0);
- for (size_t i = 0; i < kInputSize; i++) {
- csts[i] = m.Int32Constant(static_cast<int32_t>(kBase + i));
- }
- for (size_t i = 0; i < kInputSize; i++) {
- acc = m.Int32Add(acc, csts[i]);
- accs[i] = acc;
- }
- for (size_t i = 0; i < kInputSize; i++) {
- m.StoreToPointer(&outputs[i], kMachineWord32, accs[i]);
- }
- m.Return(m.Int32Add(acc, m.Int32Add(m.Parameter(0), m.Parameter(1))));
- FOR_INT32_INPUTS(i) {
- FOR_INT32_INPUTS(j) {
- int32_t expected = *i + *j;
- for (size_t k = 0; k < kInputSize; k++) {
- expected += kBase + k;
- }
- CHECK_EQ(expected, m.Call(*i, *j));
- expected = 0;
- for (size_t k = 0; k < kInputSize; k++) {
- expected += kBase + k;
- CHECK_EQ(expected, outputs[k]);
- }
- }
- }
-}
-
-
-TEST(RunNewSpaceConstantsInPhi) {
- RawMachineAssemblerTester<Object*> m(kMachineWord32);
-
- Isolate* isolate = CcTest::i_isolate();
- Handle<HeapNumber> true_val = isolate->factory()->NewHeapNumber(11.2);
- Handle<HeapNumber> false_val = isolate->factory()->NewHeapNumber(11.3);
- Node* true_node = m.HeapConstant(true_val);
- Node* false_node = m.HeapConstant(false_val);
-
- MLabel blocka, blockb, end;
- m.Branch(m.Parameter(0), &blocka, &blockb);
- m.Bind(&blocka);
- m.Goto(&end);
- m.Bind(&blockb);
- m.Goto(&end);
-
- m.Bind(&end);
- Node* phi = m.Phi(true_node, false_node);
- m.Return(phi);
-
- CHECK_EQ(*false_val, m.Call(0));
- CHECK_EQ(*true_val, m.Call(1));
-}
-
-
-#if MACHINE_ASSEMBLER_SUPPORTS_CALL_C
-
-TEST(RunSpillLotsOfThingsWithCall) {
- static const int kInputSize = 1000;
- RawMachineAssemblerTester<void> m;
- Node* accs[kInputSize];
- int32_t outputs[kInputSize];
- Node* one = m.Int32Constant(1);
- Node* acc = one;
- for (int i = 0; i < kInputSize; i++) {
- acc = m.Int32Add(acc, one);
- accs[i] = acc;
- }
- // If the spill slot computation is wrong, it might load from the c frame
- {
- void* func = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(&Seven));
- Node** args = NULL;
- MachineRepresentation* arg_types = NULL;
- m.CallC(m.PointerConstant(func), kMachineWord32, arg_types, args, 0);
- }
- for (int i = 0; i < kInputSize; i++) {
- m.StoreToPointer(&outputs[i], kMachineWord32, accs[i]);
- }
- m.Return(one);
- m.Call();
- for (int i = 0; i < kInputSize; i++) {
- CHECK_EQ(outputs[i], i + 2);
- }
-}
-
-#endif // MACHINE_ASSEMBLER_SUPPORTS_CALL_C
-
-#endif
+++ /dev/null
-// 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/compiler/function-tester.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-static const char* throws = NULL;
-
-static const char* load_tests[] = {
- "var x = a; r = x", "123", "0",
- "var x = (r = x)", "undefined", "undefined",
- "var x = (a?1:2); r = x", "1", "2",
- "const x = a; r = x", "123", "0",
- "const x = (r = x)", "undefined", "undefined",
- "const x = (a?3:4); r = x", "3", "4",
- "'use strict'; const x = a; r = x", "123", "0",
- "'use strict'; const x = (r = x)", throws, throws,
- "'use strict'; const x = (a?5:6); r = x", "5", "6",
- "'use strict'; let x = a; r = x", "123", "0",
- "'use strict'; let x = (r = x)", throws, throws,
- "'use strict'; let x = (a?7:8); r = x", "7", "8",
- NULL};
-
-static const char* store_tests[] = {
- "var x = 1; x = a; r = x", "123", "0",
- "var x = (a?(x=4,2):3); r = x", "2", "3",
- "var x = (a?4:5); x = a; r = x", "123", "0",
- "const x = 1; x = a; r = x", "1", "1",
- "const x = (a?(x=4,2):3); r = x", "2", "3",
- "const x = (a?4:5); x = a; r = x", "4", "5",
- // Assignments to 'const' are SyntaxErrors, handled by the parser,
- // hence we cannot test them here because they are early errors.
- "'use strict'; let x = 1; x = a; r = x", "123", "0",
- "'use strict'; let x = (a?(x=4,2):3); r = x", throws, "3",
- "'use strict'; let x = (a?4:5); x = a; r = x", "123", "0",
- NULL};
-
-static const char* bind_tests[] = {
- "if (a) { const x = a }; r = x;", "123", "undefined",
- "for (; a > 0; a--) { const x = a }; r = x", "123", "undefined",
- // Re-initialization of variables other than legacy 'const' is not
- // possible due to sane variable scoping, hence no tests here.
- NULL};
-
-
-static void RunVariableTests(const char* source, const char* tests[]) {
- FLAG_harmony_scoping = true;
- EmbeddedVector<char, 512> buffer;
-
- for (int i = 0; tests[i] != NULL; i += 3) {
- SNPrintF(buffer, source, tests[i]);
- PrintF("#%d: %s\n", i / 3, buffer.start());
- FunctionTester T(buffer.start());
-
- // Check function with non-falsey parameter.
- if (tests[i + 1] != throws) {
- Handle<Object> r = v8::Utils::OpenHandle(*CompileRun(tests[i + 1]));
- T.CheckCall(r, T.Val(123), T.Val("result"));
- } else {
- T.CheckThrows(T.Val(123), T.Val("result"));
- }
-
- // Check function with falsey parameter.
- if (tests[i + 2] != throws) {
- Handle<Object> r = v8::Utils::OpenHandle(*CompileRun(tests[i + 2]));
- T.CheckCall(r, T.Val(0.0), T.Val("result"));
- } else {
- T.CheckThrows(T.Val(0.0), T.Val("result"));
- }
- }
-}
-
-
-TEST(StackLoadVariables) {
- const char* source = "(function(a,r) { %s; return r; })";
- RunVariableTests(source, load_tests);
-}
-
-
-TEST(ContextLoadVariables) {
- const char* source = "(function(a,r) { %s; function f() {x} return r; })";
- RunVariableTests(source, load_tests);
-}
-
-
-TEST(StackStoreVariables) {
- const char* source = "(function(a,r) { %s; return r; })";
- RunVariableTests(source, store_tests);
-}
-
-
-TEST(ContextStoreVariables) {
- const char* source = "(function(a,r) { %s; function f() {x} return r; })";
- RunVariableTests(source, store_tests);
-}
-
-
-TEST(StackInitializeVariables) {
- const char* source = "(function(a,r) { %s; return r; })";
- RunVariableTests(source, bind_tests);
-}
-
-
-TEST(ContextInitializeVariables) {
- const char* source = "(function(a,r) { %s; function f() {x} return r; })";
- RunVariableTests(source, bind_tests);
-}
-
-
-TEST(SelfReferenceVariable) {
- FunctionTester T("(function self() { return self; })");
-
- T.CheckCall(T.function);
- CompileRun("var self = 'not a function'");
- T.CheckCall(T.function);
-}
+++ /dev/null
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/v8.h"
-
-#include "src/compiler/common-operator.h"
-#include "src/compiler/generic-node-inl.h"
-#include "src/compiler/graph.h"
-#include "src/compiler/machine-operator.h"
-#include "src/compiler/node.h"
-#include "src/compiler/operator.h"
-#include "src/compiler/schedule.h"
-#include "test/cctest/cctest.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-static SimpleOperator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
- 0, 0, "dummy");
-
-TEST(TestScheduleAllocation) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- CHECK_NE(NULL, schedule.entry());
- CHECK_EQ(schedule.entry(), *(schedule.all_blocks().begin()));
-}
-
-
-TEST(TestScheduleAddNode) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* n1 = graph.NewNode(&dummy_operator);
-
- Schedule schedule(scope.main_zone());
-
- BasicBlock* entry = schedule.entry();
- schedule.AddNode(entry, n0);
- schedule.AddNode(entry, n1);
-
- CHECK_EQ(entry, schedule.block(n0));
- CHECK_EQ(entry, schedule.block(n1));
- CHECK(schedule.SameBasicBlock(n0, n1));
-
- Node* n2 = graph.NewNode(&dummy_operator);
- CHECK_EQ(NULL, schedule.block(n2));
-}
-
-
-TEST(TestScheduleAddGoto) {
- HandleAndZoneScope scope;
-
- Schedule schedule(scope.main_zone());
- BasicBlock* entry = schedule.entry();
- BasicBlock* next = schedule.NewBasicBlock();
-
- schedule.AddGoto(entry, next);
-
- CHECK_EQ(0, entry->PredecessorCount());
- CHECK_EQ(1, entry->SuccessorCount());
- CHECK_EQ(next, entry->SuccessorAt(0));
-
- CHECK_EQ(1, next->PredecessorCount());
- CHECK_EQ(entry, next->PredecessorAt(0));
- CHECK_EQ(0, next->SuccessorCount());
-}
-
-
-TEST(TestScheduleAddBranch) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
-
- BasicBlock* entry = schedule.entry();
- BasicBlock* tblock = schedule.NewBasicBlock();
- BasicBlock* fblock = schedule.NewBasicBlock();
-
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
- Node* n0 = graph.NewNode(&dummy_operator);
- Node* b = graph.NewNode(common.Branch(), n0);
-
- schedule.AddBranch(entry, b, tblock, fblock);
-
- CHECK_EQ(0, entry->PredecessorCount());
- CHECK_EQ(2, entry->SuccessorCount());
- CHECK_EQ(tblock, entry->SuccessorAt(0));
- CHECK_EQ(fblock, entry->SuccessorAt(1));
-
- CHECK_EQ(1, tblock->PredecessorCount());
- CHECK_EQ(entry, tblock->PredecessorAt(0));
- CHECK_EQ(0, tblock->SuccessorCount());
-
- CHECK_EQ(1, fblock->PredecessorCount());
- CHECK_EQ(entry, fblock->PredecessorAt(0));
- CHECK_EQ(0, fblock->SuccessorCount());
-}
-
-
-TEST(TestScheduleAddReturn) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Graph graph(scope.main_zone());
- Node* n0 = graph.NewNode(&dummy_operator);
- BasicBlock* entry = schedule.entry();
- schedule.AddReturn(entry, n0);
-
- CHECK_EQ(0, entry->PredecessorCount());
- CHECK_EQ(1, entry->SuccessorCount());
- CHECK_EQ(schedule.exit(), entry->SuccessorAt(0));
-}
-
-
-TEST(TestScheduleAddThrow) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Graph graph(scope.main_zone());
- Node* n0 = graph.NewNode(&dummy_operator);
- BasicBlock* entry = schedule.entry();
- schedule.AddThrow(entry, n0);
-
- CHECK_EQ(0, entry->PredecessorCount());
- CHECK_EQ(1, entry->SuccessorCount());
- CHECK_EQ(schedule.exit(), entry->SuccessorAt(0));
-}
-
-
-TEST(TestScheduleAddDeopt) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Graph graph(scope.main_zone());
- Node* n0 = graph.NewNode(&dummy_operator);
- BasicBlock* entry = schedule.entry();
- schedule.AddDeoptimize(entry, n0);
-
- CHECK_EQ(0, entry->PredecessorCount());
- CHECK_EQ(1, entry->SuccessorCount());
- CHECK_EQ(schedule.exit(), entry->SuccessorAt(0));
-}
-
-
-TEST(BuildMulNodeGraph) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common(scope.main_zone());
- MachineOperatorBuilder machine(scope.main_zone(), kMachineWord32);
-
- Node* start = graph.NewNode(common.Start());
- graph.SetStart(start);
- Node* param0 = graph.NewNode(common.Parameter(0));
- Node* param1 = graph.NewNode(common.Parameter(1));
-
- Node* mul = graph.NewNode(machine.Int32Mul(), param0, param1);
- Node* ret = graph.NewNode(common.Return(), mul, start);
-
- USE(ret);
-}
+++ /dev/null
-// 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/common-operator.h"
-#include "src/compiler/generic-node-inl.h"
-#include "src/compiler/generic-node.h"
-#include "src/compiler/graph.h"
-#include "src/compiler/graph-visualizer.h"
-#include "src/compiler/js-operator.h"
-#include "src/compiler/machine-operator.h"
-#include "src/compiler/node.h"
-#include "src/compiler/operator.h"
-#include "src/compiler/schedule.h"
-#include "src/compiler/scheduler.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-struct TestLoop {
- int count;
- BasicBlock** nodes;
- BasicBlock* header() { return nodes[0]; }
- BasicBlock* last() { return nodes[count - 1]; }
- ~TestLoop() { delete[] nodes; }
-};
-
-
-static TestLoop* CreateLoop(Schedule* schedule, int count) {
- TestLoop* loop = new TestLoop();
- loop->count = count;
- loop->nodes = new BasicBlock* [count];
- for (int i = 0; i < count; i++) {
- loop->nodes[i] = schedule->NewBasicBlock();
- if (i > 0) schedule->AddSuccessor(loop->nodes[i - 1], loop->nodes[i]);
- }
- schedule->AddSuccessor(loop->nodes[count - 1], loop->nodes[0]);
- return loop;
-}
-
-
-static void CheckRPONumbers(BasicBlockVector* order, int expected,
- bool loops_allowed) {
- CHECK_EQ(expected, static_cast<int>(order->size()));
- for (int i = 0; i < static_cast<int>(order->size()); i++) {
- CHECK(order->at(i)->rpo_number_ == i);
- if (!loops_allowed) CHECK_LT(order->at(i)->loop_end_, 0);
- }
-}
-
-
-static void CheckLoopContains(BasicBlock** blocks, int body_size) {
- BasicBlock* header = blocks[0];
- CHECK_GT(header->loop_end_, 0);
- CHECK_EQ(body_size, (header->loop_end_ - header->rpo_number_));
- for (int i = 0; i < body_size; i++) {
- int num = blocks[i]->rpo_number_;
- CHECK(num >= header->rpo_number_ && num < header->loop_end_);
- CHECK(header->LoopContains(blocks[i]));
- CHECK(header->IsLoopHeader() || blocks[i]->loop_header_ == header);
- }
-}
-
-
-TEST(RPODegenerate1) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, 1, false);
- CHECK_EQ(schedule.entry(), order->at(0));
-}
-
-
-TEST(RPODegenerate2) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
-
- schedule.AddGoto(schedule.entry(), schedule.exit());
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, 2, false);
- CHECK_EQ(schedule.entry(), order->at(0));
- CHECK_EQ(schedule.exit(), order->at(1));
-}
-
-
-TEST(RPOLine) {
- HandleAndZoneScope scope;
-
- for (int i = 0; i < 10; i++) {
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
-
- BasicBlock* last = schedule.entry();
- for (int j = 0; j < i; j++) {
- BasicBlock* block = schedule.NewBasicBlock();
- schedule.AddGoto(last, block);
- last = block;
- }
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, 1 + i, false);
-
- Schedule::BasicBlocks blocks(schedule.all_blocks());
- for (Schedule::BasicBlocks::iterator iter = blocks.begin();
- iter != blocks.end(); ++iter) {
- BasicBlock* block = *iter;
- if (block->rpo_number_ >= 0 && block->SuccessorCount() == 1) {
- CHECK(block->rpo_number_ + 1 == block->SuccessorAt(0)->rpo_number_);
- }
- }
- }
-}
-
-
-TEST(RPOSelfLoop) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
- schedule.AddSuccessor(schedule.entry(), schedule.entry());
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, 1, true);
- BasicBlock* loop[] = {schedule.entry()};
- CheckLoopContains(loop, 1);
-}
-
-
-TEST(RPOEntryLoop) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
- schedule.AddSuccessor(schedule.entry(), schedule.exit());
- schedule.AddSuccessor(schedule.exit(), schedule.entry());
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, 2, true);
- BasicBlock* loop[] = {schedule.entry(), schedule.exit()};
- CheckLoopContains(loop, 2);
-}
-
-
-TEST(RPOEndLoop) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
- TestLoop* loop1 = CreateLoop(&schedule, 2);
- schedule.AddSuccessor(schedule.entry(), loop1->header());
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, 3, true);
- CheckLoopContains(loop1->nodes, loop1->count);
-}
-
-
-TEST(RPOEndLoopNested) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
- TestLoop* loop1 = CreateLoop(&schedule, 2);
- schedule.AddSuccessor(schedule.entry(), loop1->header());
- schedule.AddSuccessor(loop1->last(), schedule.entry());
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, 3, true);
- CheckLoopContains(loop1->nodes, loop1->count);
-}
-
-
-TEST(RPODiamond) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
-
- BasicBlock* A = schedule.entry();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.exit();
-
- schedule.AddSuccessor(A, B);
- schedule.AddSuccessor(A, C);
- schedule.AddSuccessor(B, D);
- schedule.AddSuccessor(C, D);
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, 4, false);
-
- CHECK_EQ(0, A->rpo_number_);
- CHECK((B->rpo_number_ == 1 && C->rpo_number_ == 2) ||
- (B->rpo_number_ == 2 && C->rpo_number_ == 1));
- CHECK_EQ(3, D->rpo_number_);
-}
-
-
-TEST(RPOLoop1) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
-
- BasicBlock* A = schedule.entry();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.exit();
-
- schedule.AddSuccessor(A, B);
- schedule.AddSuccessor(B, C);
- schedule.AddSuccessor(C, B);
- schedule.AddSuccessor(C, D);
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, 4, true);
- BasicBlock* loop[] = {B, C};
- CheckLoopContains(loop, 2);
-}
-
-
-TEST(RPOLoop2) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
-
- BasicBlock* A = schedule.entry();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.exit();
-
- schedule.AddSuccessor(A, B);
- schedule.AddSuccessor(B, C);
- schedule.AddSuccessor(C, B);
- schedule.AddSuccessor(B, D);
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, 4, true);
- BasicBlock* loop[] = {B, C};
- CheckLoopContains(loop, 2);
-}
-
-
-TEST(RPOLoopN) {
- HandleAndZoneScope scope;
-
- for (int i = 0; i < 11; i++) {
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
- BasicBlock* A = schedule.entry();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.NewBasicBlock();
- BasicBlock* E = schedule.NewBasicBlock();
- BasicBlock* F = schedule.NewBasicBlock();
- BasicBlock* G = schedule.exit();
-
- schedule.AddSuccessor(A, B);
- schedule.AddSuccessor(B, C);
- schedule.AddSuccessor(C, D);
- schedule.AddSuccessor(D, E);
- schedule.AddSuccessor(E, F);
- schedule.AddSuccessor(F, B);
- schedule.AddSuccessor(B, G);
-
- // Throw in extra backedges from time to time.
- if (i == 1) schedule.AddSuccessor(B, B);
- if (i == 2) schedule.AddSuccessor(C, B);
- if (i == 3) schedule.AddSuccessor(D, B);
- if (i == 4) schedule.AddSuccessor(E, B);
- if (i == 5) schedule.AddSuccessor(F, B);
-
- // Throw in extra loop exits from time to time.
- if (i == 6) schedule.AddSuccessor(B, G);
- if (i == 7) schedule.AddSuccessor(C, G);
- if (i == 8) schedule.AddSuccessor(D, G);
- if (i == 9) schedule.AddSuccessor(E, G);
- if (i == 10) schedule.AddSuccessor(F, G);
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, 7, true);
- BasicBlock* loop[] = {B, C, D, E, F};
- CheckLoopContains(loop, 5);
- }
-}
-
-
-TEST(RPOLoopNest1) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
-
- BasicBlock* A = schedule.entry();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.NewBasicBlock();
- BasicBlock* E = schedule.NewBasicBlock();
- BasicBlock* F = schedule.exit();
-
- schedule.AddSuccessor(A, B);
- schedule.AddSuccessor(B, C);
- schedule.AddSuccessor(C, D);
- schedule.AddSuccessor(D, C);
- schedule.AddSuccessor(D, E);
- schedule.AddSuccessor(E, B);
- schedule.AddSuccessor(E, F);
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, 6, true);
- BasicBlock* loop1[] = {B, C, D, E};
- CheckLoopContains(loop1, 4);
-
- BasicBlock* loop2[] = {C, D};
- CheckLoopContains(loop2, 2);
-}
-
-
-TEST(RPOLoopNest2) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
-
- BasicBlock* A = schedule.entry();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.NewBasicBlock();
- BasicBlock* E = schedule.NewBasicBlock();
- BasicBlock* F = schedule.NewBasicBlock();
- BasicBlock* G = schedule.NewBasicBlock();
- BasicBlock* H = schedule.exit();
-
- schedule.AddSuccessor(A, B);
- schedule.AddSuccessor(B, C);
- schedule.AddSuccessor(C, D);
- schedule.AddSuccessor(D, E);
- schedule.AddSuccessor(E, F);
- schedule.AddSuccessor(F, G);
- schedule.AddSuccessor(G, H);
-
- schedule.AddSuccessor(E, D);
- schedule.AddSuccessor(F, C);
- schedule.AddSuccessor(G, B);
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, 8, true);
- BasicBlock* loop1[] = {B, C, D, E, F, G};
- CheckLoopContains(loop1, 6);
-
- BasicBlock* loop2[] = {C, D, E, F};
- CheckLoopContains(loop2, 4);
-
- BasicBlock* loop3[] = {D, E};
- CheckLoopContains(loop3, 2);
-}
-
-
-TEST(RPOLoopFollow1) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
-
- TestLoop* loop1 = CreateLoop(&schedule, 1);
- TestLoop* loop2 = CreateLoop(&schedule, 1);
-
- BasicBlock* A = schedule.entry();
- BasicBlock* E = schedule.exit();
-
- schedule.AddSuccessor(A, loop1->header());
- schedule.AddSuccessor(loop1->header(), loop2->header());
- schedule.AddSuccessor(loop2->last(), E);
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
-
- CheckLoopContains(loop1->nodes, loop1->count);
-
- CHECK_EQ(schedule.BasicBlockCount(), static_cast<int>(order->size()));
- CheckLoopContains(loop1->nodes, loop1->count);
- CheckLoopContains(loop2->nodes, loop2->count);
- delete loop1;
- delete loop2;
-}
-
-
-TEST(RPOLoopFollow2) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
-
- TestLoop* loop1 = CreateLoop(&schedule, 1);
- TestLoop* loop2 = CreateLoop(&schedule, 1);
-
- BasicBlock* A = schedule.entry();
- BasicBlock* S = schedule.NewBasicBlock();
- BasicBlock* E = schedule.exit();
-
- schedule.AddSuccessor(A, loop1->header());
- schedule.AddSuccessor(loop1->header(), S);
- schedule.AddSuccessor(S, loop2->header());
- schedule.AddSuccessor(loop2->last(), E);
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
-
- CheckLoopContains(loop1->nodes, loop1->count);
-
- CHECK_EQ(schedule.BasicBlockCount(), static_cast<int>(order->size()));
- CheckLoopContains(loop1->nodes, loop1->count);
- CheckLoopContains(loop2->nodes, loop2->count);
- delete loop1;
- delete loop2;
-}
-
-
-TEST(RPOLoopFollowN) {
- HandleAndZoneScope scope;
-
- for (int size = 1; size < 5; size++) {
- for (int exit = 0; exit < size; exit++) {
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
- TestLoop* loop1 = CreateLoop(&schedule, size);
- TestLoop* loop2 = CreateLoop(&schedule, size);
- BasicBlock* A = schedule.entry();
- BasicBlock* E = schedule.exit();
-
- schedule.AddSuccessor(A, loop1->header());
- schedule.AddSuccessor(loop1->nodes[exit], loop2->header());
- schedule.AddSuccessor(loop2->nodes[exit], E);
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckLoopContains(loop1->nodes, loop1->count);
-
- CHECK_EQ(schedule.BasicBlockCount(), static_cast<int>(order->size()));
- CheckLoopContains(loop1->nodes, loop1->count);
- CheckLoopContains(loop2->nodes, loop2->count);
- delete loop1;
- delete loop2;
- }
- }
-}
-
-
-TEST(RPONestedLoopFollow1) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
-
- TestLoop* loop1 = CreateLoop(&schedule, 1);
- TestLoop* loop2 = CreateLoop(&schedule, 1);
-
- BasicBlock* A = schedule.entry();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* E = schedule.exit();
-
- schedule.AddSuccessor(A, B);
- schedule.AddSuccessor(B, loop1->header());
- schedule.AddSuccessor(loop1->header(), loop2->header());
- schedule.AddSuccessor(loop2->last(), C);
- schedule.AddSuccessor(C, E);
- schedule.AddSuccessor(C, B);
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
-
- CheckLoopContains(loop1->nodes, loop1->count);
-
- CHECK_EQ(schedule.BasicBlockCount(), static_cast<int>(order->size()));
- CheckLoopContains(loop1->nodes, loop1->count);
- CheckLoopContains(loop2->nodes, loop2->count);
-
- BasicBlock* loop3[] = {B, loop1->nodes[0], loop2->nodes[0], C};
- CheckLoopContains(loop3, 4);
- delete loop1;
- delete loop2;
-}
-
-
-TEST(RPOLoopBackedges1) {
- HandleAndZoneScope scope;
-
- int size = 8;
- for (int i = 0; i < size; i++) {
- for (int j = 0; j < size; j++) {
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
- BasicBlock* A = schedule.entry();
- BasicBlock* E = schedule.exit();
-
- TestLoop* loop1 = CreateLoop(&schedule, size);
- schedule.AddSuccessor(A, loop1->header());
- schedule.AddSuccessor(loop1->last(), E);
-
- schedule.AddSuccessor(loop1->nodes[i], loop1->header());
- schedule.AddSuccessor(loop1->nodes[j], E);
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- CheckLoopContains(loop1->nodes, loop1->count);
- delete loop1;
- }
- }
-}
-
-
-TEST(RPOLoopOutedges1) {
- HandleAndZoneScope scope;
-
- int size = 8;
- for (int i = 0; i < size; i++) {
- for (int j = 0; j < size; j++) {
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
- BasicBlock* A = schedule.entry();
- BasicBlock* D = schedule.NewBasicBlock();
- BasicBlock* E = schedule.exit();
-
- TestLoop* loop1 = CreateLoop(&schedule, size);
- schedule.AddSuccessor(A, loop1->header());
- schedule.AddSuccessor(loop1->last(), E);
-
- schedule.AddSuccessor(loop1->nodes[i], loop1->header());
- schedule.AddSuccessor(loop1->nodes[j], D);
- schedule.AddSuccessor(D, E);
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- CheckLoopContains(loop1->nodes, loop1->count);
- delete loop1;
- }
- }
-}
-
-
-TEST(RPOLoopOutedges2) {
- HandleAndZoneScope scope;
-
- int size = 8;
- for (int i = 0; i < size; i++) {
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
- BasicBlock* A = schedule.entry();
- BasicBlock* E = schedule.exit();
-
- TestLoop* loop1 = CreateLoop(&schedule, size);
- schedule.AddSuccessor(A, loop1->header());
- schedule.AddSuccessor(loop1->last(), E);
-
- for (int j = 0; j < size; j++) {
- BasicBlock* O = schedule.NewBasicBlock();
- schedule.AddSuccessor(loop1->nodes[j], O);
- schedule.AddSuccessor(O, E);
- }
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- CheckLoopContains(loop1->nodes, loop1->count);
- delete loop1;
- }
-}
-
-
-TEST(RPOLoopOutloops1) {
- HandleAndZoneScope scope;
-
- int size = 8;
- for (int i = 0; i < size; i++) {
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
- BasicBlock* A = schedule.entry();
- BasicBlock* E = schedule.exit();
- TestLoop* loop1 = CreateLoop(&schedule, size);
- schedule.AddSuccessor(A, loop1->header());
- schedule.AddSuccessor(loop1->last(), E);
-
- TestLoop** loopN = new TestLoop* [size];
- for (int j = 0; j < size; j++) {
- loopN[j] = CreateLoop(&schedule, 2);
- schedule.AddSuccessor(loop1->nodes[j], loopN[j]->header());
- schedule.AddSuccessor(loopN[j]->last(), E);
- }
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, schedule.BasicBlockCount(), true);
- CheckLoopContains(loop1->nodes, loop1->count);
-
- for (int j = 0; j < size; j++) {
- CheckLoopContains(loopN[j]->nodes, loopN[j]->count);
- delete loopN[j];
- }
- delete[] loopN;
- delete loop1;
- }
-}
-
-
-TEST(RPOLoopMultibackedge) {
- HandleAndZoneScope scope;
- Schedule schedule(scope.main_zone());
- Scheduler scheduler(scope.main_zone(), NULL, &schedule);
-
- BasicBlock* A = schedule.entry();
- BasicBlock* B = schedule.NewBasicBlock();
- BasicBlock* C = schedule.NewBasicBlock();
- BasicBlock* D = schedule.exit();
- BasicBlock* E = schedule.NewBasicBlock();
-
- schedule.AddSuccessor(A, B);
- schedule.AddSuccessor(B, C);
- schedule.AddSuccessor(B, D);
- schedule.AddSuccessor(B, E);
- schedule.AddSuccessor(C, B);
- schedule.AddSuccessor(D, B);
- schedule.AddSuccessor(E, B);
-
- BasicBlockVector* order = scheduler.ComputeSpecialRPO();
- CheckRPONumbers(order, 5, true);
-
- BasicBlock* loop1[] = {B, C, D, E};
- CheckLoopContains(loop1, 4);
-}
-
-
-TEST(BuildScheduleEmpty) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder builder(scope.main_zone());
- graph.SetStart(graph.NewNode(builder.Start()));
- graph.SetEnd(graph.NewNode(builder.End(), graph.start()));
-
- Scheduler scheduler(scope.main_zone());
- USE(scheduler.NewSchedule(&graph));
-}
-
-
-TEST(BuildScheduleOneParameter) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder builder(scope.main_zone());
- graph.SetStart(graph.NewNode(builder.Start()));
-
- Node* p1 = graph.NewNode(builder.Parameter(0));
- Node* ret = graph.NewNode(builder.Return(), p1, graph.start(), graph.start());
-
- graph.SetEnd(graph.NewNode(builder.End(), ret));
-
- Scheduler scheduler(scope.main_zone());
- USE(scheduler.NewSchedule(&graph));
-}
-
-
-static int GetScheduledNodeCount(Schedule* schedule) {
- int node_count = 0;
- for (BasicBlockVectorIter i = schedule->rpo_order()->begin();
- i != schedule->rpo_order()->end(); ++i) {
- BasicBlock* block = *i;
- for (BasicBlock::const_iterator j = block->begin(); j != block->end();
- ++j) {
- ++node_count;
- }
- BasicBlock::Control control = block->control_;
- if (control != BasicBlock::kNone) {
- ++node_count;
- }
- }
- return node_count;
-}
-
-
-static void PrintGraph(Graph* graph) {
- OFStream os(stdout);
- os << AsDOT(*graph);
-}
-
-
-static void PrintSchedule(Schedule* schedule) {
- OFStream os(stdout);
- os << *schedule << endl;
-}
-
-
-TEST(BuildScheduleIfSplit) {
- HandleAndZoneScope scope;
- Graph graph(scope.main_zone());
- CommonOperatorBuilder builder(scope.main_zone());
- JSOperatorBuilder js_builder(scope.main_zone());
- graph.SetStart(graph.NewNode(builder.Start()));
-
- Node* p1 = graph.NewNode(builder.Parameter(0));
- Node* p2 = graph.NewNode(builder.Parameter(1));
- Node* p3 = graph.NewNode(builder.Parameter(2));
- Node* p4 = graph.NewNode(builder.Parameter(3));
- Node* p5 = graph.NewNode(builder.Parameter(4));
- Node* cmp = graph.NewNode(js_builder.LessThanOrEqual(), p1, p2, p3,
- graph.start(), graph.start());
- Node* branch = graph.NewNode(builder.Branch(), cmp, graph.start());
- Node* true_branch = graph.NewNode(builder.IfTrue(), branch);
- Node* false_branch = graph.NewNode(builder.IfFalse(), branch);
-
- Node* ret1 = graph.NewNode(builder.Return(), p4, graph.start(), true_branch);
- Node* ret2 = graph.NewNode(builder.Return(), p5, graph.start(), false_branch);
- Node* merge = graph.NewNode(builder.Merge(2), ret1, ret2);
- graph.SetEnd(graph.NewNode(builder.End(), merge));
-
- PrintGraph(&graph);
-
- Scheduler scheduler(scope.main_zone());
- Schedule* schedule = scheduler.NewSchedule(&graph);
-
- PrintSchedule(schedule);
-
-
- CHECK_EQ(13, GetScheduledNodeCount(schedule));
-}
-
-
-TEST(BuildScheduleIfSplitWithEffects) {
- HandleAndZoneScope scope;
- Isolate* isolate = scope.main_isolate();
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common_builder(scope.main_zone());
- JSOperatorBuilder js_builder(scope.main_zone());
- Operator* op;
-
- Handle<Object> object =
- Handle<Object>(isolate->heap()->undefined_value(), isolate);
- PrintableUnique<Object> unique_constant =
- PrintableUnique<Object>::CreateUninitialized(scope.main_zone(), object);
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b, c, y) {
- // if (a < b) {
- // return a + b - c * c - a + y;
- // } else {
- // return c * c - a;
- // }
- // }
- Node* nil = graph.NewNode(common_builder.Dead());
- op = common_builder.End();
- Node* n23 = graph.NewNode(op, nil);
- USE(n23);
- op = common_builder.Merge(2);
- Node* n22 = graph.NewNode(op, nil, nil);
- USE(n22);
- op = common_builder.Return();
- Node* n16 = graph.NewNode(op, nil, nil, nil);
- USE(n16);
- op = js_builder.Add();
- Node* n15 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n15);
- op = js_builder.Subtract();
- Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n14);
- op = js_builder.Subtract();
- Node* n13 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n13);
- op = js_builder.Add();
- Node* n11 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n11);
- op = common_builder.Parameter(0);
- Node* n2 = graph.NewNode(op);
- USE(n2);
- n11->ReplaceInput(0, n2);
- op = common_builder.Parameter(0);
- Node* n3 = graph.NewNode(op);
- USE(n3);
- n11->ReplaceInput(1, n3);
- op = common_builder.HeapConstant(unique_constant);
- Node* n7 = graph.NewNode(op);
- USE(n7);
- n11->ReplaceInput(2, n7);
- op = js_builder.LessThan();
- Node* n8 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n8);
- n8->ReplaceInput(0, n2);
- n8->ReplaceInput(1, n3);
- n8->ReplaceInput(2, n7);
- op = common_builder.Start();
- Node* n0 = graph.NewNode(op);
- USE(n0);
- n8->ReplaceInput(3, n0);
- n8->ReplaceInput(4, n0);
- n11->ReplaceInput(3, n8);
- op = common_builder.IfTrue();
- Node* n10 = graph.NewNode(op, nil);
- USE(n10);
- op = common_builder.Branch();
- Node* n9 = graph.NewNode(op, nil, nil);
- USE(n9);
- n9->ReplaceInput(0, n8);
- n9->ReplaceInput(1, n0);
- n10->ReplaceInput(0, n9);
- n11->ReplaceInput(4, n10);
- n13->ReplaceInput(0, n11);
- op = js_builder.Multiply();
- Node* n12 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n12);
- op = common_builder.Parameter(0);
- Node* n4 = graph.NewNode(op);
- USE(n4);
- n12->ReplaceInput(0, n4);
- n12->ReplaceInput(1, n4);
- n12->ReplaceInput(2, n7);
- n12->ReplaceInput(3, n11);
- n12->ReplaceInput(4, n10);
- n13->ReplaceInput(1, n12);
- n13->ReplaceInput(2, n7);
- n13->ReplaceInput(3, n12);
- n13->ReplaceInput(4, n10);
- n14->ReplaceInput(0, n13);
- n14->ReplaceInput(1, n2);
- n14->ReplaceInput(2, n7);
- n14->ReplaceInput(3, n13);
- n14->ReplaceInput(4, n10);
- n15->ReplaceInput(0, n14);
- op = common_builder.Parameter(0);
- Node* n5 = graph.NewNode(op);
- USE(n5);
- n15->ReplaceInput(1, n5);
- n15->ReplaceInput(2, n7);
- n15->ReplaceInput(3, n14);
- n15->ReplaceInput(4, n10);
- n16->ReplaceInput(0, n15);
- n16->ReplaceInput(1, n15);
- n16->ReplaceInput(2, n10);
- n22->ReplaceInput(0, n16);
- op = common_builder.Return();
- Node* n21 = graph.NewNode(op, nil, nil, nil);
- USE(n21);
- op = js_builder.Subtract();
- Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n20);
- op = js_builder.Multiply();
- Node* n19 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n19);
- n19->ReplaceInput(0, n4);
- n19->ReplaceInput(1, n4);
- n19->ReplaceInput(2, n7);
- n19->ReplaceInput(3, n8);
- op = common_builder.IfFalse();
- Node* n18 = graph.NewNode(op, nil);
- USE(n18);
- n18->ReplaceInput(0, n9);
- n19->ReplaceInput(4, n18);
- n20->ReplaceInput(0, n19);
- n20->ReplaceInput(1, n2);
- n20->ReplaceInput(2, n7);
- n20->ReplaceInput(3, n19);
- n20->ReplaceInput(4, n18);
- n21->ReplaceInput(0, n20);
- n21->ReplaceInput(1, n20);
- n21->ReplaceInput(2, n18);
- n22->ReplaceInput(1, n21);
- n23->ReplaceInput(0, n22);
-
- graph.SetStart(n0);
- graph.SetEnd(n23);
-
- PrintGraph(&graph);
-
- Scheduler scheduler(scope.main_zone());
- Schedule* schedule = scheduler.NewSchedule(&graph);
-
- PrintSchedule(schedule);
-
- CHECK_EQ(20, GetScheduledNodeCount(schedule));
-}
-
-
-TEST(BuildScheduleSimpleLoop) {
- HandleAndZoneScope scope;
- Isolate* isolate = scope.main_isolate();
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common_builder(scope.main_zone());
- JSOperatorBuilder js_builder(scope.main_zone());
- Operator* op;
-
- Handle<Object> object =
- Handle<Object>(isolate->heap()->undefined_value(), isolate);
- PrintableUnique<Object> unique_constant =
- PrintableUnique<Object>::CreateUninitialized(scope.main_zone(), object);
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b) {
- // while (a < b) {
- // a++;
- // }
- // return a;
- // }
- Node* nil = graph.NewNode(common_builder.Dead());
- op = common_builder.End();
- Node* n20 = graph.NewNode(op, nil);
- USE(n20);
- op = common_builder.Return();
- Node* n19 = graph.NewNode(op, nil, nil, nil);
- USE(n19);
- op = common_builder.Phi(2);
- Node* n8 = graph.NewNode(op, nil, nil, nil);
- USE(n8);
- op = common_builder.Parameter(0);
- Node* n2 = graph.NewNode(op);
- USE(n2);
- n8->ReplaceInput(0, n2);
- op = js_builder.Add();
- Node* n18 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n18);
- op = js_builder.ToNumber();
- Node* n16 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n16);
- n16->ReplaceInput(0, n8);
- op = common_builder.HeapConstant(unique_constant);
- Node* n5 = graph.NewNode(op);
- USE(n5);
- n16->ReplaceInput(1, n5);
- op = js_builder.LessThan();
- Node* n12 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n12);
- n12->ReplaceInput(0, n8);
- op = common_builder.Phi(2);
- Node* n9 = graph.NewNode(op, nil, nil, nil);
- USE(n9);
- op = common_builder.Parameter(0);
- Node* n3 = graph.NewNode(op);
- USE(n3);
- n9->ReplaceInput(0, n3);
- n9->ReplaceInput(1, n9);
- op = common_builder.Loop(2);
- Node* n6 = graph.NewNode(op, nil, nil);
- USE(n6);
- op = common_builder.Start();
- Node* n0 = graph.NewNode(op);
- USE(n0);
- n6->ReplaceInput(0, n0);
- op = common_builder.IfTrue();
- Node* n14 = graph.NewNode(op, nil);
- USE(n14);
- op = common_builder.Branch();
- Node* n13 = graph.NewNode(op, nil, nil);
- USE(n13);
- n13->ReplaceInput(0, n12);
- n13->ReplaceInput(1, n6);
- n14->ReplaceInput(0, n13);
- n6->ReplaceInput(1, n14);
- n9->ReplaceInput(2, n6);
- n12->ReplaceInput(1, n9);
- n12->ReplaceInput(2, n5);
- op = common_builder.Phi(2);
- Node* n10 = graph.NewNode(op, nil, nil, nil);
- USE(n10);
- n10->ReplaceInput(0, n0);
- n10->ReplaceInput(1, n18);
- n10->ReplaceInput(2, n6);
- n12->ReplaceInput(3, n10);
- n12->ReplaceInput(4, n6);
- n16->ReplaceInput(2, n12);
- n16->ReplaceInput(3, n14);
- n18->ReplaceInput(0, n16);
- op = common_builder.NumberConstant(0);
- Node* n17 = graph.NewNode(op);
- USE(n17);
- n18->ReplaceInput(1, n17);
- n18->ReplaceInput(2, n5);
- n18->ReplaceInput(3, n16);
- n18->ReplaceInput(4, n14);
- n8->ReplaceInput(1, n18);
- n8->ReplaceInput(2, n6);
- n19->ReplaceInput(0, n8);
- n19->ReplaceInput(1, n12);
- op = common_builder.IfFalse();
- Node* n15 = graph.NewNode(op, nil);
- USE(n15);
- n15->ReplaceInput(0, n13);
- n19->ReplaceInput(2, n15);
- n20->ReplaceInput(0, n19);
-
- graph.SetStart(n0);
- graph.SetEnd(n20);
-
- PrintGraph(&graph);
-
- Scheduler scheduler(scope.main_zone());
- Schedule* schedule = scheduler.NewSchedule(&graph);
-
- PrintSchedule(schedule);
-
- CHECK_EQ(19, GetScheduledNodeCount(schedule));
-}
-
-
-TEST(BuildScheduleComplexLoops) {
- HandleAndZoneScope scope;
- Isolate* isolate = scope.main_isolate();
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common_builder(scope.main_zone());
- JSOperatorBuilder js_builder(scope.main_zone());
- Operator* op;
-
- Handle<Object> object =
- Handle<Object>(isolate->heap()->undefined_value(), isolate);
- PrintableUnique<Object> unique_constant =
- PrintableUnique<Object>::CreateUninitialized(scope.main_zone(), object);
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b, c) {
- // while (a < b) {
- // a++;
- // while (c < b) {
- // c++;
- // }
- // }
- // while (a < b) {
- // a += 2;
- // }
- // return a;
- // }
- Node* nil = graph.NewNode(common_builder.Dead());
- op = common_builder.End();
- Node* n46 = graph.NewNode(op, nil);
- USE(n46);
- op = common_builder.Return();
- Node* n45 = graph.NewNode(op, nil, nil, nil);
- USE(n45);
- op = common_builder.Phi(2);
- Node* n35 = graph.NewNode(op, nil, nil, nil);
- USE(n35);
- op = common_builder.Phi(2);
- Node* n9 = graph.NewNode(op, nil, nil, nil);
- USE(n9);
- op = common_builder.Parameter(0);
- Node* n2 = graph.NewNode(op);
- USE(n2);
- n9->ReplaceInput(0, n2);
- op = common_builder.Phi(2);
- Node* n23 = graph.NewNode(op, nil, nil, nil);
- USE(n23);
- op = js_builder.Add();
- Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n20);
- op = js_builder.ToNumber();
- Node* n18 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n18);
- n18->ReplaceInput(0, n9);
- op = common_builder.HeapConstant(unique_constant);
- Node* n6 = graph.NewNode(op);
- USE(n6);
- n18->ReplaceInput(1, n6);
- op = js_builder.LessThan();
- Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n14);
- n14->ReplaceInput(0, n9);
- op = common_builder.Phi(2);
- Node* n10 = graph.NewNode(op, nil, nil, nil);
- USE(n10);
- op = common_builder.Parameter(0);
- Node* n3 = graph.NewNode(op);
- USE(n3);
- n10->ReplaceInput(0, n3);
- op = common_builder.Phi(2);
- Node* n24 = graph.NewNode(op, nil, nil, nil);
- USE(n24);
- n24->ReplaceInput(0, n10);
- n24->ReplaceInput(1, n24);
- op = common_builder.Loop(2);
- Node* n21 = graph.NewNode(op, nil, nil);
- USE(n21);
- op = common_builder.IfTrue();
- Node* n16 = graph.NewNode(op, nil);
- USE(n16);
- op = common_builder.Branch();
- Node* n15 = graph.NewNode(op, nil, nil);
- USE(n15);
- n15->ReplaceInput(0, n14);
- op = common_builder.Loop(2);
- Node* n7 = graph.NewNode(op, nil, nil);
- USE(n7);
- op = common_builder.Start();
- Node* n0 = graph.NewNode(op);
- USE(n0);
- n7->ReplaceInput(0, n0);
- op = common_builder.IfFalse();
- Node* n30 = graph.NewNode(op, nil);
- USE(n30);
- op = common_builder.Branch();
- Node* n28 = graph.NewNode(op, nil, nil);
- USE(n28);
- op = js_builder.LessThan();
- Node* n27 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n27);
- op = common_builder.Phi(2);
- Node* n25 = graph.NewNode(op, nil, nil, nil);
- USE(n25);
- op = common_builder.Phi(2);
- Node* n11 = graph.NewNode(op, nil, nil, nil);
- USE(n11);
- op = common_builder.Parameter(0);
- Node* n4 = graph.NewNode(op);
- USE(n4);
- n11->ReplaceInput(0, n4);
- n11->ReplaceInput(1, n25);
- n11->ReplaceInput(2, n7);
- n25->ReplaceInput(0, n11);
- op = js_builder.Add();
- Node* n32 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n32);
- op = js_builder.ToNumber();
- Node* n31 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n31);
- n31->ReplaceInput(0, n25);
- n31->ReplaceInput(1, n6);
- n31->ReplaceInput(2, n27);
- op = common_builder.IfTrue();
- Node* n29 = graph.NewNode(op, nil);
- USE(n29);
- n29->ReplaceInput(0, n28);
- n31->ReplaceInput(3, n29);
- n32->ReplaceInput(0, n31);
- op = common_builder.NumberConstant(0);
- Node* n19 = graph.NewNode(op);
- USE(n19);
- n32->ReplaceInput(1, n19);
- n32->ReplaceInput(2, n6);
- n32->ReplaceInput(3, n31);
- n32->ReplaceInput(4, n29);
- n25->ReplaceInput(1, n32);
- n25->ReplaceInput(2, n21);
- n27->ReplaceInput(0, n25);
- n27->ReplaceInput(1, n24);
- n27->ReplaceInput(2, n6);
- op = common_builder.Phi(2);
- Node* n26 = graph.NewNode(op, nil, nil, nil);
- USE(n26);
- n26->ReplaceInput(0, n20);
- n26->ReplaceInput(1, n32);
- n26->ReplaceInput(2, n21);
- n27->ReplaceInput(3, n26);
- n27->ReplaceInput(4, n21);
- n28->ReplaceInput(0, n27);
- n28->ReplaceInput(1, n21);
- n30->ReplaceInput(0, n28);
- n7->ReplaceInput(1, n30);
- n15->ReplaceInput(1, n7);
- n16->ReplaceInput(0, n15);
- n21->ReplaceInput(0, n16);
- n21->ReplaceInput(1, n29);
- n24->ReplaceInput(2, n21);
- n10->ReplaceInput(1, n24);
- n10->ReplaceInput(2, n7);
- n14->ReplaceInput(1, n10);
- n14->ReplaceInput(2, n6);
- op = common_builder.Phi(2);
- Node* n12 = graph.NewNode(op, nil, nil, nil);
- USE(n12);
- n12->ReplaceInput(0, n0);
- n12->ReplaceInput(1, n27);
- n12->ReplaceInput(2, n7);
- n14->ReplaceInput(3, n12);
- n14->ReplaceInput(4, n7);
- n18->ReplaceInput(2, n14);
- n18->ReplaceInput(3, n16);
- n20->ReplaceInput(0, n18);
- n20->ReplaceInput(1, n19);
- n20->ReplaceInput(2, n6);
- n20->ReplaceInput(3, n18);
- n20->ReplaceInput(4, n16);
- n23->ReplaceInput(0, n20);
- n23->ReplaceInput(1, n23);
- n23->ReplaceInput(2, n21);
- n9->ReplaceInput(1, n23);
- n9->ReplaceInput(2, n7);
- n35->ReplaceInput(0, n9);
- op = js_builder.Add();
- Node* n44 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n44);
- n44->ReplaceInput(0, n35);
- op = common_builder.NumberConstant(0);
- Node* n43 = graph.NewNode(op);
- USE(n43);
- n44->ReplaceInput(1, n43);
- n44->ReplaceInput(2, n6);
- op = js_builder.LessThan();
- Node* n39 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n39);
- n39->ReplaceInput(0, n35);
- op = common_builder.Phi(2);
- Node* n36 = graph.NewNode(op, nil, nil, nil);
- USE(n36);
- n36->ReplaceInput(0, n10);
- n36->ReplaceInput(1, n36);
- op = common_builder.Loop(2);
- Node* n33 = graph.NewNode(op, nil, nil);
- USE(n33);
- op = common_builder.IfFalse();
- Node* n17 = graph.NewNode(op, nil);
- USE(n17);
- n17->ReplaceInput(0, n15);
- n33->ReplaceInput(0, n17);
- op = common_builder.IfTrue();
- Node* n41 = graph.NewNode(op, nil);
- USE(n41);
- op = common_builder.Branch();
- Node* n40 = graph.NewNode(op, nil, nil);
- USE(n40);
- n40->ReplaceInput(0, n39);
- n40->ReplaceInput(1, n33);
- n41->ReplaceInput(0, n40);
- n33->ReplaceInput(1, n41);
- n36->ReplaceInput(2, n33);
- n39->ReplaceInput(1, n36);
- n39->ReplaceInput(2, n6);
- op = common_builder.Phi(2);
- Node* n38 = graph.NewNode(op, nil, nil, nil);
- USE(n38);
- n38->ReplaceInput(0, n14);
- n38->ReplaceInput(1, n44);
- n38->ReplaceInput(2, n33);
- n39->ReplaceInput(3, n38);
- n39->ReplaceInput(4, n33);
- n44->ReplaceInput(3, n39);
- n44->ReplaceInput(4, n41);
- n35->ReplaceInput(1, n44);
- n35->ReplaceInput(2, n33);
- n45->ReplaceInput(0, n35);
- n45->ReplaceInput(1, n39);
- op = common_builder.IfFalse();
- Node* n42 = graph.NewNode(op, nil);
- USE(n42);
- n42->ReplaceInput(0, n40);
- n45->ReplaceInput(2, n42);
- n46->ReplaceInput(0, n45);
-
- graph.SetStart(n0);
- graph.SetEnd(n46);
-
- PrintGraph(&graph);
-
- Scheduler scheduler(scope.main_zone());
- Schedule* schedule = scheduler.NewSchedule(&graph);
-
- PrintSchedule(schedule);
-
- CHECK_EQ(46, GetScheduledNodeCount(schedule));
-}
-
-
-TEST(BuildScheduleBreakAndContinue) {
- HandleAndZoneScope scope;
- Isolate* isolate = scope.main_isolate();
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common_builder(scope.main_zone());
- JSOperatorBuilder js_builder(scope.main_zone());
- Operator* op;
-
- Handle<Object> object =
- Handle<Object>(isolate->heap()->undefined_value(), isolate);
- PrintableUnique<Object> unique_constant =
- PrintableUnique<Object>::CreateUninitialized(scope.main_zone(), object);
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b, c) {
- // var d = 0;
- // while (a < b) {
- // a++;
- // while (c < b) {
- // c++;
- // if (d == 0) break;
- // a++;
- // }
- // if (a == 1) continue;
- // d++;
- // }
- // return a + d;
- // }
- Node* nil = graph.NewNode(common_builder.Dead());
- op = common_builder.End();
- Node* n58 = graph.NewNode(op, nil);
- USE(n58);
- op = common_builder.Return();
- Node* n57 = graph.NewNode(op, nil, nil, nil);
- USE(n57);
- op = js_builder.Add();
- Node* n56 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n56);
- op = common_builder.Phi(2);
- Node* n10 = graph.NewNode(op, nil, nil, nil);
- USE(n10);
- op = common_builder.Parameter(0);
- Node* n2 = graph.NewNode(op);
- USE(n2);
- n10->ReplaceInput(0, n2);
- op = common_builder.Phi(2);
- Node* n25 = graph.NewNode(op, nil, nil, nil);
- USE(n25);
- op = js_builder.Add();
- Node* n22 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n22);
- op = js_builder.ToNumber();
- Node* n20 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n20);
- n20->ReplaceInput(0, n10);
- op = common_builder.HeapConstant(unique_constant);
- Node* n6 = graph.NewNode(op);
- USE(n6);
- n20->ReplaceInput(1, n6);
- op = js_builder.LessThan();
- Node* n16 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n16);
- n16->ReplaceInput(0, n10);
- op = common_builder.Phi(2);
- Node* n11 = graph.NewNode(op, nil, nil, nil);
- USE(n11);
- op = common_builder.Parameter(0);
- Node* n3 = graph.NewNode(op);
- USE(n3);
- n11->ReplaceInput(0, n3);
- op = common_builder.Phi(2);
- Node* n26 = graph.NewNode(op, nil, nil, nil);
- USE(n26);
- n26->ReplaceInput(0, n11);
- n26->ReplaceInput(1, n26);
- op = common_builder.Loop(2);
- Node* n23 = graph.NewNode(op, nil, nil);
- USE(n23);
- op = common_builder.IfTrue();
- Node* n18 = graph.NewNode(op, nil);
- USE(n18);
- op = common_builder.Branch();
- Node* n17 = graph.NewNode(op, nil, nil);
- USE(n17);
- n17->ReplaceInput(0, n16);
- op = common_builder.Loop(2);
- Node* n8 = graph.NewNode(op, nil, nil);
- USE(n8);
- op = common_builder.Start();
- Node* n0 = graph.NewNode(op);
- USE(n0);
- n8->ReplaceInput(0, n0);
- op = common_builder.Merge(2);
- Node* n53 = graph.NewNode(op, nil, nil);
- USE(n53);
- op = common_builder.IfTrue();
- Node* n49 = graph.NewNode(op, nil);
- USE(n49);
- op = common_builder.Branch();
- Node* n48 = graph.NewNode(op, nil, nil);
- USE(n48);
- op = js_builder.Equal();
- Node* n47 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n47);
- n47->ReplaceInput(0, n25);
- op = common_builder.NumberConstant(0);
- Node* n46 = graph.NewNode(op);
- USE(n46);
- n47->ReplaceInput(1, n46);
- n47->ReplaceInput(2, n6);
- op = common_builder.Phi(2);
- Node* n42 = graph.NewNode(op, nil, nil, nil);
- USE(n42);
- op = js_builder.LessThan();
- Node* n30 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n30);
- op = common_builder.Phi(2);
- Node* n27 = graph.NewNode(op, nil, nil, nil);
- USE(n27);
- op = common_builder.Phi(2);
- Node* n12 = graph.NewNode(op, nil, nil, nil);
- USE(n12);
- op = common_builder.Parameter(0);
- Node* n4 = graph.NewNode(op);
- USE(n4);
- n12->ReplaceInput(0, n4);
- op = common_builder.Phi(2);
- Node* n41 = graph.NewNode(op, nil, nil, nil);
- USE(n41);
- n41->ReplaceInput(0, n27);
- op = js_builder.Add();
- Node* n35 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n35);
- op = js_builder.ToNumber();
- Node* n34 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n34);
- n34->ReplaceInput(0, n27);
- n34->ReplaceInput(1, n6);
- n34->ReplaceInput(2, n30);
- op = common_builder.IfTrue();
- Node* n32 = graph.NewNode(op, nil);
- USE(n32);
- op = common_builder.Branch();
- Node* n31 = graph.NewNode(op, nil, nil);
- USE(n31);
- n31->ReplaceInput(0, n30);
- n31->ReplaceInput(1, n23);
- n32->ReplaceInput(0, n31);
- n34->ReplaceInput(3, n32);
- n35->ReplaceInput(0, n34);
- op = common_builder.NumberConstant(0);
- Node* n21 = graph.NewNode(op);
- USE(n21);
- n35->ReplaceInput(1, n21);
- n35->ReplaceInput(2, n6);
- n35->ReplaceInput(3, n34);
- n35->ReplaceInput(4, n32);
- n41->ReplaceInput(1, n35);
- op = common_builder.Merge(2);
- Node* n40 = graph.NewNode(op, nil, nil);
- USE(n40);
- op = common_builder.IfFalse();
- Node* n33 = graph.NewNode(op, nil);
- USE(n33);
- n33->ReplaceInput(0, n31);
- n40->ReplaceInput(0, n33);
- op = common_builder.IfTrue();
- Node* n39 = graph.NewNode(op, nil);
- USE(n39);
- op = common_builder.Branch();
- Node* n38 = graph.NewNode(op, nil, nil);
- USE(n38);
- op = js_builder.Equal();
- Node* n37 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n37);
- op = common_builder.Phi(2);
- Node* n28 = graph.NewNode(op, nil, nil, nil);
- USE(n28);
- op = common_builder.Phi(2);
- Node* n13 = graph.NewNode(op, nil, nil, nil);
- USE(n13);
- op = common_builder.NumberConstant(0);
- Node* n7 = graph.NewNode(op);
- USE(n7);
- n13->ReplaceInput(0, n7);
- op = common_builder.Phi(2);
- Node* n54 = graph.NewNode(op, nil, nil, nil);
- USE(n54);
- n54->ReplaceInput(0, n28);
- op = js_builder.Add();
- Node* n52 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n52);
- op = js_builder.ToNumber();
- Node* n51 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n51);
- n51->ReplaceInput(0, n28);
- n51->ReplaceInput(1, n6);
- n51->ReplaceInput(2, n47);
- op = common_builder.IfFalse();
- Node* n50 = graph.NewNode(op, nil);
- USE(n50);
- n50->ReplaceInput(0, n48);
- n51->ReplaceInput(3, n50);
- n52->ReplaceInput(0, n51);
- n52->ReplaceInput(1, n21);
- n52->ReplaceInput(2, n6);
- n52->ReplaceInput(3, n51);
- n52->ReplaceInput(4, n50);
- n54->ReplaceInput(1, n52);
- n54->ReplaceInput(2, n53);
- n13->ReplaceInput(1, n54);
- n13->ReplaceInput(2, n8);
- n28->ReplaceInput(0, n13);
- n28->ReplaceInput(1, n28);
- n28->ReplaceInput(2, n23);
- n37->ReplaceInput(0, n28);
- op = common_builder.NumberConstant(0);
- Node* n36 = graph.NewNode(op);
- USE(n36);
- n37->ReplaceInput(1, n36);
- n37->ReplaceInput(2, n6);
- n37->ReplaceInput(3, n35);
- n37->ReplaceInput(4, n32);
- n38->ReplaceInput(0, n37);
- n38->ReplaceInput(1, n32);
- n39->ReplaceInput(0, n38);
- n40->ReplaceInput(1, n39);
- n41->ReplaceInput(2, n40);
- n12->ReplaceInput(1, n41);
- n12->ReplaceInput(2, n8);
- n27->ReplaceInput(0, n12);
- n27->ReplaceInput(1, n35);
- n27->ReplaceInput(2, n23);
- n30->ReplaceInput(0, n27);
- n30->ReplaceInput(1, n26);
- n30->ReplaceInput(2, n6);
- op = common_builder.Phi(2);
- Node* n29 = graph.NewNode(op, nil, nil, nil);
- USE(n29);
- n29->ReplaceInput(0, n22);
- op = js_builder.Add();
- Node* n45 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n45);
- op = js_builder.ToNumber();
- Node* n44 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n44);
- n44->ReplaceInput(0, n25);
- n44->ReplaceInput(1, n6);
- n44->ReplaceInput(2, n37);
- op = common_builder.IfFalse();
- Node* n43 = graph.NewNode(op, nil);
- USE(n43);
- n43->ReplaceInput(0, n38);
- n44->ReplaceInput(3, n43);
- n45->ReplaceInput(0, n44);
- n45->ReplaceInput(1, n21);
- n45->ReplaceInput(2, n6);
- n45->ReplaceInput(3, n44);
- n45->ReplaceInput(4, n43);
- n29->ReplaceInput(1, n45);
- n29->ReplaceInput(2, n23);
- n30->ReplaceInput(3, n29);
- n30->ReplaceInput(4, n23);
- n42->ReplaceInput(0, n30);
- n42->ReplaceInput(1, n37);
- n42->ReplaceInput(2, n40);
- n47->ReplaceInput(3, n42);
- n47->ReplaceInput(4, n40);
- n48->ReplaceInput(0, n47);
- n48->ReplaceInput(1, n40);
- n49->ReplaceInput(0, n48);
- n53->ReplaceInput(0, n49);
- n53->ReplaceInput(1, n50);
- n8->ReplaceInput(1, n53);
- n17->ReplaceInput(1, n8);
- n18->ReplaceInput(0, n17);
- n23->ReplaceInput(0, n18);
- n23->ReplaceInput(1, n43);
- n26->ReplaceInput(2, n23);
- n11->ReplaceInput(1, n26);
- n11->ReplaceInput(2, n8);
- n16->ReplaceInput(1, n11);
- n16->ReplaceInput(2, n6);
- op = common_builder.Phi(2);
- Node* n14 = graph.NewNode(op, nil, nil, nil);
- USE(n14);
- n14->ReplaceInput(0, n0);
- op = common_builder.Phi(2);
- Node* n55 = graph.NewNode(op, nil, nil, nil);
- USE(n55);
- n55->ReplaceInput(0, n47);
- n55->ReplaceInput(1, n52);
- n55->ReplaceInput(2, n53);
- n14->ReplaceInput(1, n55);
- n14->ReplaceInput(2, n8);
- n16->ReplaceInput(3, n14);
- n16->ReplaceInput(4, n8);
- n20->ReplaceInput(2, n16);
- n20->ReplaceInput(3, n18);
- n22->ReplaceInput(0, n20);
- n22->ReplaceInput(1, n21);
- n22->ReplaceInput(2, n6);
- n22->ReplaceInput(3, n20);
- n22->ReplaceInput(4, n18);
- n25->ReplaceInput(0, n22);
- n25->ReplaceInput(1, n45);
- n25->ReplaceInput(2, n23);
- n10->ReplaceInput(1, n25);
- n10->ReplaceInput(2, n8);
- n56->ReplaceInput(0, n10);
- n56->ReplaceInput(1, n13);
- n56->ReplaceInput(2, n6);
- n56->ReplaceInput(3, n16);
- op = common_builder.IfFalse();
- Node* n19 = graph.NewNode(op, nil);
- USE(n19);
- n19->ReplaceInput(0, n17);
- n56->ReplaceInput(4, n19);
- n57->ReplaceInput(0, n56);
- n57->ReplaceInput(1, n56);
- n57->ReplaceInput(2, n19);
- n58->ReplaceInput(0, n57);
-
- graph.SetStart(n0);
- graph.SetEnd(n58);
-
- PrintGraph(&graph);
-
- Scheduler scheduler(scope.main_zone());
- Schedule* schedule = scheduler.NewSchedule(&graph);
-
- PrintSchedule(schedule);
-
- CHECK_EQ(62, GetScheduledNodeCount(schedule));
-}
-
-
-TEST(BuildScheduleSimpleLoopWithCodeMotion) {
- HandleAndZoneScope scope;
- Isolate* isolate = scope.main_isolate();
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common_builder(scope.main_zone());
- JSOperatorBuilder js_builder(scope.main_zone());
- MachineOperatorBuilder machine_builder(scope.main_zone(), kMachineWord32);
- Operator* op;
-
- Handle<Object> object =
- Handle<Object>(isolate->heap()->undefined_value(), isolate);
- PrintableUnique<Object> unique_constant =
- PrintableUnique<Object>::CreateUninitialized(scope.main_zone(), object);
-
- // Manually transcripted code for:
- // function turbo_fan_test(a, b, c) {
- // while (a < b) {
- // a += b + c;
- // }
- // return a;
- // }
- Node* nil = graph.NewNode(common_builder.Dead());
- op = common_builder.End();
- Node* n22 = graph.NewNode(op, nil);
- USE(n22);
- op = common_builder.Return();
- Node* n21 = graph.NewNode(op, nil, nil, nil);
- USE(n21);
- op = common_builder.Phi(2);
- Node* n9 = graph.NewNode(op, nil, nil, nil);
- USE(n9);
- op = common_builder.Parameter(0);
- Node* n2 = graph.NewNode(op);
- USE(n2);
- n9->ReplaceInput(0, n2);
- op = js_builder.Add();
- Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n20);
- n20->ReplaceInput(0, n9);
- op = machine_builder.Int32Add();
- Node* n19 = graph.NewNode(op, nil, nil);
- USE(n19);
- op = common_builder.Phi(2);
- Node* n10 = graph.NewNode(op, nil, nil, nil);
- USE(n10);
- op = common_builder.Parameter(0);
- Node* n3 = graph.NewNode(op);
- USE(n3);
- n10->ReplaceInput(0, n3);
- n10->ReplaceInput(1, n10);
- op = common_builder.Loop(2);
- Node* n7 = graph.NewNode(op, nil, nil);
- USE(n7);
- op = common_builder.Start();
- Node* n0 = graph.NewNode(op);
- USE(n0);
- n7->ReplaceInput(0, n0);
- op = common_builder.IfTrue();
- Node* n17 = graph.NewNode(op, nil);
- USE(n17);
- op = common_builder.Branch();
- Node* n16 = graph.NewNode(op, nil, nil);
- USE(n16);
- op = js_builder.ToBoolean();
- Node* n15 = graph.NewNode(op, nil, nil, nil, nil);
- USE(n15);
- op = js_builder.LessThan();
- Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil);
- USE(n14);
- n14->ReplaceInput(0, n9);
- n14->ReplaceInput(1, n10);
- op = common_builder.HeapConstant(unique_constant);
- Node* n6 = graph.NewNode(op);
- USE(n6);
- n14->ReplaceInput(2, n6);
- op = common_builder.Phi(2);
- Node* n12 = graph.NewNode(op, nil, nil, nil);
- USE(n12);
- n12->ReplaceInput(0, n0);
- n12->ReplaceInput(1, n20);
- n12->ReplaceInput(2, n7);
- n14->ReplaceInput(3, n12);
- n14->ReplaceInput(4, n7);
- n15->ReplaceInput(0, n14);
- n15->ReplaceInput(1, n6);
- n15->ReplaceInput(2, n14);
- n15->ReplaceInput(3, n7);
- n16->ReplaceInput(0, n15);
- n16->ReplaceInput(1, n7);
- n17->ReplaceInput(0, n16);
- n7->ReplaceInput(1, n17);
- n10->ReplaceInput(2, n7);
- n19->ReplaceInput(0, n2);
- op = common_builder.Phi(2);
- Node* n11 = graph.NewNode(op, nil, nil, nil);
- USE(n11);
- op = common_builder.Parameter(0);
- Node* n4 = graph.NewNode(op);
- USE(n4);
- n11->ReplaceInput(0, n4);
- n11->ReplaceInput(1, n11);
- n11->ReplaceInput(2, n7);
- n19->ReplaceInput(1, n3);
- n20->ReplaceInput(1, n19);
- n20->ReplaceInput(2, n6);
- n20->ReplaceInput(3, n19);
- n20->ReplaceInput(4, n17);
- n9->ReplaceInput(1, n20);
- n9->ReplaceInput(2, n7);
- n21->ReplaceInput(0, n9);
- n21->ReplaceInput(1, n15);
- op = common_builder.IfFalse();
- Node* n18 = graph.NewNode(op, nil);
- USE(n18);
- n18->ReplaceInput(0, n16);
- n21->ReplaceInput(2, n18);
- n22->ReplaceInput(0, n21);
-
- graph.SetStart(n0);
- graph.SetEnd(n22);
-
- PrintGraph(&graph);
-
- Scheduler scheduler(scope.main_zone());
- Schedule* schedule = scheduler.NewSchedule(&graph);
-
- PrintSchedule(schedule);
-
- CHECK_EQ(19, GetScheduledNodeCount(schedule));
-
- // Make sure the integer-only add gets hoisted to a different block that the
- // JSAdd.
- CHECK(schedule->block(n19) != schedule->block(n20));
-}
-
-
-// So we can get a real JS function.
-static Handle<JSFunction> Compile(const char* source) {
- Isolate* isolate = CcTest::i_isolate();
- Handle<String> source_code = isolate->factory()
- ->NewStringFromUtf8(CStrVector(source))
- .ToHandleChecked();
- Handle<SharedFunctionInfo> shared_function = Compiler::CompileScript(
- source_code, Handle<String>(), 0, 0, false,
- Handle<Context>(isolate->native_context()), NULL, NULL,
- v8::ScriptCompiler::kNoCompileOptions, NOT_NATIVES_CODE);
- return isolate->factory()->NewFunctionFromSharedFunctionInfo(
- shared_function, isolate->native_context());
-}
-
-
-TEST(BuildScheduleTrivialLazyDeoptCall) {
- HandleAndZoneScope scope;
- Isolate* isolate = scope.main_isolate();
- Graph graph(scope.main_zone());
- CommonOperatorBuilder common_builder(scope.main_zone());
- JSOperatorBuilder js_builder(scope.main_zone());
-
- InitializedHandleScope handles;
- Handle<JSFunction> function = Compile("m()");
- CompilationInfoWithZone info(function);
- Linkage linkage(&info);
-
- // Manually transcribed code for:
- // function turbo_fan_test() {
- // m();
- // }
- // where m can lazy deopt (so it has a deopt block associated with it).
-
-
- // Start //
- // ^ //
- // | (EC) //
- // | //
- // /------> Call <--------------\ //
- // / ^ ^ \ //
- // / | | \ undef //
- // / / \ \ ^ //
- // (E) | (C) / \ (C) \ (E) | //
- // | Continuation LazyDeoptimization | | //
- // \___ ^ ^ / | //
- // \ | | ______/ Framestate //
- // undef \ | (VC) | (C) / ^ //
- // \ \ | | / / //
- // Return Deoptimization ----------/ //
- // ^ ^ //
- // \ / //
- // (C) \ / (C) //
- // \ / //
- // Merge //
- // ^ //
- // | //
- // End //
-
- Handle<Object> undef_object =
- Handle<Object>(isolate->heap()->undefined_value(), isolate);
- PrintableUnique<Object> undef_constant =
- PrintableUnique<Object>::CreateUninitialized(scope.main_zone(),
- undef_object);
-
- Node* undef_node = graph.NewNode(common_builder.HeapConstant(undef_constant));
-
- Node* start_node = graph.NewNode(common_builder.Start());
-
- CallDescriptor* descriptor = linkage.GetJSCallDescriptor(0);
- Node* call_node = graph.NewNode(common_builder.Call(descriptor),
- undef_node, // function
- undef_node, // context
- start_node, // effect
- start_node); // control
-
- Node* cont_node = graph.NewNode(common_builder.Continuation(), call_node);
- Node* lazy_deopt_node =
- graph.NewNode(common_builder.LazyDeoptimization(), call_node);
-
- FrameStateDescriptor stateDescriptor(BailoutId(1234));
- Node* state_node = graph.NewNode(common_builder.FrameState(stateDescriptor));
-
- Node* return_node = graph.NewNode(common_builder.Return(),
- undef_node, // return value
- call_node, // effect
- cont_node); // control
- Node* deoptimization_node = graph.NewNode(common_builder.Deoptimize(),
- state_node, // deopt environment
- call_node, // effect
- lazy_deopt_node); // control
-
- Node* merge_node =
- graph.NewNode(common_builder.Merge(2), return_node, deoptimization_node);
-
- Node* end_node = graph.NewNode(common_builder.End(), merge_node);
-
- graph.SetStart(start_node);
- graph.SetEnd(end_node);
-
- PrintGraph(&graph);
-
- Scheduler scheduler(scope.main_zone());
- Schedule* schedule = scheduler.NewSchedule(&graph);
-
- PrintSchedule(schedule);
-
- // Tests:
- // Continuation and deopt have basic blocks.
- BasicBlock* cont_block = schedule->block(cont_node);
- BasicBlock* deopt_block = schedule->block(lazy_deopt_node);
- BasicBlock* call_block = schedule->block(call_node);
- CHECK_NE(NULL, cont_block);
- CHECK_NE(NULL, deopt_block);
- CHECK_NE(NULL, call_block);
- // The basic blocks are different.
- CHECK_NE(cont_block, deopt_block);
- CHECK_NE(cont_block, call_block);
- CHECK_NE(deopt_block, call_block);
- // The call node finishes its own basic block.
- CHECK_EQ(BasicBlock::kCall, call_block->control_);
- CHECK_EQ(call_node, call_block->control_input_);
- // The lazy deopt block is deferred.
- CHECK(deopt_block->deferred_);
- CHECK(!call_block->deferred_);
- CHECK(!cont_block->deferred_);
- // The lazy deopt block contains framestate + bailout (and nothing else).
- CHECK_EQ(deoptimization_node, deopt_block->control_input_);
- CHECK_EQ(2, deopt_block->nodes_.size());
- CHECK_EQ(lazy_deopt_node, deopt_block->nodes_[0]);
- CHECK_EQ(state_node, deopt_block->nodes_[1]);
-}
+++ /dev/null
-// 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 <limits>
-
-#include "src/compiler/control-builders.h"
-#include "src/compiler/node-properties-inl.h"
-#include "src/compiler/pipeline.h"
-#include "src/compiler/simplified-lowering.h"
-#include "src/compiler/simplified-node-factory.h"
-#include "src/compiler/typer.h"
-#include "src/compiler/verifier.h"
-#include "src/execution.h"
-#include "src/parser.h"
-#include "src/rewriter.h"
-#include "src/scopes.h"
-#include "test/cctest/cctest.h"
-#include "test/cctest/compiler/codegen-tester.h"
-#include "test/cctest/compiler/graph-builder-tester.h"
-#include "test/cctest/compiler/value-helper.h"
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-template <typename ReturnType>
-class SimplifiedGraphBuilderTester : public GraphBuilderTester<ReturnType> {
- public:
- SimplifiedGraphBuilderTester(MachineRepresentation p0 = kMachineLast,
- MachineRepresentation p1 = kMachineLast,
- MachineRepresentation p2 = kMachineLast,
- MachineRepresentation p3 = kMachineLast,
- MachineRepresentation p4 = kMachineLast)
- : GraphBuilderTester<ReturnType>(p0, p1, p2, p3, p4) {}
-
- // Close graph and lower one node.
- void Lower(Node* node) {
- this->End();
- Typer typer(this->zone());
- CommonOperatorBuilder common(this->zone());
- SourcePositionTable source_positions(this->graph());
- JSGraph jsgraph(this->graph(), &common, &typer);
- SimplifiedLowering lowering(&jsgraph, &source_positions);
- if (node == NULL) {
- lowering.LowerAllNodes();
- } else {
- lowering.Lower(node);
- }
- }
-
- // Close graph and lower all nodes.
- void LowerAllNodes() { Lower(NULL); }
-
- void StoreFloat64(Node* node, double* ptr) {
- Node* ptr_node = this->PointerConstant(ptr);
- this->Store(kMachineFloat64, ptr_node, node);
- }
-
- Node* LoadInt32(int32_t* ptr) {
- Node* ptr_node = this->PointerConstant(ptr);
- return this->Load(kMachineWord32, ptr_node);
- }
-
- Node* LoadUint32(uint32_t* ptr) {
- Node* ptr_node = this->PointerConstant(ptr);
- return this->Load(kMachineWord32, ptr_node);
- }
-
- Node* LoadFloat64(double* ptr) {
- Node* ptr_node = this->PointerConstant(ptr);
- return this->Load(kMachineFloat64, ptr_node);
- }
-
- Factory* factory() { return this->isolate()->factory(); }
- Heap* heap() { return this->isolate()->heap(); }
-};
-
-
-class SimplifiedGraphBuilderJSTester
- : public SimplifiedGraphBuilderTester<Object*> {
- public:
- SimplifiedGraphBuilderJSTester()
- : SimplifiedGraphBuilderTester<Object*>(),
- f_(v8::Utils::OpenHandle(*v8::Handle<v8::Function>::Cast(CompileRun(
- "(function() { 'use strict'; return 2.7123; })")))),
- swapped_(false) {
- set_current_context(HeapConstant(handle(f_->context())));
- }
-
- template <typename T>
- T* CallJS() {
- if (!swapped_) {
- Compile();
- }
- Handle<Object>* args = NULL;
- MaybeHandle<Object> result = Execution::Call(
- isolate(), f_, factory()->undefined_value(), 0, args, false);
- return T::cast(*result.ToHandleChecked());
- }
-
- private:
- void Compile() {
- CompilationInfoWithZone info(f_);
- CHECK(Parser::Parse(&info));
- StrictMode strict_mode = info.function()->strict_mode();
- info.SetStrictMode(strict_mode);
- info.SetOptimizing(BailoutId::None(), Handle<Code>(f_->code()));
- CHECK(Rewriter::Rewrite(&info));
- CHECK(Scope::Analyze(&info));
- CHECK_NE(NULL, info.scope());
- Pipeline pipeline(&info);
- Linkage linkage(&info);
- Handle<Code> code = pipeline.GenerateCodeForMachineGraph(&linkage, graph());
- CHECK(!code.is_null());
- f_->ReplaceCode(*code);
- swapped_ = true;
- }
-
- Handle<JSFunction> f_;
- bool swapped_;
-};
-
-
-TEST(RunChangeTaggedToInt32) {
- SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged);
- Node* x = t.ChangeTaggedToInt32(t.Parameter(0));
- t.Return(x);
-
- t.Lower(x);
-
- // TODO(titzer): remove me.
- return;
-
- FOR_INT32_INPUTS(i) {
- int32_t input = *i;
-
- if (Smi::IsValid(input)) {
- int32_t result = t.Call(Smi::FromInt(input));
- CHECK_EQ(input, result);
- }
-
- {
- Handle<Object> number = t.factory()->NewNumber(input);
- int32_t result = t.Call(*number);
- CHECK_EQ(input, result);
- }
-
- {
- Handle<HeapNumber> number = t.factory()->NewHeapNumber(input);
- int32_t result = t.Call(*number);
- CHECK_EQ(input, result);
- }
- }
-}
-
-
-TEST(RunChangeTaggedToUint32) {
- SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged);
- Node* x = t.ChangeTaggedToUint32(t.Parameter(0));
- t.Return(x);
-
- t.Lower(x);
-
- // TODO(titzer): remove me.
- return;
-
- FOR_UINT32_INPUTS(i) {
- uint32_t input = *i;
-
- if (Smi::IsValid(input)) {
- int32_t result = t.Call(Smi::FromInt(input));
- CHECK_EQ(static_cast<int32_t>(input), result);
- }
-
- {
- Handle<Object> number = t.factory()->NewNumber(input);
- int32_t result = t.Call(*number);
- CHECK_EQ(static_cast<int32_t>(input), result);
- }
-
- {
- Handle<HeapNumber> number = t.factory()->NewHeapNumber(input);
- int32_t result = t.Call(*number);
- CHECK_EQ(static_cast<int32_t>(input), result);
- }
- }
-}
-
-
-TEST(RunChangeTaggedToFloat64) {
- SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged);
- double result;
- Node* x = t.ChangeTaggedToFloat64(t.Parameter(0));
- t.StoreFloat64(x, &result);
- t.Return(t.Int32Constant(0));
-
- t.Lower(x);
-
- // TODO(titzer): remove me.
- return;
-
- {
- FOR_INT32_INPUTS(i) {
- int32_t input = *i;
-
- if (Smi::IsValid(input)) {
- t.Call(Smi::FromInt(input));
- CHECK_EQ(input, static_cast<int32_t>(result));
- }
-
- {
- Handle<Object> number = t.factory()->NewNumber(input);
- t.Call(*number);
- CHECK_EQ(input, static_cast<int32_t>(result));
- }
-
- {
- Handle<HeapNumber> number = t.factory()->NewHeapNumber(input);
- t.Call(*number);
- CHECK_EQ(input, static_cast<int32_t>(result));
- }
- }
- }
-
- {
- FOR_FLOAT64_INPUTS(i) {
- double input = *i;
- {
- Handle<Object> number = t.factory()->NewNumber(input);
- t.Call(*number);
- CHECK_EQ(input, result);
- }
-
- {
- Handle<HeapNumber> number = t.factory()->NewHeapNumber(input);
- t.Call(*number);
- CHECK_EQ(input, result);
- }
- }
- }
-}
-
-
-TEST(RunChangeBoolToBit) {
- SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged);
- Node* x = t.ChangeBoolToBit(t.Parameter(0));
- t.Return(x);
-
- t.Lower(x);
-
- if (!Pipeline::SupportedTarget()) return;
-
- {
- Object* true_obj = t.heap()->true_value();
- int32_t result = t.Call(true_obj);
- CHECK_EQ(1, result);
- }
-
- {
- Object* false_obj = t.heap()->false_value();
- int32_t result = t.Call(false_obj);
- CHECK_EQ(0, result);
- }
-}
-
-
-TEST(RunChangeBitToBool) {
- SimplifiedGraphBuilderTester<Object*> t(kMachineTagged);
- Node* x = t.ChangeBitToBool(t.Parameter(0));
- t.Return(x);
-
- t.Lower(x);
-
- // TODO(titzer): remove me.
- return;
-
- {
- Object* result = t.Call(1);
- Object* true_obj = t.heap()->true_value();
- CHECK_EQ(true_obj, result);
- }
-
- {
- Object* result = t.Call(0);
- Object* false_obj = t.heap()->false_value();
- CHECK_EQ(false_obj, result);
- }
-}
-
-
-TEST(RunChangeInt32ToTagged) {
- SimplifiedGraphBuilderJSTester t;
- int32_t input;
- Node* load = t.LoadInt32(&input);
- Node* x = t.ChangeInt32ToTagged(load);
- t.Return(x);
-
- t.Lower(x);
-
- // TODO(titzer): remove me.
- return;
-
-
- {
- FOR_INT32_INPUTS(i) {
- input = *i;
- HeapNumber* result = t.CallJS<HeapNumber>();
- CHECK_EQ(static_cast<double>(input), result->value());
- }
- }
-
- {
- FOR_INT32_INPUTS(i) {
- input = *i;
- SimulateFullSpace(CcTest::heap()->new_space());
- HeapNumber* result = t.CallJS<HeapNumber>();
- CHECK_EQ(static_cast<double>(input), result->value());
- }
- }
-}
-
-
-TEST(RunChangeUint32ToTagged) {
- SimplifiedGraphBuilderJSTester t;
- uint32_t input;
- Node* load = t.LoadUint32(&input);
- Node* x = t.ChangeUint32ToTagged(load);
- t.Return(x);
-
- t.Lower(x);
-
- // TODO(titzer): remove me.
- return;
-
- {
- FOR_UINT32_INPUTS(i) {
- input = *i;
- HeapNumber* result = t.CallJS<HeapNumber>();
- double expected = static_cast<double>(input);
- CHECK_EQ(expected, result->value());
- }
- }
-
- {
- FOR_UINT32_INPUTS(i) {
- input = *i;
- SimulateFullSpace(CcTest::heap()->new_space());
- HeapNumber* result = t.CallJS<HeapNumber>();
- double expected = static_cast<double>(static_cast<uint32_t>(input));
- CHECK_EQ(expected, result->value());
- }
- }
-}
-
-
-TEST(RunChangeFloat64ToTagged) {
- SimplifiedGraphBuilderJSTester t;
- double input;
- Node* load = t.LoadFloat64(&input);
- Node* x = t.ChangeFloat64ToTagged(load);
- t.Return(x);
-
- t.Lower(x);
-
- // TODO(titzer): remove me.
- return;
-
- {
- FOR_FLOAT64_INPUTS(i) {
- input = *i;
- HeapNumber* result = t.CallJS<HeapNumber>();
- CHECK_EQ(input, result->value());
- }
- }
- {
- FOR_FLOAT64_INPUTS(i) {
- input = *i;
- SimulateFullSpace(CcTest::heap()->new_space());
- HeapNumber* result = t.CallJS<HeapNumber>();
- CHECK_EQ(input, result->value());
- }
- }
-}
-
-
-// TODO(dcarney): find a home for these functions.
-namespace {
-
-FieldAccess ForJSObjectMap() {
- FieldAccess access = {JSObject::kMapOffset, Handle<Name>(), Type::Any(),
- kMachineTagged};
- return access;
-}
-
-
-FieldAccess ForJSObjectProperties() {
- FieldAccess access = {JSObject::kPropertiesOffset, Handle<Name>(),
- Type::Any(), kMachineTagged};
- return access;
-}
-
-
-FieldAccess ForArrayBufferBackingStore() {
- FieldAccess access = {
- JSArrayBuffer::kBackingStoreOffset, Handle<Name>(), Type::UntaggedPtr(),
- MachineOperatorBuilder::pointer_rep(),
- };
- return access;
-}
-
-
-ElementAccess ForFixedArrayElement() {
- ElementAccess access = {FixedArray::kHeaderSize, Type::Any(), kMachineTagged};
- return access;
-}
-
-
-ElementAccess ForBackingStoreElement(MachineRepresentation rep) {
- ElementAccess access = {kNonHeapObjectHeaderSize, Type::Any(), rep};
- return access;
-}
-}
-
-
-// Create a simple JSObject with a unique map.
-static Handle<JSObject> TestObject() {
- static int index = 0;
- char buffer[50];
- v8::base::OS::SNPrintF(buffer, 50, "({'a_%d':1})", index++);
- return Handle<JSObject>::cast(v8::Utils::OpenHandle(*CompileRun(buffer)));
-}
-
-
-TEST(RunLoadMap) {
- SimplifiedGraphBuilderTester<Object*> t(kMachineTagged);
- FieldAccess access = ForJSObjectMap();
- Node* load = t.LoadField(access, t.Parameter(0));
- t.Return(load);
-
- t.LowerAllNodes();
-
- if (!Pipeline::SupportedTarget()) return;
-
- Handle<JSObject> src = TestObject();
- Handle<Map> src_map(src->map());
- Object* result = t.Call(*src);
- CHECK_EQ(*src_map, result);
-}
-
-
-TEST(RunStoreMap) {
- SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged, kMachineTagged);
- FieldAccess access = ForJSObjectMap();
- t.StoreField(access, t.Parameter(1), t.Parameter(0));
- t.Return(t.Int32Constant(0));
-
- t.LowerAllNodes();
-
- if (!Pipeline::SupportedTarget()) return;
-
- Handle<JSObject> src = TestObject();
- Handle<Map> src_map(src->map());
- Handle<JSObject> dst = TestObject();
- CHECK(src->map() != dst->map());
- t.Call(*src_map, *dst);
- CHECK(*src_map == dst->map());
-}
-
-
-TEST(RunLoadProperties) {
- SimplifiedGraphBuilderTester<Object*> t(kMachineTagged);
- FieldAccess access = ForJSObjectProperties();
- Node* load = t.LoadField(access, t.Parameter(0));
- t.Return(load);
-
- t.LowerAllNodes();
-
- if (!Pipeline::SupportedTarget()) return;
-
- Handle<JSObject> src = TestObject();
- Handle<FixedArray> src_props(src->properties());
- Object* result = t.Call(*src);
- CHECK_EQ(*src_props, result);
-}
-
-
-TEST(RunLoadStoreMap) {
- SimplifiedGraphBuilderTester<Object*> t(kMachineTagged, kMachineTagged);
- FieldAccess access = ForJSObjectMap();
- Node* load = t.LoadField(access, t.Parameter(0));
- t.StoreField(access, t.Parameter(1), load);
- t.Return(load);
-
- t.LowerAllNodes();
-
- if (!Pipeline::SupportedTarget()) return;
-
- Handle<JSObject> src = TestObject();
- Handle<Map> src_map(src->map());
- Handle<JSObject> dst = TestObject();
- CHECK(src->map() != dst->map());
- Object* result = t.Call(*src, *dst);
- CHECK(result->IsMap());
- CHECK_EQ(*src_map, result);
- CHECK(*src_map == dst->map());
-}
-
-
-TEST(RunLoadStoreFixedArrayIndex) {
- SimplifiedGraphBuilderTester<Object*> t(kMachineTagged);
- ElementAccess access = ForFixedArrayElement();
- Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0));
- t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), load);
- t.Return(load);
-
- t.LowerAllNodes();
-
- if (!Pipeline::SupportedTarget()) return;
-
- Handle<FixedArray> array = t.factory()->NewFixedArray(2);
- Handle<JSObject> src = TestObject();
- Handle<JSObject> dst = TestObject();
- array->set(0, *src);
- array->set(1, *dst);
- Object* result = t.Call(*array);
- CHECK_EQ(*src, result);
- CHECK_EQ(*src, array->get(0));
- CHECK_EQ(*src, array->get(1));
-}
-
-
-TEST(RunLoadStoreArrayBuffer) {
- SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged);
- const int index = 12;
- FieldAccess access = ForArrayBufferBackingStore();
- Node* backing_store = t.LoadField(access, t.Parameter(0));
- ElementAccess buffer_access = ForBackingStoreElement(kMachineWord8);
- Node* load =
- t.LoadElement(buffer_access, backing_store, t.Int32Constant(index));
- t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1),
- load);
- t.Return(load);
-
- t.LowerAllNodes();
-
- if (!Pipeline::SupportedTarget()) return;
-
- Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer();
- const int array_length = 2 * index;
- Runtime::SetupArrayBufferAllocatingData(t.isolate(), array, array_length);
- uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store());
- for (int i = 0; i < array_length; i++) {
- data[i] = i;
- }
- int32_t result = t.Call(*array);
- CHECK_EQ(index, result);
- for (int i = 0; i < array_length; i++) {
- uint8_t expected = i;
- if (i == (index + 1)) expected = result;
- CHECK_EQ(data[i], expected);
- }
-}
-
-
-TEST(RunCopyFixedArray) {
- SimplifiedGraphBuilderTester<int32_t> t(kMachineTagged, kMachineTagged);
-
- const int kArraySize = 15;
- Node* one = t.Int32Constant(1);
- Node* index = t.Int32Constant(0);
- Node* limit = t.Int32Constant(kArraySize);
- t.environment()->Push(index);
- {
- LoopBuilder loop(&t);
- loop.BeginLoop();
- // Loop exit condition.
- index = t.environment()->Top();
- Node* condition = t.Int32LessThan(index, limit);
- loop.BreakUnless(condition);
- // src[index] = dst[index].
- index = t.environment()->Pop();
- ElementAccess access = ForFixedArrayElement();
- Node* src = t.Parameter(0);
- Node* load = t.LoadElement(access, src, index);
- Node* dst = t.Parameter(1);
- t.StoreElement(access, dst, index, load);
- // index++
- index = t.Int32Add(index, one);
- t.environment()->Push(index);
- // continue.
- loop.EndBody();
- loop.EndLoop();
- }
- index = t.environment()->Pop();
- t.Return(index);
-
- t.LowerAllNodes();
-
- if (!Pipeline::SupportedTarget()) return;
-
- Handle<FixedArray> src = t.factory()->NewFixedArray(kArraySize);
- Handle<FixedArray> src_copy = t.factory()->NewFixedArray(kArraySize);
- Handle<FixedArray> dst = t.factory()->NewFixedArray(kArraySize);
- for (int i = 0; i < kArraySize; i++) {
- src->set(i, *TestObject());
- src_copy->set(i, src->get(i));
- dst->set(i, *TestObject());
- CHECK_NE(src_copy->get(i), dst->get(i));
- }
- CHECK_EQ(kArraySize, t.Call(*src, *dst));
- for (int i = 0; i < kArraySize; i++) {
- CHECK_EQ(src_copy->get(i), dst->get(i));
- }
-}
+++ /dev/null
-// 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 <string>
-
-#include "src/v8.h"
-#include "test/cctest/cctest.h"
-
-#include "src/base/utils/random-number-generator.h"
-#include "test/cctest/compiler/codegen-tester.h"
-
-#if V8_TURBOFAN_TARGET
-
-using namespace v8::internal;
-using namespace v8::internal::compiler;
-
-typedef StructuredMachineAssembler::IfBuilder IfBuilder;
-typedef StructuredMachineAssembler::LoopBuilder Loop;
-
-static const int32_t kUninitializedVariableOffset = -1;
-static const int32_t kUninitializedOutput = -1;
-static const int32_t kVerifiedOutput = -2;
-
-static const int32_t kInitalVar = 1013;
-static const int32_t kConjunctionInc = 1069;
-static const int32_t kDisjunctionInc = 1151;
-static const int32_t kThenInc = 1223;
-static const int32_t kElseInc = 1291;
-static const int32_t kIfInc = 1373;
-
-class IfBuilderModel {
- public:
- explicit IfBuilderModel(Zone* zone)
- : zone_(zone),
- variable_offset_(0),
- root_(new (zone_) Node(NULL)),
- current_node_(root_),
- current_expression_(NULL) {}
-
- void If() {
- if (current_node_->else_node != NULL) {
- current_node_ = current_node_->else_node;
- } else if (current_node_->then_node != NULL) {
- current_node_ = current_node_->then_node;
- }
- ASSERT(current_expression_ == NULL);
- current_expression_ = new (zone_) Expression(zone_, NULL);
- current_node_->condition = current_expression_;
- }
- void IfNode() { LastChild()->variable_offset = variable_offset_++; }
-
- void OpenParen() { current_expression_ = LastChild(); }
- void CloseParen() { current_expression_ = current_expression_->parent; }
-
- void And() { NewChild()->conjunction = true; }
- void Or() { NewChild()->disjunction = true; }
-
- void Then() {
- ASSERT(current_expression_ == NULL || current_expression_->parent == NULL);
- current_expression_ = NULL;
- ASSERT(current_node_->then_node == NULL);
- current_node_->then_node = new (zone_) Node(current_node_);
- }
- void Else() {
- ASSERT(current_expression_ == NULL || current_expression_->parent == NULL);
- current_expression_ = NULL;
- ASSERT(current_node_->else_node == NULL);
- current_node_->else_node = new (zone_) Node(current_node_);
- }
- void Return() {
- if (current_node_->else_node != NULL) {
- current_node_->else_node->returns = true;
- } else if (current_node_->then_node != NULL) {
- current_node_->then_node->returns = true;
- } else {
- CHECK(false);
- }
- }
- void End() {}
-
- void Print(std::vector<char>* v) { PrintRecursive(v, root_); }
-
- struct VerificationState {
- int32_t* inputs;
- int32_t* outputs;
- int32_t var;
- };
-
- int32_t Verify(int length, int32_t* inputs, int32_t* outputs) {
- CHECK_EQ(variable_offset_, length);
- // Input/Output verification.
- for (int i = 0; i < length; ++i) {
- CHECK(inputs[i] == 0 || inputs[i] == 1);
- CHECK(outputs[i] == kUninitializedOutput || outputs[i] >= 0);
- }
- // Do verification.
- VerificationState state;
- state.inputs = inputs;
- state.outputs = outputs;
- state.var = kInitalVar;
- VerifyRecursive(root_, &state);
- // Verify all outputs marked.
- for (int i = 0; i < length; ++i) {
- CHECK(outputs[i] == kUninitializedOutput ||
- outputs[i] == kVerifiedOutput);
- }
- return state.var;
- }
-
- private:
- struct Expression;
- typedef std::vector<Expression*, zone_allocator<Expression*> > Expressions;
-
- struct Expression : public ZoneObject {
- Expression(Zone* zone, Expression* p)
- : variable_offset(kUninitializedVariableOffset),
- disjunction(false),
- conjunction(false),
- parent(p),
- children(Expressions::allocator_type(zone)) {}
- int variable_offset;
- bool disjunction;
- bool conjunction;
- Expression* parent;
- Expressions children;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Expression);
- };
-
- struct Node : public ZoneObject {
- explicit Node(Node* p)
- : parent(p),
- condition(NULL),
- then_node(NULL),
- else_node(NULL),
- returns(false) {}
- Node* parent;
- Expression* condition;
- Node* then_node;
- Node* else_node;
- bool returns;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Node);
- };
-
- Expression* LastChild() {
- if (current_expression_->children.empty()) {
- current_expression_->children.push_back(
- new (zone_) Expression(zone_, current_expression_));
- }
- return current_expression_->children.back();
- }
-
- Expression* NewChild() {
- Expression* child = new (zone_) Expression(zone_, current_expression_);
- current_expression_->children.push_back(child);
- return child;
- }
-
- static void PrintRecursive(std::vector<char>* v, Expression* expression) {
- CHECK(expression != NULL);
- if (expression->conjunction) {
- ASSERT(!expression->disjunction);
- v->push_back('&');
- } else if (expression->disjunction) {
- v->push_back('|');
- }
- if (expression->variable_offset != kUninitializedVariableOffset) {
- v->push_back('v');
- }
- Expressions& children = expression->children;
- if (children.empty()) return;
- v->push_back('(');
- for (Expressions::iterator i = children.begin(); i != children.end(); ++i) {
- PrintRecursive(v, *i);
- }
- v->push_back(')');
- }
-
- static void PrintRecursive(std::vector<char>* v, Node* node) {
- // Termination condition.
- if (node->condition == NULL) {
- CHECK(node->then_node == NULL && node->else_node == NULL);
- if (node->returns) v->push_back('r');
- return;
- }
- CHECK(!node->returns);
- v->push_back('i');
- PrintRecursive(v, node->condition);
- if (node->then_node != NULL) {
- v->push_back('t');
- PrintRecursive(v, node->then_node);
- }
- if (node->else_node != NULL) {
- v->push_back('e');
- PrintRecursive(v, node->else_node);
- }
- }
-
- static bool VerifyRecursive(Expression* expression,
- VerificationState* state) {
- bool result = false;
- bool first_iteration = true;
- Expressions& children = expression->children;
- CHECK(!children.empty());
- for (Expressions::iterator i = children.begin(); i != children.end(); ++i) {
- Expression* child = *i;
- // Short circuit evaluation,
- // but mixes of &&s and ||s have weird semantics.
- if ((child->conjunction && !result) || (child->disjunction && result)) {
- continue;
- }
- if (child->conjunction) state->var += kConjunctionInc;
- if (child->disjunction) state->var += kDisjunctionInc;
- bool child_result;
- if (child->variable_offset != kUninitializedVariableOffset) {
- // Verify output
- CHECK_EQ(state->var, state->outputs[child->variable_offset]);
- state->outputs[child->variable_offset] = kVerifiedOutput; // Mark seen.
- child_result = state->inputs[child->variable_offset];
- CHECK(child->children.empty());
- state->var += kIfInc;
- } else {
- child_result = VerifyRecursive(child, state);
- }
- if (child->conjunction) {
- result &= child_result;
- } else if (child->disjunction) {
- result |= child_result;
- } else {
- CHECK(first_iteration);
- result = child_result;
- }
- first_iteration = false;
- }
- return result;
- }
-
- static void VerifyRecursive(Node* node, VerificationState* state) {
- if (node->condition == NULL) return;
- bool result = VerifyRecursive(node->condition, state);
- if (result) {
- if (node->then_node) {
- state->var += kThenInc;
- return VerifyRecursive(node->then_node, state);
- }
- } else {
- if (node->else_node) {
- state->var += kElseInc;
- return VerifyRecursive(node->else_node, state);
- }
- }
- }
-
- Zone* zone_;
- int variable_offset_;
- Node* root_;
- Node* current_node_;
- Expression* current_expression_;
- DISALLOW_COPY_AND_ASSIGN(IfBuilderModel);
-};
-
-
-class IfBuilderGenerator : public StructuredMachineAssemblerTester<int32_t> {
- public:
- IfBuilderGenerator()
- : StructuredMachineAssemblerTester(MachineOperatorBuilder::pointer_rep(),
- MachineOperatorBuilder::pointer_rep()),
- var_(NewVariable(Int32Constant(kInitalVar))),
- c_(this),
- m_(this->zone()),
- one_(Int32Constant(1)),
- offset_(0) {}
-
- static void GenerateExpression(v8::base::RandomNumberGenerator* rng,
- std::vector<char>* v, int n_vars) {
- int depth = 1;
- v->push_back('(');
- bool need_if = true;
- bool populated = false;
- while (n_vars != 0) {
- if (need_if) {
- // can nest a paren or do a variable
- if (rng->NextBool()) {
- v->push_back('v');
- n_vars--;
- need_if = false;
- populated = true;
- } else {
- v->push_back('(');
- depth++;
- populated = false;
- }
- } else {
- // can pop, do && or do ||
- int options = 3;
- if (depth == 1 || !populated) {
- options--;
- }
- switch (rng->NextInt(options)) {
- case 0:
- v->push_back('&');
- need_if = true;
- break;
- case 1:
- v->push_back('|');
- need_if = true;
- break;
- case 2:
- v->push_back(')');
- depth--;
- break;
- }
- }
- }
- CHECK(!need_if);
- while (depth != 0) {
- v->push_back(')');
- depth--;
- }
- }
-
- static void GenerateIfThenElse(v8::base::RandomNumberGenerator* rng,
- std::vector<char>* v, int n_ifs,
- int max_exp_length) {
- CHECK_GT(n_ifs, 0);
- CHECK_GT(max_exp_length, 0);
- bool have_env = true;
- bool then_done = false;
- bool else_done = false;
- bool first_iteration = true;
- while (n_ifs != 0) {
- if (have_env) {
- int options = 3;
- if (else_done || first_iteration) { // Don't do else or return
- options -= 2;
- first_iteration = false;
- }
- switch (rng->NextInt(options)) {
- case 0:
- v->push_back('i');
- n_ifs--;
- have_env = false;
- GenerateExpression(rng, v, rng->NextInt(max_exp_length) + 1);
- break;
- case 1:
- v->push_back('r');
- have_env = false;
- break;
- case 2:
- v->push_back('e');
- else_done = true;
- then_done = false;
- break;
- default:
- CHECK(false);
- }
- } else { // Can only do then or else
- int options = 2;
- if (then_done) options--;
- switch (rng->NextInt(options)) {
- case 0:
- v->push_back('e');
- else_done = true;
- then_done = false;
- break;
- case 1:
- v->push_back('t');
- then_done = true;
- else_done = false;
- break;
- default:
- CHECK(false);
- }
- have_env = true;
- }
- }
- // Last instruction must have been an if, can complete it in several ways.
- int options = 2;
- if (then_done && !else_done) options++;
- switch (rng->NextInt(3)) {
- case 0:
- // Do nothing.
- break;
- case 1:
- v->push_back('t');
- switch (rng->NextInt(3)) {
- case 0:
- v->push_back('r');
- break;
- case 1:
- v->push_back('e');
- break;
- case 2:
- v->push_back('e');
- v->push_back('r');
- break;
- default:
- CHECK(false);
- }
- break;
- case 2:
- v->push_back('e');
- if (rng->NextBool()) v->push_back('r');
- break;
- default:
- CHECK(false);
- }
- }
-
- std::string::const_iterator ParseExpression(std::string::const_iterator it,
- std::string::const_iterator end) {
- // Prepare for expression.
- m_.If();
- c_.If();
- int depth = 0;
- for (; it != end; ++it) {
- switch (*it) {
- case 'v':
- m_.IfNode();
- {
- Node* offset = Int32Constant(offset_ * 4);
- Store(kMachineWord32, Parameter(1), offset, var_.Get());
- var_.Set(Int32Add(var_.Get(), Int32Constant(kIfInc)));
- c_.If(Load(kMachineWord32, Parameter(0), offset));
- offset_++;
- }
- break;
- case '&':
- m_.And();
- c_.And();
- var_.Set(Int32Add(var_.Get(), Int32Constant(kConjunctionInc)));
- break;
- case '|':
- m_.Or();
- c_.Or();
- var_.Set(Int32Add(var_.Get(), Int32Constant(kDisjunctionInc)));
- break;
- case '(':
- if (depth != 0) {
- m_.OpenParen();
- c_.OpenParen();
- }
- depth++;
- break;
- case ')':
- depth--;
- if (depth == 0) return it;
- m_.CloseParen();
- c_.CloseParen();
- break;
- default:
- CHECK(false);
- }
- }
- CHECK(false);
- return it;
- }
-
- void ParseIfThenElse(const std::string& str) {
- int n_vars = 0;
- for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) {
- if (*it == 'v') n_vars++;
- }
- InitializeConstants(n_vars);
- for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) {
- switch (*it) {
- case 'i': {
- it++;
- CHECK(it != str.end());
- CHECK_EQ('(', *it);
- it = ParseExpression(it, str.end());
- CHECK_EQ(')', *it);
- break;
- }
- case 't':
- m_.Then();
- c_.Then();
- var_.Set(Int32Add(var_.Get(), Int32Constant(kThenInc)));
- break;
- case 'e':
- m_.Else();
- c_.Else();
- var_.Set(Int32Add(var_.Get(), Int32Constant(kElseInc)));
- break;
- case 'r':
- m_.Return();
- Return(var_.Get());
- break;
- default:
- CHECK(false);
- }
- }
- m_.End();
- c_.End();
- Return(var_.Get());
- // Compare generated model to parsed version.
- {
- std::vector<char> v;
- m_.Print(&v);
- std::string m_str(v.begin(), v.end());
- CHECK(m_str == str);
- }
- }
-
- void ParseExpression(const std::string& str) {
- CHECK(inputs_.is_empty());
- std::string wrapped = "i(" + str + ")te";
- ParseIfThenElse(wrapped);
- }
-
- void ParseRandomIfThenElse(v8::base::RandomNumberGenerator* rng, int n_ifs,
- int n_vars) {
- std::vector<char> v;
- GenerateIfThenElse(rng, &v, n_ifs, n_vars);
- std::string str(v.begin(), v.end());
- ParseIfThenElse(str);
- }
-
- void RunRandom(v8::base::RandomNumberGenerator* rng) {
- // TODO(dcarney): permute inputs via model.
- // TODO(dcarney): compute test_cases from n_ifs and n_vars.
- int test_cases = 100;
- for (int test = 0; test < test_cases; test++) {
- Initialize();
- for (int i = 0; i < offset_; i++) {
- inputs_[i] = rng->NextBool();
- }
- DoCall();
- }
- }
-
- void Run(const std::string& str, int32_t expected) {
- Initialize();
- int offset = 0;
- for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) {
- switch (*it) {
- case 't':
- inputs_[offset++] = 1;
- break;
- case 'f':
- inputs_[offset++] = 0;
- break;
- default:
- CHECK(false);
- }
- }
- CHECK_EQ(offset_, offset);
- // Call.
- int32_t result = DoCall();
- CHECK_EQ(result, expected);
- }
-
- private:
- typedef std::vector<int32_t, zone_allocator<int32_t> > IOVector;
-
- void InitializeConstants(int n_vars) {
- CHECK(inputs_.is_empty());
- inputs_.Reset(new int32_t[n_vars]);
- outputs_.Reset(new int32_t[n_vars]);
- }
-
- void Initialize() {
- for (int i = 0; i < offset_; i++) {
- inputs_[i] = 0;
- outputs_[i] = kUninitializedOutput;
- }
- }
-
- int32_t DoCall() {
- int32_t result = Call(inputs_.get(), outputs_.get());
- int32_t expected = m_.Verify(offset_, inputs_.get(), outputs_.get());
- CHECK_EQ(result, expected);
- return result;
- }
-
- const v8::internal::compiler::Variable var_;
- IfBuilder c_;
- IfBuilderModel m_;
- Node* one_;
- int32_t offset_;
- SmartArrayPointer<int32_t> inputs_;
- SmartArrayPointer<int32_t> outputs_;
-};
-
-
-TEST(RunExpressionString) {
- IfBuilderGenerator m;
- m.ParseExpression("((v|v)|v)");
- m.Run("ttt", kInitalVar + 1 * kIfInc + kThenInc);
- m.Run("ftt", kInitalVar + 2 * kIfInc + kDisjunctionInc + kThenInc);
- m.Run("fft", kInitalVar + 3 * kIfInc + 2 * kDisjunctionInc + kThenInc);
- m.Run("fff", kInitalVar + 3 * kIfInc + 2 * kDisjunctionInc + kElseInc);
-}
-
-
-TEST(RunExpressionStrings) {
- const char* strings[] = {
- "v", "(v)", "((v))", "v|v",
- "(v|v)", "((v|v))", "v&v", "(v&v)",
- "((v&v))", "v&(v)", "v&(v|v)", "v&(v|v)&v",
- "v|(v)", "v|(v&v)", "v|(v&v)|v", "v|(((v)|(v&v)|(v)|v)&(v))|v",
- };
- v8::base::RandomNumberGenerator rng;
- for (size_t i = 0; i < ARRAY_SIZE(strings); i++) {
- IfBuilderGenerator m;
- m.ParseExpression(strings[i]);
- m.RunRandom(&rng);
- }
-}
-
-
-TEST(RunSimpleIfElseTester) {
- const char* tests[] = {
- "i(v)", "i(v)t", "i(v)te",
- "i(v)er", "i(v)ter", "i(v)ti(v)trei(v)ei(v)ei(v)ei(v)ei(v)ei(v)ei(v)e"};
- v8::base::RandomNumberGenerator rng;
- for (size_t i = 0; i < ARRAY_SIZE(tests); ++i) {
- IfBuilderGenerator m;
- m.ParseIfThenElse(tests[i]);
- m.RunRandom(&rng);
- }
-}
-
-
-TEST(RunRandomExpressions) {
- v8::base::RandomNumberGenerator rng;
- for (int n_vars = 1; n_vars < 12; n_vars++) {
- for (int i = 0; i < n_vars * n_vars + 10; i++) {
- IfBuilderGenerator m;
- m.ParseRandomIfThenElse(&rng, 1, n_vars);
- m.RunRandom(&rng);
- }
- }
-}
-
-
-TEST(RunRandomIfElse) {
- v8::base::RandomNumberGenerator rng;
- for (int n_ifs = 1; n_ifs < 12; n_ifs++) {
- for (int i = 0; i < n_ifs * n_ifs + 10; i++) {
- IfBuilderGenerator m;
- m.ParseRandomIfThenElse(&rng, n_ifs, 1);
- m.RunRandom(&rng);
- }
- }
-}
-
-
-TEST(RunRandomIfElseExpressions) {
- v8::base::RandomNumberGenerator rng;
- for (int n_vars = 2; n_vars < 6; n_vars++) {
- for (int n_ifs = 2; n_ifs < 7; n_ifs++) {
- for (int i = 0; i < n_ifs * n_vars + 10; i++) {
- IfBuilderGenerator m;
- m.ParseRandomIfThenElse(&rng, n_ifs, n_vars);
- m.RunRandom(&rng);
- }
- }
- }
-}
-
-#endif
+++ /dev/null
-// 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/utils/random-number-generator.h"
-#include "src/compiler/structured-machine-assembler.h"
-#include "test/cctest/compiler/codegen-tester.h"
-#include "test/cctest/compiler/value-helper.h"
-
-#if V8_TURBOFAN_TARGET
-
-using namespace v8::internal::compiler;
-
-typedef StructuredMachineAssembler::IfBuilder IfBuilder;
-typedef StructuredMachineAssembler::LoopBuilder Loop;
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-class StructuredMachineAssemblerFriend {
- public:
- static bool VariableAlive(StructuredMachineAssembler* m,
- const Variable& var) {
- CHECK(m->current_environment_ != NULL);
- int offset = var.offset_;
- return offset < static_cast<int>(m->CurrentVars()->size()) &&
- m->CurrentVars()->at(offset) != NULL;
- }
-};
-}
-}
-} // namespace v8::internal::compiler
-
-
-TEST(RunVariable) {
- StructuredMachineAssemblerTester<int32_t> m;
-
- int32_t constant = 0x86c2bb16;
-
- Variable v1 = m.NewVariable(m.Int32Constant(constant));
- Variable v2 = m.NewVariable(v1.Get());
- m.Return(v2.Get());
-
- CHECK_EQ(constant, m.Call());
-}
-
-
-TEST(RunSimpleIf) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- int32_t constant = 0xc4a3e3a6;
- {
- IfBuilder cond(&m);
- cond.If(m.Parameter(0)).Then();
- m.Return(m.Int32Constant(constant));
- }
- m.Return(m.Word32Not(m.Int32Constant(constant)));
-
- CHECK_EQ(~constant, m.Call(0));
- CHECK_EQ(constant, m.Call(1));
-}
-
-
-TEST(RunSimpleIfVariable) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- int32_t constant = 0xdb6f20c2;
- Variable var = m.NewVariable(m.Int32Constant(constant));
- {
- IfBuilder cond(&m);
- cond.If(m.Parameter(0)).Then();
- var.Set(m.Word32Not(var.Get()));
- }
- m.Return(var.Get());
-
- CHECK_EQ(constant, m.Call(0));
- CHECK_EQ(~constant, m.Call(1));
-}
-
-
-TEST(RunSimpleElse) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- int32_t constant = 0xfc5eadf4;
- {
- IfBuilder cond(&m);
- cond.If(m.Parameter(0)).Else();
- m.Return(m.Int32Constant(constant));
- }
- m.Return(m.Word32Not(m.Int32Constant(constant)));
-
- CHECK_EQ(constant, m.Call(0));
- CHECK_EQ(~constant, m.Call(1));
-}
-
-
-TEST(RunSimpleIfElse) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- int32_t constant = 0xaa9c8cd3;
- {
- IfBuilder cond(&m);
- cond.If(m.Parameter(0)).Then();
- m.Return(m.Int32Constant(constant));
- cond.Else();
- m.Return(m.Word32Not(m.Int32Constant(constant)));
- }
-
- CHECK_EQ(~constant, m.Call(0));
- CHECK_EQ(constant, m.Call(1));
-}
-
-
-TEST(RunSimpleIfElseVariable) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- int32_t constant = 0x67b6f39c;
- Variable var = m.NewVariable(m.Int32Constant(constant));
- {
- IfBuilder cond(&m);
- cond.If(m.Parameter(0)).Then();
- var.Set(m.Word32Not(m.Word32Not(var.Get())));
- cond.Else();
- var.Set(m.Word32Not(var.Get()));
- }
- m.Return(var.Get());
-
- CHECK_EQ(~constant, m.Call(0));
- CHECK_EQ(constant, m.Call(1));
-}
-
-
-TEST(RunSimpleIfNoThenElse) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- int32_t constant = 0xd5e550ed;
- {
- IfBuilder cond(&m);
- cond.If(m.Parameter(0));
- }
- m.Return(m.Int32Constant(constant));
-
- CHECK_EQ(constant, m.Call(0));
- CHECK_EQ(constant, m.Call(1));
-}
-
-
-TEST(RunSimpleConjunctionVariable) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- int32_t constant = 0xf8fb9ec6;
- Variable var = m.NewVariable(m.Int32Constant(constant));
- {
- IfBuilder cond(&m);
- cond.If(m.Int32Constant(1)).And();
- var.Set(m.Word32Not(var.Get()));
- cond.If(m.Parameter(0)).Then();
- var.Set(m.Word32Not(m.Word32Not(var.Get())));
- cond.Else();
- var.Set(m.Word32Not(var.Get()));
- }
- m.Return(var.Get());
-
- CHECK_EQ(constant, m.Call(0));
- CHECK_EQ(~constant, m.Call(1));
-}
-
-
-TEST(RunSimpleDisjunctionVariable) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- int32_t constant = 0x118f6ffc;
- Variable var = m.NewVariable(m.Int32Constant(constant));
- {
- IfBuilder cond(&m);
- cond.If(m.Int32Constant(0)).Or();
- var.Set(m.Word32Not(var.Get()));
- cond.If(m.Parameter(0)).Then();
- var.Set(m.Word32Not(m.Word32Not(var.Get())));
- cond.Else();
- var.Set(m.Word32Not(var.Get()));
- }
- m.Return(var.Get());
-
- CHECK_EQ(constant, m.Call(0));
- CHECK_EQ(~constant, m.Call(1));
-}
-
-
-TEST(RunIfElse) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- {
- IfBuilder cond(&m);
- bool first = true;
- FOR_INT32_INPUTS(i) {
- Node* c = m.Int32Constant(*i);
- if (first) {
- cond.If(m.Word32Equal(m.Parameter(0), c)).Then();
- m.Return(c);
- first = false;
- } else {
- cond.Else();
- cond.If(m.Word32Equal(m.Parameter(0), c)).Then();
- m.Return(c);
- }
- }
- }
- m.Return(m.Int32Constant(333));
-
- FOR_INT32_INPUTS(i) { CHECK_EQ(*i, m.Call(*i)); }
-}
-
-
-enum IfBuilderBranchType { kSkipBranch, kBranchFallsThrough, kBranchReturns };
-
-
-static IfBuilderBranchType all_branch_types[] = {
- kSkipBranch, kBranchFallsThrough, kBranchReturns};
-
-
-static void RunIfBuilderDisjunction(size_t max, IfBuilderBranchType then_type,
- IfBuilderBranchType else_type) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- std::vector<int32_t> inputs = ValueHelper::int32_vector();
- std::vector<int32_t>::const_iterator i = inputs.begin();
- int32_t hit = 0x8c723c9a;
- int32_t miss = 0x88a6b9f3;
- {
- Node* p0 = m.Parameter(0);
- IfBuilder cond(&m);
- for (size_t j = 0; j < max; j++, ++i) {
- CHECK(i != inputs.end()); // Thank you STL.
- if (j > 0) cond.Or();
- cond.If(m.Word32Equal(p0, m.Int32Constant(*i)));
- }
- switch (then_type) {
- case kSkipBranch:
- break;
- case kBranchFallsThrough:
- cond.Then();
- break;
- case kBranchReturns:
- cond.Then();
- m.Return(m.Int32Constant(hit));
- break;
- }
- switch (else_type) {
- case kSkipBranch:
- break;
- case kBranchFallsThrough:
- cond.Else();
- break;
- case kBranchReturns:
- cond.Else();
- m.Return(m.Int32Constant(miss));
- break;
- }
- }
- if (then_type != kBranchReturns || else_type != kBranchReturns) {
- m.Return(m.Int32Constant(miss));
- }
-
- if (then_type != kBranchReturns) hit = miss;
-
- i = inputs.begin();
- for (size_t j = 0; i != inputs.end(); j++, ++i) {
- int32_t result = m.Call(*i);
- CHECK_EQ(j < max ? hit : miss, result);
- }
-}
-
-
-TEST(RunIfBuilderDisjunction) {
- size_t len = ValueHelper::int32_vector().size() - 1;
- size_t max = len > 10 ? 10 : len - 1;
- for (size_t i = 0; i < ARRAY_SIZE(all_branch_types); i++) {
- for (size_t j = 0; j < ARRAY_SIZE(all_branch_types); j++) {
- for (size_t size = 1; size < max; size++) {
- RunIfBuilderDisjunction(size, all_branch_types[i], all_branch_types[j]);
- }
- RunIfBuilderDisjunction(len, all_branch_types[i], all_branch_types[j]);
- }
- }
-}
-
-
-static void RunIfBuilderConjunction(size_t max, IfBuilderBranchType then_type,
- IfBuilderBranchType else_type) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- std::vector<int32_t> inputs = ValueHelper::int32_vector();
- std::vector<int32_t>::const_iterator i = inputs.begin();
- int32_t hit = 0xa0ceb9ca;
- int32_t miss = 0x226cafaa;
- {
- IfBuilder cond(&m);
- Node* p0 = m.Parameter(0);
- for (size_t j = 0; j < max; j++, ++i) {
- if (j > 0) cond.And();
- cond.If(m.Word32NotEqual(p0, m.Int32Constant(*i)));
- }
- switch (then_type) {
- case kSkipBranch:
- break;
- case kBranchFallsThrough:
- cond.Then();
- break;
- case kBranchReturns:
- cond.Then();
- m.Return(m.Int32Constant(hit));
- break;
- }
- switch (else_type) {
- case kSkipBranch:
- break;
- case kBranchFallsThrough:
- cond.Else();
- break;
- case kBranchReturns:
- cond.Else();
- m.Return(m.Int32Constant(miss));
- break;
- }
- }
- if (then_type != kBranchReturns || else_type != kBranchReturns) {
- m.Return(m.Int32Constant(miss));
- }
-
- if (then_type != kBranchReturns) hit = miss;
-
- i = inputs.begin();
- for (size_t j = 0; i != inputs.end(); j++, ++i) {
- int32_t result = m.Call(*i);
- CHECK_EQ(j >= max ? hit : miss, result);
- }
-}
-
-
-TEST(RunIfBuilderConjunction) {
- size_t len = ValueHelper::int32_vector().size() - 1;
- size_t max = len > 10 ? 10 : len - 1;
- for (size_t i = 0; i < ARRAY_SIZE(all_branch_types); i++) {
- for (size_t j = 0; j < ARRAY_SIZE(all_branch_types); j++) {
- for (size_t size = 1; size < max; size++) {
- RunIfBuilderConjunction(size, all_branch_types[i], all_branch_types[j]);
- }
- RunIfBuilderConjunction(len, all_branch_types[i], all_branch_types[j]);
- }
- }
-}
-
-
-static void RunDisjunctionVariables(int disjunctions, bool explicit_then,
- bool explicit_else) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- int32_t constant = 0x65a09535;
-
- Node* cmp_val = m.Int32Constant(constant);
- Node* one = m.Int32Constant(1);
- Variable var = m.NewVariable(m.Parameter(0));
- {
- IfBuilder cond(&m);
- cond.If(m.Word32Equal(var.Get(), cmp_val));
- for (int i = 0; i < disjunctions; i++) {
- cond.Or();
- var.Set(m.Int32Add(var.Get(), one));
- cond.If(m.Word32Equal(var.Get(), cmp_val));
- }
- if (explicit_then) {
- cond.Then();
- }
- if (explicit_else) {
- cond.Else();
- var.Set(m.Int32Add(var.Get(), one));
- }
- }
- m.Return(var.Get());
-
- int adds = disjunctions + (explicit_else ? 1 : 0);
- int32_t input = constant - 2 * adds;
- for (int i = 0; i < adds; i++) {
- CHECK_EQ(input + adds, m.Call(input));
- input++;
- }
- for (int i = 0; i < adds + 1; i++) {
- CHECK_EQ(constant, m.Call(input));
- input++;
- }
- for (int i = 0; i < adds; i++) {
- CHECK_EQ(input + adds, m.Call(input));
- input++;
- }
-}
-
-
-TEST(RunDisjunctionVariables) {
- for (int disjunctions = 0; disjunctions < 10; disjunctions++) {
- RunDisjunctionVariables(disjunctions, false, false);
- RunDisjunctionVariables(disjunctions, false, true);
- RunDisjunctionVariables(disjunctions, true, false);
- RunDisjunctionVariables(disjunctions, true, true);
- }
-}
-
-
-static void RunConjunctionVariables(int conjunctions, bool explicit_then,
- bool explicit_else) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- int32_t constant = 0x2c7f4b45;
- Node* cmp_val = m.Int32Constant(constant);
- Node* one = m.Int32Constant(1);
- Variable var = m.NewVariable(m.Parameter(0));
- {
- IfBuilder cond(&m);
- cond.If(m.Word32NotEqual(var.Get(), cmp_val));
- for (int i = 0; i < conjunctions; i++) {
- cond.And();
- var.Set(m.Int32Add(var.Get(), one));
- cond.If(m.Word32NotEqual(var.Get(), cmp_val));
- }
- if (explicit_then) {
- cond.Then();
- var.Set(m.Int32Add(var.Get(), one));
- }
- if (explicit_else) {
- cond.Else();
- }
- }
- m.Return(var.Get());
-
- int adds = conjunctions + (explicit_then ? 1 : 0);
- int32_t input = constant - 2 * adds;
- for (int i = 0; i < adds; i++) {
- CHECK_EQ(input + adds, m.Call(input));
- input++;
- }
- for (int i = 0; i < adds + 1; i++) {
- CHECK_EQ(constant, m.Call(input));
- input++;
- }
- for (int i = 0; i < adds; i++) {
- CHECK_EQ(input + adds, m.Call(input));
- input++;
- }
-}
-
-
-TEST(RunConjunctionVariables) {
- for (int conjunctions = 0; conjunctions < 10; conjunctions++) {
- RunConjunctionVariables(conjunctions, false, false);
- RunConjunctionVariables(conjunctions, false, true);
- RunConjunctionVariables(conjunctions, true, false);
- RunConjunctionVariables(conjunctions, true, true);
- }
-}
-
-
-TEST(RunSimpleNestedIf) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32, kMachineWord32);
- const size_t NUM_VALUES = 7;
- std::vector<int32_t> inputs = ValueHelper::int32_vector();
- CHECK(inputs.size() >= NUM_VALUES);
- Node* values[NUM_VALUES];
- for (size_t j = 0; j < NUM_VALUES; j++) {
- values[j] = m.Int32Constant(inputs[j]);
- }
- {
- IfBuilder if_0(&m);
- if_0.If(m.Word32Equal(m.Parameter(0), values[0])).Then();
- {
- IfBuilder if_1(&m);
- if_1.If(m.Word32Equal(m.Parameter(1), values[1])).Then();
- { m.Return(values[3]); }
- if_1.Else();
- { m.Return(values[4]); }
- }
- if_0.Else();
- {
- IfBuilder if_1(&m);
- if_1.If(m.Word32Equal(m.Parameter(1), values[2])).Then();
- { m.Return(values[5]); }
- if_1.Else();
- { m.Return(values[6]); }
- }
- }
-
- int32_t result = m.Call(inputs[0], inputs[1]);
- CHECK_EQ(inputs[3], result);
-
- result = m.Call(inputs[0], inputs[1] + 1);
- CHECK_EQ(inputs[4], result);
-
- result = m.Call(inputs[0] + 1, inputs[2]);
- CHECK_EQ(inputs[5], result);
-
- result = m.Call(inputs[0] + 1, inputs[2] + 1);
- CHECK_EQ(inputs[6], result);
-}
-
-
-TEST(RunUnreachableBlockAfterIf) {
- StructuredMachineAssemblerTester<int32_t> m;
- {
- IfBuilder cond(&m);
- cond.If(m.Int32Constant(0)).Then();
- m.Return(m.Int32Constant(1));
- cond.Else();
- m.Return(m.Int32Constant(2));
- }
- // This is unreachable.
- m.Return(m.Int32Constant(3));
- CHECK_EQ(2, m.Call());
-}
-
-
-TEST(RunUnreachableBlockAfterLoop) {
- StructuredMachineAssemblerTester<int32_t> m;
- {
- Loop loop(&m);
- m.Return(m.Int32Constant(1));
- }
- // This is unreachable.
- m.Return(m.Int32Constant(3));
- CHECK_EQ(1, m.Call());
-}
-
-
-TEST(RunSimpleLoop) {
- StructuredMachineAssemblerTester<int32_t> m;
- int32_t constant = 0x120c1f85;
- {
- Loop loop(&m);
- m.Return(m.Int32Constant(constant));
- }
- CHECK_EQ(constant, m.Call());
-}
-
-
-TEST(RunSimpleLoopBreak) {
- StructuredMachineAssemblerTester<int32_t> m;
- int32_t constant = 0x10ddb0a6;
- {
- Loop loop(&m);
- loop.Break();
- }
- m.Return(m.Int32Constant(constant));
- CHECK_EQ(constant, m.Call());
-}
-
-
-TEST(RunCountToTen) {
- StructuredMachineAssemblerTester<int32_t> m;
- Variable i = m.NewVariable(m.Int32Constant(0));
- Node* ten = m.Int32Constant(10);
- Node* one = m.Int32Constant(1);
- {
- Loop loop(&m);
- {
- IfBuilder cond(&m);
- cond.If(m.Word32Equal(i.Get(), ten)).Then();
- loop.Break();
- }
- i.Set(m.Int32Add(i.Get(), one));
- }
- m.Return(i.Get());
- CHECK_EQ(10, m.Call());
-}
-
-
-TEST(RunCountToTenAcc) {
- StructuredMachineAssemblerTester<int32_t> m;
- int32_t constant = 0xf27aed64;
- Variable i = m.NewVariable(m.Int32Constant(0));
- Variable var = m.NewVariable(m.Int32Constant(constant));
- Node* ten = m.Int32Constant(10);
- Node* one = m.Int32Constant(1);
- {
- Loop loop(&m);
- {
- IfBuilder cond(&m);
- cond.If(m.Word32Equal(i.Get(), ten)).Then();
- loop.Break();
- }
- i.Set(m.Int32Add(i.Get(), one));
- var.Set(m.Int32Add(var.Get(), i.Get()));
- }
- m.Return(var.Get());
-
- CHECK_EQ(constant + 10 + 9 * 5, m.Call());
-}
-
-
-TEST(RunSimpleNestedLoop) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- Node* zero = m.Int32Constant(0);
- Node* one = m.Int32Constant(1);
- Node* two = m.Int32Constant(2);
- Node* three = m.Int32Constant(3);
- {
- Loop l1(&m);
- {
- Loop l2(&m);
- {
- IfBuilder cond(&m);
- cond.If(m.Word32Equal(m.Parameter(0), one)).Then();
- l1.Break();
- }
- {
- Loop l3(&m);
- {
- IfBuilder cond(&m);
- cond.If(m.Word32Equal(m.Parameter(0), two)).Then();
- l2.Break();
- cond.Else();
- cond.If(m.Word32Equal(m.Parameter(0), three)).Then();
- l3.Break();
- }
- m.Return(three);
- }
- m.Return(two);
- }
- m.Return(one);
- }
- m.Return(zero);
-
- CHECK_EQ(0, m.Call(1));
- CHECK_EQ(1, m.Call(2));
- CHECK_EQ(2, m.Call(3));
- CHECK_EQ(3, m.Call(4));
-}
-
-
-TEST(RunFib) {
- StructuredMachineAssemblerTester<int32_t> m(kMachineWord32);
-
- // Constants.
- Node* zero = m.Int32Constant(0);
- Node* one = m.Int32Constant(1);
- Node* two = m.Int32Constant(2);
- // Variables.
- // cnt = input
- Variable cnt = m.NewVariable(m.Parameter(0));
- // if (cnt < 2) return i
- {
- IfBuilder lt2(&m);
- lt2.If(m.Int32LessThan(cnt.Get(), two)).Then();
- m.Return(cnt.Get());
- }
- // cnt -= 2
- cnt.Set(m.Int32Sub(cnt.Get(), two));
- // res = 1
- Variable res = m.NewVariable(one);
- {
- // prv_0 = 1
- // prv_1 = 1
- Variable prv_0 = m.NewVariable(one);
- Variable prv_1 = m.NewVariable(one);
- // while (cnt != 0) {
- Loop main(&m);
- {
- IfBuilder nz(&m);
- nz.If(m.Word32Equal(cnt.Get(), zero)).Then();
- main.Break();
- }
- // res = prv_0 + prv_1
- // prv_0 = prv_1
- // prv_1 = res
- res.Set(m.Int32Add(prv_0.Get(), prv_1.Get()));
- prv_0.Set(prv_1.Get());
- prv_1.Set(res.Get());
- // cnt--
- cnt.Set(m.Int32Sub(cnt.Get(), one));
- }
- m.Return(res.Get());
-
- int32_t values[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144};
- for (size_t i = 0; i < ARRAY_SIZE(values); i++) {
- CHECK_EQ(values[i], m.Call(static_cast<int32_t>(i)));
- }
-}
-
-
-static int VariableIntroduction() {
- while (true) {
- int ret = 0;
- for (int i = 0; i < 10; i++) {
- for (int j = i; j < 10; j++) {
- for (int k = j; k < 10; k++) {
- ret++;
- }
- ret++;
- }
- ret++;
- }
- return ret;
- }
-}
-
-
-TEST(RunVariableIntroduction) {
- StructuredMachineAssemblerTester<int32_t> m;
- Node* zero = m.Int32Constant(0);
- Node* one = m.Int32Constant(1);
- // Use an IfBuilder to get out of start block.
- {
- IfBuilder i0(&m);
- i0.If(zero).Then();
- m.Return(one);
- }
- Node* ten = m.Int32Constant(10);
- Variable v0 =
- m.NewVariable(zero); // Introduce variable outside of start block.
- {
- Loop l0(&m);
- Variable ret = m.NewVariable(zero); // Introduce loop variable.
- {
- Loop l1(&m);
- {
- IfBuilder i1(&m);
- i1.If(m.Word32Equal(v0.Get(), ten)).Then();
- l1.Break();
- }
- Variable v1 = m.NewVariable(v0.Get()); // Introduce loop variable.
- {
- Loop l2(&m);
- {
- IfBuilder i2(&m);
- i2.If(m.Word32Equal(v1.Get(), ten)).Then();
- l2.Break();
- }
- Variable v2 = m.NewVariable(v1.Get()); // Introduce loop variable.
- {
- Loop l3(&m);
- {
- IfBuilder i3(&m);
- i3.If(m.Word32Equal(v2.Get(), ten)).Then();
- l3.Break();
- }
- ret.Set(m.Int32Add(ret.Get(), one));
- v2.Set(m.Int32Add(v2.Get(), one));
- }
- ret.Set(m.Int32Add(ret.Get(), one));
- v1.Set(m.Int32Add(v1.Get(), one));
- }
- ret.Set(m.Int32Add(ret.Get(), one));
- v0.Set(m.Int32Add(v0.Get(), one));
- }
- m.Return(ret.Get()); // Return loop variable.
- }
- CHECK_EQ(VariableIntroduction(), m.Call());
-}
-
-
-TEST(RunIfBuilderVariableLiveness) {
- StructuredMachineAssemblerTester<int32_t> m;
- typedef i::compiler::StructuredMachineAssemblerFriend F;
- Node* zero = m.Int32Constant(0);
- Variable v_outer = m.NewVariable(zero);
- IfBuilder cond(&m);
- cond.If(zero).Then();
- Variable v_then = m.NewVariable(zero);
- CHECK(F::VariableAlive(&m, v_outer));
- CHECK(F::VariableAlive(&m, v_then));
- cond.Else();
- Variable v_else = m.NewVariable(zero);
- CHECK(F::VariableAlive(&m, v_outer));
- CHECK(F::VariableAlive(&m, v_else));
- CHECK(!F::VariableAlive(&m, v_then));
- cond.End();
- CHECK(F::VariableAlive(&m, v_outer));
- CHECK(!F::VariableAlive(&m, v_then));
- CHECK(!F::VariableAlive(&m, v_else));
-}
-
-
-TEST(RunSimpleExpression1) {
- StructuredMachineAssemblerTester<int32_t> m;
-
- int32_t constant = 0x0c2974ef;
- Node* zero = m.Int32Constant(0);
- Node* one = m.Int32Constant(1);
- {
- // if (((1 && 1) && 1) && 1) return constant; return 0;
- IfBuilder cond(&m);
- cond.OpenParen();
- cond.OpenParen().If(one).And();
- cond.If(one).CloseParen().And();
- cond.If(one).CloseParen().And();
- cond.If(one).Then();
- m.Return(m.Int32Constant(constant));
- }
- m.Return(zero);
-
- CHECK_EQ(constant, m.Call());
-}
-
-
-TEST(RunSimpleExpression2) {
- StructuredMachineAssemblerTester<int32_t> m;
-
- int32_t constant = 0x2eddc11b;
- Node* zero = m.Int32Constant(0);
- Node* one = m.Int32Constant(1);
- {
- // if (((0 || 1) && 1) && 1) return constant; return 0;
- IfBuilder cond(&m);
- cond.OpenParen();
- cond.OpenParen().If(zero).Or();
- cond.If(one).CloseParen().And();
- cond.If(one).CloseParen().And();
- cond.If(one).Then();
- m.Return(m.Int32Constant(constant));
- }
- m.Return(zero);
-
- CHECK_EQ(constant, m.Call());
-}
-
-
-TEST(RunSimpleExpression3) {
- StructuredMachineAssemblerTester<int32_t> m;
-
- int32_t constant = 0x9ed5e9ef;
- Node* zero = m.Int32Constant(0);
- Node* one = m.Int32Constant(1);
- {
- // if (1 && ((0 || 1) && 1) && 1) return constant; return 0;
- IfBuilder cond(&m);
- cond.If(one).And();
- cond.OpenParen();
- cond.OpenParen().If(zero).Or();
- cond.If(one).CloseParen().And();
- cond.If(one).CloseParen().And();
- cond.If(one).Then();
- m.Return(m.Int32Constant(constant));
- }
- m.Return(zero);
-
- CHECK_EQ(constant, m.Call());
-}
-
-
-TEST(RunSimpleExpressionVariable1) {
- StructuredMachineAssemblerTester<int32_t> m;
-
- int32_t constant = 0x4b40a986;
- Node* one = m.Int32Constant(1);
- Variable var = m.NewVariable(m.Int32Constant(constant));
- {
- // if (var.Get() && ((!var || var) && var) && var) {} return var;
- // incrementing var in each environment.
- IfBuilder cond(&m);
- cond.If(var.Get()).And();
- var.Set(m.Int32Add(var.Get(), one));
- cond.OpenParen().OpenParen().If(m.Word32BinaryNot(var.Get())).Or();
- var.Set(m.Int32Add(var.Get(), one));
- cond.If(var.Get()).CloseParen().And();
- var.Set(m.Int32Add(var.Get(), one));
- cond.If(var.Get()).CloseParen().And();
- var.Set(m.Int32Add(var.Get(), one));
- cond.If(var.Get());
- }
- m.Return(var.Get());
-
- CHECK_EQ(constant + 4, m.Call());
-}
-
-
-class QuicksortHelper : public StructuredMachineAssemblerTester<int32_t> {
- public:
- QuicksortHelper()
- : StructuredMachineAssemblerTester(
- MachineOperatorBuilder::pointer_rep(), kMachineWord32,
- MachineOperatorBuilder::pointer_rep(), kMachineWord32),
- input_(NULL),
- stack_limit_(NULL),
- one_(Int32Constant(1)),
- stack_frame_size_(Int32Constant(kFrameVariables * 4)),
- left_offset_(Int32Constant(0 * 4)),
- right_offset_(Int32Constant(1 * 4)) {
- Build();
- }
-
- int32_t DoCall(int32_t* input, int32_t input_length) {
- int32_t stack_space[20];
- // Do call.
- int32_t return_val = Call(input, input_length, stack_space,
- static_cast<int32_t>(ARRAY_SIZE(stack_space)));
- // Ran out of stack space.
- if (return_val != 0) return return_val;
- // Check sorted.
- int32_t last = input[0];
- for (int32_t i = 0; i < input_length; i++) {
- CHECK(last <= input[i]);
- last = input[i];
- }
- return return_val;
- }
-
- private:
- void Inc32(const Variable& var) { var.Set(Int32Add(var.Get(), one_)); }
- Node* Index(Node* index) { return Word32Shl(index, Int32Constant(2)); }
- Node* ArrayLoad(Node* index) {
- return Load(kMachineWord32, input_, Index(index));
- }
- void Swap(Node* a_index, Node* b_index) {
- Node* a = ArrayLoad(a_index);
- Node* b = ArrayLoad(b_index);
- Store(kMachineWord32, input_, Index(a_index), b);
- Store(kMachineWord32, input_, Index(b_index), a);
- }
- void AddToCallStack(const Variable& fp, Node* left, Node* right) {
- {
- // Stack limit check.
- IfBuilder cond(this);
- cond.If(IntPtrLessThanOrEqual(fp.Get(), stack_limit_)).Then();
- Return(Int32Constant(-1));
- }
- Store(kMachineWord32, fp.Get(), left_offset_, left);
- Store(kMachineWord32, fp.Get(), right_offset_, right);
- fp.Set(IntPtrAdd(fp.Get(), ConvertInt32ToIntPtr(stack_frame_size_)));
- }
- void Build() {
- Variable left = NewVariable(Int32Constant(0));
- Variable right =
- NewVariable(Int32Sub(Parameter(kInputLengthParameter), one_));
- input_ = Parameter(kInputParameter);
- Node* top_of_stack = Parameter(kStackParameter);
- stack_limit_ = IntPtrSub(
- top_of_stack, ConvertInt32ToIntPtr(Parameter(kStackLengthParameter)));
- Variable fp = NewVariable(top_of_stack);
- {
- Loop outermost(this);
- // Edge case - 2 element array.
- {
- IfBuilder cond(this);
- cond.If(Word32Equal(left.Get(), Int32Sub(right.Get(), one_))).And();
- cond.If(Int32LessThanOrEqual(ArrayLoad(right.Get()),
- ArrayLoad(left.Get()))).Then();
- Swap(left.Get(), right.Get());
- }
- {
- IfBuilder cond(this);
- // Algorithm complete condition.
- cond.If(WordEqual(top_of_stack, fp.Get())).And();
- cond.If(Int32LessThanOrEqual(Int32Sub(right.Get(), one_), left.Get()))
- .Then();
- outermost.Break();
- // 'Recursion' exit condition. Pop frame and continue.
- cond.Else();
- cond.If(Int32LessThanOrEqual(Int32Sub(right.Get(), one_), left.Get()))
- .Then();
- fp.Set(IntPtrSub(fp.Get(), ConvertInt32ToIntPtr(stack_frame_size_)));
- left.Set(Load(kMachineWord32, fp.Get(), left_offset_));
- right.Set(Load(kMachineWord32, fp.Get(), right_offset_));
- outermost.Continue();
- }
- // Partition.
- Variable store_index = NewVariable(left.Get());
- {
- Node* pivot_index =
- Int32Div(Int32Add(left.Get(), right.Get()), Int32Constant(2));
- Node* pivot = ArrayLoad(pivot_index);
- Swap(pivot_index, right.Get());
- Variable i = NewVariable(left.Get());
- {
- Loop partition(this);
- {
- IfBuilder cond(this);
- // Parition complete.
- cond.If(Word32Equal(i.Get(), right.Get())).Then();
- partition.Break();
- // Need swap.
- cond.Else();
- cond.If(Int32LessThanOrEqual(ArrayLoad(i.Get()), pivot)).Then();
- Swap(i.Get(), store_index.Get());
- Inc32(store_index);
- }
- Inc32(i);
- } // End partition loop.
- Swap(store_index.Get(), right.Get());
- }
- // 'Recurse' left and right halves of partition.
- // Tail recurse second one.
- AddToCallStack(fp, left.Get(), Int32Sub(store_index.Get(), one_));
- left.Set(Int32Add(store_index.Get(), one_));
- } // End outermost loop.
- Return(Int32Constant(0));
- }
-
- static const int kFrameVariables = 2; // left, right
- // Parameter offsets.
- static const int kInputParameter = 0;
- static const int kInputLengthParameter = 1;
- static const int kStackParameter = 2;
- static const int kStackLengthParameter = 3;
- // Function inputs.
- Node* input_;
- Node* stack_limit_;
- // Constants.
- Node* const one_;
- // Frame constants.
- Node* const stack_frame_size_;
- Node* const left_offset_;
- Node* const right_offset_;
-};
-
-
-TEST(RunSimpleQuicksort) {
- QuicksortHelper m;
- int32_t inputs[] = {9, 7, 1, 8, 11};
- CHECK_EQ(0, m.DoCall(inputs, ARRAY_SIZE(inputs)));
-}
-
-
-TEST(RunRandomQuicksort) {
- QuicksortHelper m;
-
- v8::base::RandomNumberGenerator rng;
- static const int kMaxLength = 40;
- int32_t inputs[kMaxLength];
-
- for (int length = 1; length < kMaxLength; length++) {
- for (int i = 0; i < 70; i++) {
- // Randomize inputs.
- for (int j = 0; j < length; j++) {
- inputs[j] = rng.NextInt(10) - 5;
- }
- CHECK_EQ(0, m.DoCall(inputs, length));
- }
- }
-}
-
-
-TEST(MultipleScopes) {
- StructuredMachineAssemblerTester<int32_t> m;
- for (int i = 0; i < 10; i++) {
- IfBuilder b(&m);
- b.If(m.Int32Constant(0)).Then();
- m.NewVariable(m.Int32Constant(0));
- }
- m.Return(m.Int32Constant(0));
- CHECK_EQ(0, m.Call());
-}
-
-#endif
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_CCTEST_COMPILER_VALUE_HELPER_H_
-#define V8_CCTEST_COMPILER_VALUE_HELPER_H_
-
-#include "src/compiler/common-operator.h"
-#include "src/compiler/node.h"
-#include "src/compiler/node-matchers.h"
-#include "src/isolate.h"
-#include "src/objects.h"
-#include "test/cctest/cctest.h"
-#include "v8.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-// A collection of utilities related to numerical and heap values, including
-// example input values of various types, including int32_t, uint32_t, double,
-// etc.
-class ValueHelper {
- public:
- Isolate* isolate_;
-
- ValueHelper() : isolate_(CcTest::InitIsolateOnce()) {}
-
- template <typename T>
- void CheckConstant(T expected, Node* node) {
- CHECK_EQ(expected, ValueOf<T>(node->op()));
- }
-
- void CheckFloat64Constant(double expected, Node* node) {
- CHECK_EQ(IrOpcode::kFloat64Constant, node->opcode());
- CHECK_EQ(expected, ValueOf<double>(node->op()));
- }
-
- void CheckNumberConstant(double expected, Node* node) {
- CHECK_EQ(IrOpcode::kNumberConstant, node->opcode());
- CHECK_EQ(expected, ValueOf<double>(node->op()));
- }
-
- void CheckInt32Constant(int32_t expected, Node* node) {
- CHECK_EQ(IrOpcode::kInt32Constant, node->opcode());
- CHECK_EQ(expected, ValueOf<int32_t>(node->op()));
- }
-
- void CheckUint32Constant(int32_t expected, Node* node) {
- CHECK_EQ(IrOpcode::kInt32Constant, node->opcode());
- CHECK_EQ(expected, ValueOf<uint32_t>(node->op()));
- }
-
- void CheckHeapConstant(Object* expected, Node* node) {
- CHECK_EQ(IrOpcode::kHeapConstant, node->opcode());
- CHECK_EQ(expected, *ValueOf<Handle<Object> >(node->op()));
- }
-
- void CheckTrue(Node* node) {
- CheckHeapConstant(isolate_->heap()->true_value(), node);
- }
-
- void CheckFalse(Node* node) {
- CheckHeapConstant(isolate_->heap()->false_value(), node);
- }
-
- static std::vector<double> float64_vector() {
- static const double nan = v8::base::OS::nan_value();
- static const double values[] = {
- 0.125, 0.25, 0.375, 0.5,
- 1.25, -1.75, 2, 5.125,
- 6.25, 0.0, -0.0, 982983.25,
- 888, 2147483647.0, -999.75, 3.1e7,
- -2e66, 3e-88, -2147483648.0, V8_INFINITY,
- -V8_INFINITY, nan, 2147483647.375, 2147483647.75,
- 2147483648.0, 2147483648.25, 2147483649.25, -2147483647.0,
- -2147483647.125, -2147483647.875, -2147483648.25, -2147483649.5};
- return std::vector<double>(&values[0], &values[ARRAY_SIZE(values)]);
- }
-
- static const std::vector<int32_t> int32_vector() {
- std::vector<uint32_t> values = uint32_vector();
- return std::vector<int32_t>(values.begin(), values.end());
- }
-
- static const std::vector<uint32_t> uint32_vector() {
- static const uint32_t kValues[] = {
- 0x00000000, 0x00000001, 0xffffffff, 0x1b09788b, 0x04c5fce8, 0xcc0de5bf,
- 0x273a798e, 0x187937a3, 0xece3af83, 0x5495a16b, 0x0b668ecc, 0x11223344,
- 0x0000009e, 0x00000043, 0x0000af73, 0x0000116b, 0x00658ecc, 0x002b3b4c,
- 0x88776655, 0x70000000, 0x07200000, 0x7fffffff, 0x56123761, 0x7fffff00,
- 0x761c4761, 0x80000000, 0x88888888, 0xa0000000, 0xdddddddd, 0xe0000000,
- 0xeeeeeeee, 0xfffffffd, 0xf0000000, 0x007fffff, 0x003fffff, 0x001fffff,
- 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff, 0x0000ffff, 0x00007fff,
- 0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff};
- return std::vector<uint32_t>(&kValues[0], &kValues[ARRAY_SIZE(kValues)]);
- }
-
- static const std::vector<double> nan_vector(size_t limit = 0) {
- static const double nan = v8::base::OS::nan_value();
- static const double values[] = {-nan, -V8_INFINITY * -0.0,
- -V8_INFINITY * 0.0, V8_INFINITY * -0.0,
- V8_INFINITY * 0.0, nan};
- return std::vector<double>(&values[0], &values[ARRAY_SIZE(values)]);
- }
-};
-
-// Helper macros that can be used in FOR_INT32_INPUTS(i) { ... *i ... }
-// Watch out, these macros aren't hygenic; they pollute your scope. Thanks STL.
-#define FOR_INPUTS(ctype, itype, var) \
- std::vector<ctype> var##_vec = ValueHelper::itype##_vector(); \
- for (std::vector<ctype>::iterator var = var##_vec.begin(); \
- var != var##_vec.end(); ++var)
-
-#define FOR_INT32_INPUTS(var) FOR_INPUTS(int32_t, int32, var)
-#define FOR_UINT32_INPUTS(var) FOR_INPUTS(uint32_t, uint32, var)
-#define FOR_FLOAT64_INPUTS(var) FOR_INPUTS(double, float64, var)
-}
-}
-} // namespace v8::internal::compiler
-
-#endif // V8_CCTEST_COMPILER_VALUE_HELPER_H_