diff options
Diffstat (limited to 'deps/v8/test')
503 files changed, 30539 insertions, 9510 deletions
diff --git a/deps/v8/test/cctest/cctest.gyp b/deps/v8/test/cctest/cctest.gyp index 276ebd2f97..bcbbe7b226 100644 --- a/deps/v8/test/cctest/cctest.gyp +++ b/deps/v8/test/cctest/cctest.gyp @@ -54,8 +54,6 @@ 'compiler/test-basic-block-profiler.cc', 'compiler/test-branch-combine.cc', 'compiler/test-changes-lowering.cc', - 'compiler/test-codegen-deopt.cc', - 'compiler/test-control-reducer.cc', 'compiler/test-gap-resolver.cc', 'compiler/test-graph-visualizer.cc', 'compiler/test-instruction.cc', diff --git a/deps/v8/test/cctest/cctest.h b/deps/v8/test/cctest/cctest.h index bade26308f..cc9edc801f 100644 --- a/deps/v8/test/cctest/cctest.h +++ b/deps/v8/test/cctest/cctest.h @@ -93,6 +93,7 @@ class TestHeap : public i::Heap { using i::Heap::AllocateByteArray; using i::Heap::AllocateFixedArray; using i::Heap::AllocateHeapNumber; + using i::Heap::AllocateFloat32x4; using i::Heap::AllocateJSObject; using i::Heap::AllocateJSObjectFromMap; using i::Heap::AllocateMap; @@ -397,6 +398,13 @@ static inline v8::Local<v8::Value> CompileRun(const char* source) { } +// Helper functions that compile and run the source. +static inline v8::MaybeLocal<v8::Value> CompileRun( + v8::Local<v8::Context> context, const char* source) { + return v8::Script::Compile(v8_str(source))->Run(context); +} + + // Compiles source as an ES6 module. static inline v8::Local<v8::Value> CompileRunModule(const char* source) { v8::ScriptCompiler::Source script_source(v8_str(source)); @@ -504,8 +512,8 @@ static inline void ExpectUndefined(const char* code) { // Helper function that simulates a full new-space in the heap. static inline bool FillUpOnePage(v8::internal::NewSpace* space) { - v8::internal::AllocationResult allocation = - space->AllocateRaw(v8::internal::Page::kMaxRegularHeapObjectSize); + v8::internal::AllocationResult allocation = space->AllocateRawUnaligned( + v8::internal::Page::kMaxRegularHeapObjectSize); if (allocation.IsRetry()) return false; v8::internal::HeapObject* free_space = NULL; CHECK(allocation.To(&free_space)); @@ -524,7 +532,7 @@ static inline void AllocateAllButNBytes(v8::internal::NewSpace* space, int new_linear_size = space_remaining - extra_bytes; if (new_linear_size == 0) return; v8::internal::AllocationResult allocation = - space->AllocateRaw(new_linear_size); + space->AllocateRawUnaligned(new_linear_size); v8::internal::HeapObject* free_space = NULL; CHECK(allocation.To(&free_space)); space->heap()->CreateFillerObjectAt(free_space->address(), new_linear_size); @@ -561,7 +569,7 @@ static inline void SimulateIncrementalMarking(i::Heap* heap) { } CHECK(marking->IsMarking() || marking->IsStopped()); if (marking->IsStopped()) { - marking->Start(); + marking->Start(i::Heap::kNoGCFlags); } CHECK(marking->IsMarking()); while (!marking->IsComplete()) { @@ -574,6 +582,18 @@ static inline void SimulateIncrementalMarking(i::Heap* heap) { } +static void DummyDebugEventListener( + const v8::Debug::EventDetails& event_details) {} + + +static inline void EnableDebugger() { + v8::Debug::SetDebugEventListener(&DummyDebugEventListener); +} + + +static inline void DisableDebugger() { v8::Debug::SetDebugEventListener(NULL); } + + // Helper class for new allocations tracking and checking. // To use checking of JS allocations tracking in a test, // just create an instance of this class. diff --git a/deps/v8/test/cctest/cctest.status b/deps/v8/test/cctest/cctest.status index 9c4f6ccf05..68c570edcc 100644 --- a/deps/v8/test/cctest/cctest.status +++ b/deps/v8/test/cctest/cctest.status @@ -64,11 +64,13 @@ # are actually 13 * 38 * 5 * 128 = 316160 individual tests hidden here. 'test-parsing/ParserSync': [PASS, NO_VARIANTS], - # This tests only the type system, so there is no point in running several - # variants. + # This tests only the type system, no point in running several variants. 'test-hydrogen-types/*': [PASS, NO_VARIANTS], 'test-types/*': [PASS, NO_VARIANTS], + # This tests API threading, no point in running several variants. + 'test-api/Threading*': [PASS, NO_VARIANTS], + # The cpu profiler tests are notoriously flaky. # BUG(2999). (test/cpu-profiler/CollectCpuProfile) # BUG(3287). (test-cpu-profiler/SampleWhenFrameIsNotSetup) @@ -97,11 +99,7 @@ ############################################################################## # TurboFan compiler failures. - # TODO(mstarzinger): control edges are messed up in exception tests. - 'test-run-jsexceptions/*': [PASS, NO_VARIANTS], - # Some tests are just too slow to run for now. - 'test-api/Threading*': [PASS, NO_VARIANTS], 'test-heap/IncrementalMarkingStepMakesBigProgressWithLargeObjects': [PASS, NO_VARIANTS], 'test-heap-profiler/ManyLocalsInSharedContext': [PASS, NO_VARIANTS], 'test-serialize/SerializeToplevelLargeCodeObject': [PASS, NO_VARIANTS], @@ -119,12 +117,6 @@ 'test-debug/ScriptBreakPointByIdThroughJavaScript': [PASS, NO_VARIANTS], 'test-debug/ScriptBreakPointByNameThroughJavaScript': [PASS, NO_VARIANTS], - # TODO(jarin): Cannot lazy-deoptimize from conversions before comparisons. - 'test-js-typed-lowering/OrderCompareEffects': [SKIP], - - # TODO(jochen): Reenable after we removed the CHECK() from the marking queue. - 'test-mark-compact/MarkingDeque': [SKIP], - ############################################################################ # Slow tests. 'test-api/Threading1': [PASS, ['mode == debug', SLOW]], @@ -194,6 +186,12 @@ ['msan == True', { # ICU upstream issues. 'test-strings/CountBreakIterator': [SKIP], + + # Slow tests. + 'test-api/Threading1': [PASS, SLOW], + 'test-api/Threading2': [PASS, SLOW], + 'test-api/Threading3': [PASS, SLOW], + 'test-api/Threading4': [PASS, SLOW], }], # 'msan == True' ############################################################################## @@ -258,6 +256,9 @@ ['arch == mipsel or arch == mips', { 'test-cpu-profiler/CollectDeoptEvents': [PASS, FAIL], + # TODO(mips-team): Improve code-size on large RegExp's. + 'test-heap/TestSizeOfRegExpCode': [SKIP], + # BUG(1075): Unresolved crashes on MIPS also. 'test-serialize/Deserialize': [SKIP], 'test-serialize/DeserializeFromSecondSerializationAndRunScript2': [SKIP], @@ -271,12 +272,8 @@ 'test-api/ExternalArrays': [PASS, NO_VARIANTS], # TODO(mips-team): Currently fails on mips board. - 'test-simplified-lowering/RunNumberMultiply_TruncatingToUint32': [SKIP], - 'test-simplified-lowering/RunNumberDivide_2_TruncatingToUint32': [SKIP], 'test-parsing/TooManyArguments': [SKIP], 'test-api/Threading3': [SKIP], - 'test-api/RequestInterruptTestWithNativeAccessor': [SKIP], - 'test-api/RequestInterruptTestWithAccessor': [SKIP], }], # 'arch == mips' ############################################################################## @@ -295,12 +292,7 @@ ############################################################################## ['arch == x87', { - - # Test requires turbofan: - 'codegen-tester/CompareWrapper': [SKIP], - 'codegen-tester/ParametersEqual': [SKIP], - 'test-simplified-lowering/LowerStringOps_to_call_and_compare': [SKIP], - 'test-serialize/SerializeInternalReference': [FAIL], + 'test-run-machops/RunFloat64InsertLowWord32': [SKIP] }], # 'arch == x87' ############################################################################## diff --git a/deps/v8/test/cctest/compiler/c-signature.h b/deps/v8/test/cctest/compiler/c-signature.h index 5d161dbe7a..83b3328a3b 100644 --- a/deps/v8/test/cctest/compiler/c-signature.h +++ b/deps/v8/test/cctest/compiler/c-signature.h @@ -11,76 +11,103 @@ namespace v8 { namespace internal { namespace compiler { +#define FOREACH_CTYPE_MACHINE_TYPE_MAPPING(V) \ + V(void, kMachNone) \ + V(bool, kMachBool) \ + V(int8_t, kMachInt8) \ + V(uint8_t, kMachUint8) \ + V(int16_t, kMachInt16) \ + V(uint16_t, kMachUint16) \ + V(int32_t, kMachInt32) \ + V(uint32_t, kMachUint32) \ + V(int64_t, kMachInt64) \ + V(uint64_t, kMachUint64) \ + V(float, kMachFloat32) \ + V(double, kMachFloat64) \ + V(void*, kMachPtr) \ + V(int*, kMachPtr) + template <typename T> inline MachineType MachineTypeForC() { - CHECK(false); // Instantiated with invalid type. - return kMachNone; -} - -template <> -inline MachineType MachineTypeForC<void>() { - return kMachNone; -} - -template <> -inline MachineType MachineTypeForC<int8_t>() { - return kMachInt8; -} - -template <> -inline MachineType MachineTypeForC<uint8_t>() { - return kMachUint8; -} - -template <> -inline MachineType MachineTypeForC<int16_t>() { - return kMachInt16; -} - -template <> -inline MachineType MachineTypeForC<uint16_t>() { - return kMachUint16; -} - -template <> -inline MachineType MachineTypeForC<int32_t>() { - return kMachInt32; + while (false) { + // All other types T must be assignable to Object* + *(static_cast<Object* volatile*>(0)) = static_cast<T>(0); + } + return kMachAnyTagged; } -template <> -inline MachineType MachineTypeForC<uint32_t>() { - return kMachUint32; -} +#define DECLARE_TEMPLATE_SPECIALIZATION(ctype, mtype) \ + template <> \ + inline MachineType MachineTypeForC<ctype>() { \ + return mtype; \ + } +FOREACH_CTYPE_MACHINE_TYPE_MAPPING(DECLARE_TEMPLATE_SPECIALIZATION) +#undef DECLARE_TEMPLATE_SPECIALIZATION -template <> -inline MachineType MachineTypeForC<int64_t>() { - return kMachInt64; -} +// Helper for building machine signatures from C types. +class CSignature : public MachineSignature { + protected: + CSignature(size_t return_count, size_t parameter_count, MachineType* reps) + : MachineSignature(return_count, parameter_count, reps) {} -template <> -inline MachineType MachineTypeForC<uint64_t>() { - return kMachUint64; -} + public: + template <typename P1 = void, typename P2 = void, typename P3 = void, + typename P4 = void, typename P5 = void> + void VerifyParams() { + // Verifies the C signature against the machine types. Maximum {5} params. + CHECK_LT(parameter_count(), 6u); + const int kMax = 5; + MachineType params[] = {MachineTypeForC<P1>(), MachineTypeForC<P2>(), + MachineTypeForC<P3>(), MachineTypeForC<P4>(), + MachineTypeForC<P5>()}; + for (int p = kMax - 1; p >= 0; p--) { + if (p < static_cast<int>(parameter_count())) { + CHECK_EQ(GetParam(p), params[p]); + } else { + CHECK_EQ(kMachNone, params[p]); + } + } + } -template <> -inline MachineType MachineTypeForC<double>() { - return kMachFloat64; -} + static CSignature* New(Zone* zone, MachineType ret, + MachineType p1 = kMachNone, MachineType p2 = kMachNone, + MachineType p3 = kMachNone, MachineType p4 = kMachNone, + MachineType p5 = kMachNone) { + MachineType* buffer = zone->NewArray<MachineType>(6); + int pos = 0; + size_t return_count = 0; + if (ret != kMachNone) { + buffer[pos++] = ret; + return_count++; + } + buffer[pos++] = p1; + buffer[pos++] = p2; + buffer[pos++] = p3; + buffer[pos++] = p4; + buffer[pos++] = p5; + size_t param_count = 5; + if (p5 == kMachNone) param_count--; + if (p4 == kMachNone) param_count--; + if (p3 == kMachNone) param_count--; + if (p2 == kMachNone) param_count--; + if (p1 == kMachNone) param_count--; + for (size_t i = 0; i < param_count; i++) { + // Check that there are no kMachNone's in the middle of parameters. + CHECK_NE(kMachNone, buffer[return_count + i]); + } + return new (zone) CSignature(return_count, param_count, buffer); + } +}; -template <> -inline MachineType MachineTypeForC<Object*>() { - return kMachAnyTagged; -} template <typename Ret, uint16_t kParamCount> -class CSignatureOf : public MachineSignature { +class CSignatureOf : public CSignature { protected: MachineType storage_[1 + kParamCount]; CSignatureOf() - : MachineSignature(MachineTypeForC<Ret>() != kMachNone ? 1 : 0, - kParamCount, - reinterpret_cast<MachineType*>(&storage_)) { + : CSignature(MachineTypeForC<Ret>() != kMachNone ? 1 : 0, kParamCount, + reinterpret_cast<MachineType*>(&storage_)) { if (return_count_ == 1) storage_[0] = MachineTypeForC<Ret>(); } void Set(int index, MachineType type) { @@ -123,9 +150,11 @@ class CSignature3 : public CSignatureOf<Ret, 3> { } }; -static const CSignature2<int32_t, int32_t, int32_t> int32_int32_to_int32; -static const CSignature2<uint32_t, uint32_t, uint32_t> uint32_uint32_to_uint32; -static const CSignature2<double, double, double> float64_float64_to_float64; +typedef CSignature2<int32_t, int32_t, int32_t> CSignature_i_ii; +typedef CSignature2<uint32_t, uint32_t, uint32_t> CSignature_u_uu; +typedef CSignature2<float, float, float> CSignature_f_ff; +typedef CSignature2<double, double, double> CSignature_d_dd; +typedef CSignature2<Object*, Object*, Object*> CSignature_o_oo; } } } // namespace v8::internal::compiler diff --git a/deps/v8/test/cctest/compiler/call-tester.h b/deps/v8/test/cctest/compiler/call-tester.h index 6d8c761452..dc265ea5fa 100644 --- a/deps/v8/test/cctest/compiler/call-tester.h +++ b/deps/v8/test/cctest/compiler/call-tester.h @@ -9,6 +9,8 @@ #include "src/simulator.h" +#include "test/cctest/compiler/c-signature.h" + #if V8_TARGET_ARCH_IA32 #if __GNUC__ #define V8_CDECL __attribute__((cdecl)) @@ -23,95 +25,64 @@ namespace v8 { namespace internal { namespace compiler { -// TODO(titzer): use c-signature.h instead of ReturnValueTraits template <typename R> -struct ReturnValueTraits { - static R Cast(uintptr_t r) { return reinterpret_cast<R>(r); } - static MachineType Representation() { - // TODO(dcarney): detect when R is of a subclass of Object* instead of this - // type check. - while (false) { - *(static_cast<Object* volatile*>(0)) = static_cast<R>(0); - } - return kMachAnyTagged; - } -}; +inline R CastReturnValue(uintptr_t r) { + return reinterpret_cast<R>(r); +} template <> -struct ReturnValueTraits<int32_t*> { - static int32_t* Cast(uintptr_t r) { return reinterpret_cast<int32_t*>(r); } - static MachineType Representation() { return kMachPtr; } -}; +inline void CastReturnValue(uintptr_t r) {} template <> -struct ReturnValueTraits<void> { - static void Cast(uintptr_t r) {} - static MachineType Representation() { return kMachPtr; } -}; +inline bool CastReturnValue(uintptr_t r) { + return static_cast<bool>(r); +} template <> -struct ReturnValueTraits<bool> { - static bool Cast(uintptr_t r) { return static_cast<bool>(r); } - static MachineType Representation() { return kRepBit; } -}; +inline int32_t CastReturnValue(uintptr_t r) { + return static_cast<int32_t>(r); +} template <> -struct ReturnValueTraits<int32_t> { - static int32_t Cast(uintptr_t r) { return static_cast<int32_t>(r); } - static MachineType Representation() { return kMachInt32; } -}; +inline uint32_t CastReturnValue(uintptr_t r) { + return static_cast<uint32_t>(r); +} template <> -struct ReturnValueTraits<uint32_t> { - static uint32_t Cast(uintptr_t r) { return static_cast<uint32_t>(r); } - static MachineType Representation() { return kMachUint32; } -}; - -template <> -struct ReturnValueTraits<int64_t> { - static int64_t Cast(uintptr_t r) { return static_cast<int64_t>(r); } - static MachineType Representation() { return kMachInt64; } -}; +inline int64_t CastReturnValue(uintptr_t r) { + return static_cast<int64_t>(r); +} template <> -struct ReturnValueTraits<uint64_t> { - static uint64_t Cast(uintptr_t r) { return static_cast<uint64_t>(r); } - static MachineType Representation() { return kMachUint64; } -}; +inline uint64_t CastReturnValue(uintptr_t r) { + return static_cast<uint64_t>(r); +} template <> -struct ReturnValueTraits<int16_t> { - static int16_t Cast(uintptr_t r) { return static_cast<int16_t>(r); } - static MachineType Representation() { return kMachInt16; } -}; +inline int16_t CastReturnValue(uintptr_t r) { + return static_cast<int16_t>(r); +} template <> -struct ReturnValueTraits<uint16_t> { - static uint16_t Cast(uintptr_t r) { return static_cast<uint16_t>(r); } - static MachineType Representation() { return kMachUint16; } -}; +inline uint16_t CastReturnValue(uintptr_t r) { + return static_cast<uint16_t>(r); +} template <> -struct ReturnValueTraits<int8_t> { - static int8_t Cast(uintptr_t r) { return static_cast<int8_t>(r); } - static MachineType Representation() { return kMachInt8; } -}; +inline int8_t CastReturnValue(uintptr_t r) { + return static_cast<int8_t>(r); +} template <> -struct ReturnValueTraits<uint8_t> { - static uint8_t Cast(uintptr_t r) { return static_cast<uint8_t>(r); } - static MachineType Representation() { return kMachUint8; } -}; +inline uint8_t CastReturnValue(uintptr_t r) { + return static_cast<uint8_t>(r); +} template <> -struct ReturnValueTraits<double> { - static double Cast(uintptr_t r) { - UNREACHABLE(); - return 0.0; - } - static MachineType Representation() { return kMachFloat64; } -}; - +inline double CastReturnValue(uintptr_t r) { + UNREACHABLE(); + return 0.0; +} template <typename R> struct ParameterTraits { @@ -148,42 +119,52 @@ struct ParameterTraits<uint32_t> { #endif // !V8_TARGET_ARCH_64_BIT +template <typename R> class CallHelper { public: - explicit CallHelper(Isolate* isolate, MachineSignature* machine_sig) - : machine_sig_(machine_sig), isolate_(isolate) { + explicit CallHelper(Isolate* isolate, CSignature* csig) + : csig_(csig), isolate_(isolate) { USE(isolate_); } virtual ~CallHelper() {} - static MachineSignature* MakeMachineSignature( - Zone* zone, MachineType return_type, MachineType p0 = kMachNone, - MachineType p1 = kMachNone, MachineType p2 = kMachNone, - MachineType p3 = kMachNone, MachineType p4 = kMachNone) { - // Count the number of parameters. - size_t param_count = 5; - MachineType types[] = {p0, p1, p2, p3, p4}; - while (param_count > 0 && types[param_count - 1] == kMachNone) - param_count--; - size_t return_count = return_type == kMachNone ? 0 : 1; - - // Build the machine signature. - MachineSignature::Builder builder(zone, return_count, param_count); - if (return_count > 0) builder.AddReturn(return_type); - for (size_t i = 0; i < param_count; i++) { - builder.AddParam(types[i]); - } - return builder.Build(); + R Call() { + typedef R V8_CDECL FType(); + csig_->VerifyParams(); + return DoCall(FUNCTION_CAST<FType*>(Generate())); } - protected: - MachineSignature* machine_sig_; - void VerifyParameters(size_t parameter_count, MachineType* parameter_types) { - CHECK(machine_sig_->parameter_count() == parameter_count); - for (size_t i = 0; i < parameter_count; i++) { - CHECK_EQ(machine_sig_->GetParam(i), parameter_types[i]); - } + template <typename P1> + R Call(P1 p1) { + typedef R V8_CDECL FType(P1); + csig_->VerifyParams<P1>(); + return DoCall(FUNCTION_CAST<FType*>(Generate()), p1); + } + + template <typename P1, typename P2> + R Call(P1 p1, P2 p2) { + typedef R V8_CDECL FType(P1, P2); + csig_->VerifyParams<P1, P2>(); + return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2); + } + + template <typename P1, typename P2, typename P3> + R Call(P1 p1, P2 p2, P3 p3) { + typedef R V8_CDECL FType(P1, P2, P3); + csig_->VerifyParams<P1, P2, P3>(); + return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3); + } + + template <typename P1, typename P2, typename P3, typename P4> + R Call(P1 p1, P2 p2, P3 p3, P4 p4) { + typedef R V8_CDECL FType(P1, P2, P3, P4); + csig_->VerifyParams<P1, P2, P3, P4>(); + return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4); } + + protected: + CSignature* csig_; + virtual byte* Generate() = 0; private: @@ -193,39 +174,38 @@ class CallHelper { return static_cast<uintptr_t>(simulator->CallInt64(f, args)); } - template <typename R, typename F> + template <typename F> R DoCall(F* f) { Simulator::CallArgument args[] = {Simulator::CallArgument::End()}; - return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args)); + return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f), args)); } - template <typename R, typename F, typename P1> + template <typename F, typename P1> R DoCall(F* f, P1 p1) { Simulator::CallArgument args[] = {Simulator::CallArgument(p1), Simulator::CallArgument::End()}; - return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args)); + return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f), args)); } - template <typename R, typename F, typename P1, typename P2> + template <typename F, typename P1, typename P2> R DoCall(F* f, P1 p1, P2 p2) { Simulator::CallArgument args[] = {Simulator::CallArgument(p1), Simulator::CallArgument(p2), Simulator::CallArgument::End()}; - return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args)); + return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f), args)); } - template <typename R, typename F, typename P1, typename P2, typename P3> + template <typename F, typename P1, typename P2, typename P3> R DoCall(F* f, P1 p1, P2 p2, P3 p3) { Simulator::CallArgument args[] = { Simulator::CallArgument(p1), Simulator::CallArgument(p2), Simulator::CallArgument(p3), Simulator::CallArgument::End()}; - return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args)); + return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f), args)); } - template <typename R, typename F, typename P1, typename P2, typename P3, - typename P4> + template <typename F, typename P1, typename P2, typename P3, typename P4> R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) { Simulator::CallArgument args[] = { Simulator::CallArgument(p1), Simulator::CallArgument(p2), Simulator::CallArgument(p3), Simulator::CallArgument(p4), Simulator::CallArgument::End()}; - return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args)); + return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f), args)); } #elif USE_SIMULATOR && (V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64) uintptr_t CallSimulator(byte* f, int64_t p1 = 0, int64_t p2 = 0, @@ -235,31 +215,30 @@ class CallHelper { } - template <typename R, typename F> + template <typename F> R DoCall(F* f) { - return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f))); + return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f))); } - template <typename R, typename F, typename P1> + template <typename F, typename P1> R DoCall(F* f, P1 p1) { - return ReturnValueTraits<R>::Cast( + return CastReturnValue<R>( CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1))); } - template <typename R, typename F, typename P1, typename P2> + template <typename F, typename P1, typename P2> R DoCall(F* f, P1 p1, P2 p2) { - return ReturnValueTraits<R>::Cast( - CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1), - ParameterTraits<P2>::Cast(p2))); + return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f), + ParameterTraits<P1>::Cast(p1), + ParameterTraits<P2>::Cast(p2))); } - template <typename R, typename F, typename P1, typename P2, typename P3> + template <typename F, typename P1, typename P2, typename P3> R DoCall(F* f, P1 p1, P2 p2, P3 p3) { - return ReturnValueTraits<R>::Cast(CallSimulator( + return CastReturnValue<R>(CallSimulator( FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1), ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3))); } - template <typename R, typename F, typename P1, typename P2, typename P3, - typename P4> + template <typename F, typename P1, typename P2, typename P3, typename P4> R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) { - return ReturnValueTraits<R>::Cast(CallSimulator( + return CastReturnValue<R>(CallSimulator( FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1), ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3), ParameterTraits<P4>::Cast(p4))); @@ -271,179 +250,60 @@ class CallHelper { Simulator* simulator = Simulator::current(isolate_); return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4)); } - template <typename R, typename F> + template <typename F> R DoCall(F* f) { - return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f))); + return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f))); } - template <typename R, typename F, typename P1> + template <typename F, typename P1> R DoCall(F* f, P1 p1) { - return ReturnValueTraits<R>::Cast( + return CastReturnValue<R>( CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1))); } - template <typename R, typename F, typename P1, typename P2> + template <typename F, typename P1, typename P2> R DoCall(F* f, P1 p1, P2 p2) { - return ReturnValueTraits<R>::Cast( - CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1), - ParameterTraits<P2>::Cast(p2))); + return CastReturnValue<R>(CallSimulator(FUNCTION_ADDR(f), + ParameterTraits<P1>::Cast(p1), + ParameterTraits<P2>::Cast(p2))); } - template <typename R, typename F, typename P1, typename P2, typename P3> + template <typename F, typename P1, typename P2, typename P3> R DoCall(F* f, P1 p1, P2 p2, P3 p3) { - return ReturnValueTraits<R>::Cast(CallSimulator( + return CastReturnValue<R>(CallSimulator( FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1), ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3))); } - template <typename R, typename F, typename P1, typename P2, typename P3, - typename P4> + template <typename F, typename P1, typename P2, typename P3, typename P4> R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) { - return ReturnValueTraits<R>::Cast(CallSimulator( + return CastReturnValue<R>(CallSimulator( FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1), ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3), ParameterTraits<P4>::Cast(p4))); } #else - template <typename R, typename F> + template <typename F> R DoCall(F* f) { return f(); } - template <typename R, typename F, typename P1> + template <typename F, typename P1> R DoCall(F* f, P1 p1) { return f(p1); } - template <typename R, typename F, typename P1, typename P2> + template <typename F, typename P1, typename P2> R DoCall(F* f, P1 p1, P2 p2) { return f(p1, p2); } - template <typename R, typename F, typename P1, typename P2, typename P3> + template <typename F, typename P1, typename P2, typename P3> R DoCall(F* f, P1 p1, P2 p2, P3 p3) { return f(p1, p2, p3); } - template <typename R, typename F, typename P1, typename P2, typename P3, - typename P4> + template <typename F, typename P1, typename P2, typename P3, typename P4> R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) { return f(p1, p2, p3, p4); } #endif -#ifndef DEBUG - void VerifyParameters0() {} - - template <typename P1> - void VerifyParameters1() {} - - template <typename P1, typename P2> - void VerifyParameters2() {} - - template <typename P1, typename P2, typename P3> - void VerifyParameters3() {} - - template <typename P1, typename P2, typename P3, typename P4> - void VerifyParameters4() {} -#else - void VerifyParameters0() { VerifyParameters(0, NULL); } - - template <typename P1> - void VerifyParameters1() { - MachineType parameters[] = {ReturnValueTraits<P1>::Representation()}; - VerifyParameters(arraysize(parameters), parameters); - } - - template <typename P1, typename P2> - void VerifyParameters2() { - MachineType parameters[] = {ReturnValueTraits<P1>::Representation(), - ReturnValueTraits<P2>::Representation()}; - VerifyParameters(arraysize(parameters), parameters); - } - - template <typename P1, typename P2, typename P3> - void VerifyParameters3() { - MachineType parameters[] = {ReturnValueTraits<P1>::Representation(), - ReturnValueTraits<P2>::Representation(), - ReturnValueTraits<P3>::Representation()}; - VerifyParameters(arraysize(parameters), parameters); - } - - template <typename P1, typename P2, typename P3, typename P4> - void VerifyParameters4() { - MachineType parameters[] = {ReturnValueTraits<P1>::Representation(), - ReturnValueTraits<P2>::Representation(), - ReturnValueTraits<P3>::Representation(), - ReturnValueTraits<P4>::Representation()}; - VerifyParameters(arraysize(parameters), parameters); - } -#endif - - // TODO(dcarney): replace Call() in CallHelper2 with these. - template <typename R> - R Call0() { - typedef R V8_CDECL FType(); - VerifyParameters0(); - return DoCall<R>(FUNCTION_CAST<FType*>(Generate())); - } - - template <typename R, typename P1> - R Call1(P1 p1) { - typedef R V8_CDECL FType(P1); - VerifyParameters1<P1>(); - return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1); - } - - template <typename R, typename P1, typename P2> - R Call2(P1 p1, P2 p2) { - typedef R V8_CDECL FType(P1, P2); - VerifyParameters2<P1, P2>(); - return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2); - } - - template <typename R, typename P1, typename P2, typename P3> - R Call3(P1 p1, P2 p2, P3 p3) { - typedef R V8_CDECL FType(P1, P2, P3); - VerifyParameters3<P1, P2, P3>(); - return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3); - } - - template <typename R, typename P1, typename P2, typename P3, typename P4> - R Call4(P1 p1, P2 p2, P3 p3, P4 p4) { - typedef R V8_CDECL FType(P1, P2, P3, P4); - VerifyParameters4<P1, P2, P3, P4>(); - return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4); - } - - template <typename R, typename C> - friend class CallHelper2; Isolate* isolate_; }; - -// TODO(dcarney): replace CallHelper with CallHelper2 and rename. -template <typename R, typename C> -class CallHelper2 { - public: - R Call() { return helper()->template Call0<R>(); } - - template <typename P1> - R Call(P1 p1) { - return helper()->template Call1<R>(p1); - } - - template <typename P1, typename P2> - R Call(P1 p1, P2 p2) { - return helper()->template Call2<R>(p1, p2); - } - - template <typename P1, typename P2, typename P3> - R Call(P1 p1, P2 p2, P3 p3) { - return helper()->template Call3<R>(p1, p2, p3); - } - - template <typename P1, typename P2, typename P3, typename P4> - R Call(P1 p1, P2 p2, P3 p3, P4 p4) { - return helper()->template Call4<R>(p1, p2, p3, p4); - } - - private: - CallHelper* helper() { return static_cast<C*>(this); } -}; - } // namespace compiler } // namespace internal } // namespace v8 diff --git a/deps/v8/test/cctest/compiler/codegen-tester.h b/deps/v8/test/cctest/compiler/codegen-tester.h index f2fc48a479..bc6d938ce1 100644 --- a/deps/v8/test/cctest/compiler/codegen-tester.h +++ b/deps/v8/test/cctest/compiler/codegen-tester.h @@ -17,38 +17,26 @@ namespace v8 { namespace internal { namespace compiler { -template <typename MachineAssembler> -class MachineAssemblerTester : public HandleAndZoneScope, - public CallHelper, - public MachineAssembler { +template <typename ReturnType> +class RawMachineAssemblerTester : public HandleAndZoneScope, + public CallHelper<ReturnType>, + public RawMachineAssembler { public: - MachineAssemblerTester(MachineType return_type, MachineType p0, - MachineType p1, MachineType p2, MachineType p3, - MachineType p4, - MachineOperatorBuilder::Flags flags = - MachineOperatorBuilder::Flag::kNoFlags) + RawMachineAssemblerTester(MachineType p0 = kMachNone, + MachineType p1 = kMachNone, + MachineType p2 = kMachNone, + MachineType p3 = kMachNone, + MachineType p4 = kMachNone) : HandleAndZoneScope(), - CallHelper( + CallHelper<ReturnType>( main_isolate(), - MakeMachineSignature(main_zone(), return_type, p0, p1, p2, p3, p4)), - MachineAssembler( + CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0, p1, + p2, p3, p4)), + RawMachineAssembler( main_isolate(), new (main_zone()) Graph(main_zone()), - MakeMachineSignature(main_zone(), return_type, p0, p1, p2, p3, p4), - kMachPtr, flags) {} - - Node* LoadFromPointer(void* address, MachineType rep, int32_t offset = 0) { - return this->Load(rep, this->PointerConstant(address), - this->Int32Constant(offset)); - } - - void StoreToPointer(void* address, MachineType rep, Node* node) { - this->Store(rep, this->PointerConstant(address), node); - } - - Node* StringConstant(const char* string) { - return this->HeapConstant( - this->isolate()->factory()->InternalizeUtf8String(string)); - } + CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0, p1, + p2, p3, p4), + kMachPtr, InstructionSelector::SupportedMachineOperatorFlags()) {} void CheckNumber(double expected, Object* number) { CHECK(this->isolate()->factory()->NewNumber(expected)->SameValue(number)); @@ -79,41 +67,6 @@ class MachineAssemblerTester : public HandleAndZoneScope, }; -template <typename ReturnType> -class RawMachineAssemblerTester - : public MachineAssemblerTester<RawMachineAssembler>, - public CallHelper2<ReturnType, RawMachineAssemblerTester<ReturnType> > { - public: - RawMachineAssemblerTester(MachineType p0 = kMachNone, - MachineType p1 = kMachNone, - MachineType p2 = kMachNone, - MachineType p3 = kMachNone, - MachineType p4 = kMachNone) - : MachineAssemblerTester<RawMachineAssembler>( - ReturnValueTraits<ReturnType>::Representation(), p0, p1, p2, p3, p4, - InstructionSelector::SupportedMachineOperatorFlags()) {} - - template <typename Ci, typename Fn> - void Run(const Ci& ci, const Fn& fn) { - typename Ci::const_iterator i; - for (i = ci.begin(); i != ci.end(); ++i) { - CHECK_EQ(fn(*i), this->Call(*i)); - } - } - - template <typename Ci, typename Cj, typename Fn> - void Run(const Ci& ci, const Cj& cj, const Fn& fn) { - typename Ci::const_iterator i; - typename Cj::const_iterator j; - for (i = ci.begin(); i != ci.end(); ++i) { - for (j = cj.begin(); j != cj.end(); ++j) { - CHECK_EQ(fn(*i, *j), this->Call(*i, *j)); - } - } - } -}; - - static const bool USE_RESULT_BUFFER = true; static const bool USE_RETURN_REGISTER = false; static const int32_t CHECK_VALUE = 0x99BEEDCE; diff --git a/deps/v8/test/cctest/compiler/function-tester.h b/deps/v8/test/cctest/compiler/function-tester.h index 20efd1e304..54c62ab634 100644 --- a/deps/v8/test/cctest/compiler/function-tester.h +++ b/deps/v8/test/cctest/compiler/function-tester.h @@ -34,15 +34,16 @@ class FunctionTester : public InitializedHandleScope { flags_(flags) { Compile(function); const uint32_t supported_flags = CompilationInfo::kContextSpecializing | - CompilationInfo::kBuiltinInliningEnabled | CompilationInfo::kInliningEnabled | CompilationInfo::kTypingEnabled; CHECK_EQ(0u, flags_ & ~supported_flags); } + // TODO(turbofan): generalize FunctionTester to work with N arguments. Now, it + // can handle up to four. explicit FunctionTester(Graph* graph) : isolate(main_isolate()), - function(NewFunction("(function(a,b){})")), + function(NewFunction("(function(a,b,c,d){})")), flags_(0) { CompileGraph(graph); } @@ -55,8 +56,14 @@ class FunctionTester : public InitializedHandleScope { return Execution::Call(isolate, function, undefined(), 2, args, false); } + MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, Handle<Object> c, + Handle<Object> d) { + Handle<Object> args[] = {a, b, c, d}; + return Execution::Call(isolate, function, undefined(), 4, args, false); + } + void CheckThrows(Handle<Object> a, Handle<Object> b) { - TryCatch try_catch; + TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); MaybeHandle<Object> no_result = Call(a, b); CHECK(isolate->has_pending_exception()); CHECK(try_catch.HasCaught()); @@ -66,7 +73,7 @@ class FunctionTester : public InitializedHandleScope { v8::Handle<v8::Message> CheckThrowsReturnMessage(Handle<Object> a, Handle<Object> b) { - TryCatch try_catch; + TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); MaybeHandle<Object> no_result = Call(a, b); CHECK(isolate->has_pending_exception()); CHECK(try_catch.HasCaught()); @@ -153,6 +160,7 @@ class FunctionTester : public InitializedHandleScope { Zone zone; ParseInfo parse_info(&zone, function); CompilationInfo info(&parse_info); + info.MarkAsDeoptimizationEnabled(); CHECK(Parser::ParseStatic(info.parse_info())); info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code())); @@ -170,11 +178,8 @@ class FunctionTester : public InitializedHandleScope { Pipeline pipeline(&info); Handle<Code> code = pipeline.GenerateCode(); - if (FLAG_turbo_deoptimization) { - info.context()->native_context()->AddOptimizedCode(*code); - } - CHECK(!code.is_null()); + info.context()->native_context()->AddOptimizedCode(*code); function->ReplaceCode(*code); #elif USE_CRANKSHAFT Handle<Code> unoptimized = Handle<Code>(function->code()); diff --git a/deps/v8/test/cctest/compiler/graph-builder-tester.h b/deps/v8/test/cctest/compiler/graph-builder-tester.h index 9a5174c1d7..7270293e0f 100644 --- a/deps/v8/test/cctest/compiler/graph-builder-tester.h +++ b/deps/v8/test/cctest/compiler/graph-builder-tester.h @@ -39,12 +39,10 @@ class GraphAndBuilders { template <typename ReturnType> -class GraphBuilderTester - : public HandleAndZoneScope, - private GraphAndBuilders, - public CallHelper, - public SimplifiedGraphBuilder, - public CallHelper2<ReturnType, GraphBuilderTester<ReturnType> > { +class GraphBuilderTester : public HandleAndZoneScope, + private GraphAndBuilders, + public CallHelper<ReturnType>, + public SimplifiedGraphBuilder { public: explicit GraphBuilderTester(MachineType p0 = kMachNone, MachineType p1 = kMachNone, @@ -52,11 +50,10 @@ class GraphBuilderTester MachineType p3 = kMachNone, MachineType p4 = kMachNone) : GraphAndBuilders(main_zone()), - CallHelper( + CallHelper<ReturnType>( main_isolate(), - MakeMachineSignature( - main_zone(), ReturnValueTraits<ReturnType>::Representation(), - p0, p1, p2, p3, p4)), + CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0, p1, + p2, p3, p4)), SimplifiedGraphBuilder(main_isolate(), main_graph_, &main_common_, &main_machine_, &main_simplified_), parameters_(main_zone()->template NewArray<Node*>(parameter_count())) { @@ -79,7 +76,7 @@ class GraphBuilderTester if (code_.is_null()) { Zone* zone = graph()->zone(); CallDescriptor* desc = - Linkage::GetSimplifiedCDescriptor(zone, machine_sig_); + Linkage::GetSimplifiedCDescriptor(zone, this->csig_); code_ = Pipeline::GenerateCodeForTesting(main_isolate(), desc, graph()); } return code_.ToHandleChecked()->entry(); @@ -92,7 +89,7 @@ class GraphBuilderTester } } - size_t parameter_count() const { return machine_sig_->parameter_count(); } + size_t parameter_count() const { return this->csig_->parameter_count(); } private: Node** parameters_; diff --git a/deps/v8/test/cctest/compiler/simplified-graph-builder.cc b/deps/v8/test/cctest/compiler/simplified-graph-builder.cc index 6afdc0a211..4d57719eff 100644 --- a/deps/v8/test/cctest/compiler/simplified-graph-builder.cc +++ b/deps/v8/test/cctest/compiler/simplified-graph-builder.cc @@ -23,7 +23,7 @@ SimplifiedGraphBuilder::SimplifiedGraphBuilder( void SimplifiedGraphBuilder::Begin(int num_parameters) { DCHECK(graph()->start() == NULL); - Node* start = graph()->NewNode(common()->Start(num_parameters)); + Node* start = graph()->NewNode(common()->Start(num_parameters + 3)); graph()->SetStart(start); effect_ = start; } @@ -37,7 +37,7 @@ void SimplifiedGraphBuilder::Return(Node* value) { void SimplifiedGraphBuilder::End() { - Node* end = graph()->NewNode(common()->End(), return_); + Node* end = graph()->NewNode(common()->End(1), return_); graph()->SetEnd(end); } diff --git a/deps/v8/test/cctest/compiler/simplified-graph-builder.h b/deps/v8/test/cctest/compiler/simplified-graph-builder.h index c9ba002c25..50c51d5ed8 100644 --- a/deps/v8/test/cctest/compiler/simplified-graph-builder.h +++ b/deps/v8/test/cctest/compiler/simplified-graph-builder.h @@ -92,9 +92,6 @@ class SimplifiedGraphBuilder : public GraphBuilder { Node* StringLessThanOrEqual(Node* a, Node* b) { return NewNode(simplified()->StringLessThanOrEqual(), a, b); } - Node* StringAdd(Node* a, Node* b) { - return NewNode(simplified()->StringAdd(), a, b); - } Node* ChangeTaggedToInt32(Node* a) { return NewNode(simplified()->ChangeTaggedToInt32(), a); diff --git a/deps/v8/test/cctest/compiler/test-changes-lowering.cc b/deps/v8/test/cctest/compiler/test-changes-lowering.cc index d11210bb8b..04b5b9176b 100644 --- a/deps/v8/test/cctest/compiler/test-changes-lowering.cc +++ b/deps/v8/test/cctest/compiler/test-changes-lowering.cc @@ -88,7 +88,7 @@ class ChangesLoweringTester : public GraphBuilderTester<ReturnType> { Node* change = this->graph()->NewNode(op, p0); Node* ret = this->graph()->NewNode(this->common()->Return(), change, this->start(), this->start()); - Node* end = this->graph()->NewNode(this->common()->End(), ret); + Node* end = this->graph()->NewNode(this->common()->End(1), ret); this->graph()->SetEnd(end); LowerChange(change); } @@ -104,7 +104,7 @@ class ChangesLoweringTester : public GraphBuilderTester<ReturnType> { change, this->start(), this->start()); Node* ret = this->graph()->NewNode( this->common()->Return(), this->Int32Constant(0), store, this->start()); - Node* end = this->graph()->NewNode(this->common()->End(), ret); + Node* end = this->graph()->NewNode(this->common()->End(1), ret); this->graph()->SetEnd(end); LowerChange(change); } @@ -119,18 +119,18 @@ class ChangesLoweringTester : public GraphBuilderTester<ReturnType> { Node* change = this->graph()->NewNode(op, load); Node* ret = this->graph()->NewNode(this->common()->Return(), change, this->start(), this->start()); - Node* end = this->graph()->NewNode(this->common()->End(), ret); + Node* end = this->graph()->NewNode(this->common()->End(1), ret); this->graph()->SetEnd(end); LowerChange(change); } void LowerChange(Node* change) { // Run the graph reducer with changes lowering on a single node. - Typer typer(this->isolate(), this->graph(), Handle<Context>()); + Typer typer(this->isolate(), this->graph()); typer.Run(); ChangeLowering change_lowering(&jsgraph); SelectLowering select_lowering(this->graph(), this->common()); - GraphReducer reducer(this->graph(), this->zone()); + GraphReducer reducer(this->zone(), this->graph()); reducer.AddReducer(&change_lowering); reducer.AddReducer(&select_lowering); reducer.ReduceNode(change); diff --git a/deps/v8/test/cctest/compiler/test-codegen-deopt.cc b/deps/v8/test/cctest/compiler/test-codegen-deopt.cc deleted file mode 100644 index 0b59308216..0000000000 --- a/deps/v8/test/cctest/compiler/test-codegen-deopt.cc +++ /dev/null @@ -1,301 +0,0 @@ -// Copyright 2014 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "src/v8.h" -#include "test/cctest/cctest.h" - -#include "src/compiler/code-generator.h" -#include "src/compiler/common-operator.h" -#include "src/compiler/graph.h" -#include "src/compiler/instruction-selector.h" -#include "src/compiler/machine-operator.h" -#include "src/compiler/node.h" -#include "src/compiler/operator.h" -#include "src/compiler/raw-machine-assembler.h" -#include "src/compiler/register-allocator.h" -#include "src/compiler/schedule.h" - -#include "src/ast-numbering.h" -#include "src/full-codegen.h" -#include "src/parser.h" -#include "src/rewriter.h" - -#include "test/cctest/compiler/c-signature.h" -#include "test/cctest/compiler/function-tester.h" - -using namespace v8::internal; -using namespace v8::internal::compiler; - - -#if V8_TURBOFAN_TARGET - -typedef RawMachineAssembler::Label MLabel; -typedef v8::internal::compiler::InstructionSequence TestInstrSeq; - -static Handle<JSFunction> NewFunction(const char* source) { - return v8::Utils::OpenHandle( - *v8::Handle<v8::Function>::Cast(CompileRun(source))); -} - - -class DeoptCodegenTester { - public: - explicit DeoptCodegenTester(HandleAndZoneScope* scope, const char* src) - : scope_(scope), - function(NewFunction(src)), - parse_info(scope->main_zone(), function), - info(&parse_info), - bailout_id(-1), - tagged_type(1, kMachAnyTagged, zone()), - empty_types(zone()) { - CHECK(Parser::ParseStatic(&parse_info)); - info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code())); - CHECK(Compiler::Analyze(&parse_info)); - CHECK(Compiler::EnsureDeoptimizationSupport(&info)); - - DCHECK(info.shared_info()->has_deoptimization_support()); - - graph = new (scope_->main_zone()) Graph(scope_->main_zone()); - } - - virtual ~DeoptCodegenTester() {} - - void GenerateCodeFromSchedule(Schedule* schedule) { - OFStream os(stdout); - if (FLAG_trace_turbo) { - os << *schedule; - } - result_code = Pipeline::GenerateCodeForTesting(&info, graph, schedule); -#ifdef OBJECT_PRINT - if (FLAG_print_opt_code || FLAG_trace_turbo) { - result_code->Print(); - } -#endif - } - - Zone* zone() { return scope_->main_zone(); } - Isolate* isolate() { return scope_->main_isolate(); } - - HandleAndZoneScope* scope_; - Handle<JSFunction> function; - ParseInfo parse_info; - CompilationInfo info; - BailoutId bailout_id; - Handle<Code> result_code; - TestInstrSeq* code; - Graph* graph; - ZoneVector<MachineType> tagged_type; - ZoneVector<MachineType> empty_types; -}; - - -class TrivialDeoptCodegenTester : public DeoptCodegenTester { - public: - explicit TrivialDeoptCodegenTester(HandleAndZoneScope* scope) - : DeoptCodegenTester(scope, - "function foo() { deopt(); return 42; }; foo") {} - - void GenerateCode() { - GenerateCodeFromSchedule(BuildGraphAndSchedule(graph)); - } - - Schedule* BuildGraphAndSchedule(Graph* graph) { - CommonOperatorBuilder common(zone()); - - // Manually construct a schedule for the function below: - // function foo() { - // deopt(); - // } - - CSignature1<Object*, Object*> sig; - RawMachineAssembler m(isolate(), graph, &sig); - - Handle<JSFunction> deopt_function = - NewFunction("function deopt() { %DeoptimizeFunction(foo); }; deopt"); - Unique<JSFunction> deopt_fun_constant = - Unique<JSFunction>::CreateUninitialized(deopt_function); - Node* deopt_fun_node = m.NewNode(common.HeapConstant(deopt_fun_constant)); - - Handle<Context> caller_context(function->context(), CcTest::i_isolate()); - Unique<Context> caller_context_constant = - Unique<Context>::CreateUninitialized(caller_context); - Node* caller_context_node = - m.NewNode(common.HeapConstant(caller_context_constant)); - - bailout_id = GetCallBailoutId(); - Node* parameters = - m.NewNode(common.TypedStateValues(&tagged_type), m.UndefinedConstant()); - Node* locals = m.NewNode(common.TypedStateValues(&empty_types)); - Node* stack = m.NewNode(common.TypedStateValues(&empty_types)); - - Node* state_node = m.NewNode( - common.FrameState(JS_FRAME, bailout_id, - OutputFrameStateCombine::Ignore()), - parameters, locals, stack, caller_context_node, m.UndefinedConstant()); - - Handle<Context> context(deopt_function->context(), CcTest::i_isolate()); - Unique<Context> context_constant = - Unique<Context>::CreateUninitialized(context); - Node* context_node = m.NewNode(common.HeapConstant(context_constant)); - - m.CallJS0(deopt_fun_node, m.UndefinedConstant(), context_node, state_node); - - m.Return(m.UndefinedConstant()); - - // Schedule the graph: - Schedule* schedule = m.Export(); - - return schedule; - } - - BailoutId GetCallBailoutId() { - ZoneList<Statement*>* body = info.function()->body(); - for (int i = 0; i < body->length(); i++) { - if (body->at(i)->IsExpressionStatement() && - body->at(i)->AsExpressionStatement()->expression()->IsCall()) { - return body->at(i)->AsExpressionStatement()->expression()->id(); - } - } - CHECK(false); - return BailoutId(-1); - } -}; - - -TEST(TurboTrivialDeoptCodegen) { - HandleAndZoneScope scope; - InitializedHandleScope handles; - - FLAG_allow_natives_syntax = true; - FLAG_turbo_deoptimization = true; - - TrivialDeoptCodegenTester t(&scope); - t.GenerateCode(); - - DeoptimizationInputData* data = - DeoptimizationInputData::cast(t.result_code->deoptimization_data()); - - // TODO(jarin) Find a way to test the safepoint. - - // Check that we deoptimize to the right AST id. - CHECK_EQ(1, data->DeoptCount()); - CHECK_EQ(t.bailout_id.ToInt(), data->AstId(0).ToInt()); -} - - -TEST(TurboTrivialDeoptCodegenAndRun) { - HandleAndZoneScope scope; - InitializedHandleScope handles; - - FLAG_allow_natives_syntax = true; - FLAG_turbo_deoptimization = true; - - TrivialDeoptCodegenTester t(&scope); - t.GenerateCode(); - - t.function->ReplaceCode(*t.result_code); - t.info.context()->native_context()->AddOptimizedCode(*t.result_code); - - Isolate* isolate = scope.main_isolate(); - Handle<Object> result; - bool has_pending_exception = - !Execution::Call(isolate, t.function, - isolate->factory()->undefined_value(), 0, NULL, - false).ToHandle(&result); - CHECK(!has_pending_exception); - CHECK(result->SameValue(Smi::FromInt(42))); -} - - -class TrivialRuntimeDeoptCodegenTester : public DeoptCodegenTester { - public: - explicit TrivialRuntimeDeoptCodegenTester(HandleAndZoneScope* scope) - : DeoptCodegenTester( - scope, - "function foo() { %DeoptimizeFunction(foo); return 42; }; foo") {} - - void GenerateCode() { - GenerateCodeFromSchedule(BuildGraphAndSchedule(graph)); - } - - Schedule* BuildGraphAndSchedule(Graph* graph) { - CommonOperatorBuilder common(zone()); - - // Manually construct a schedule for the function below: - // function foo() { - // %DeoptimizeFunction(foo); - // } - - CSignature1<Object*, Object*> sig; - RawMachineAssembler m(isolate(), graph, &sig); - - Unique<HeapObject> this_fun_constant = - Unique<HeapObject>::CreateUninitialized(function); - Node* this_fun_node = m.NewNode(common.HeapConstant(this_fun_constant)); - - Handle<Context> context(function->context(), CcTest::i_isolate()); - Unique<HeapObject> context_constant = - Unique<HeapObject>::CreateUninitialized(context); - Node* context_node = m.NewNode(common.HeapConstant(context_constant)); - - bailout_id = GetCallBailoutId(); - Node* parameters = - m.NewNode(common.TypedStateValues(&tagged_type), m.UndefinedConstant()); - Node* locals = m.NewNode(common.TypedStateValues(&empty_types)); - Node* stack = m.NewNode(common.TypedStateValues(&empty_types)); - - Node* state_node = m.NewNode( - common.FrameState(JS_FRAME, bailout_id, - OutputFrameStateCombine::Ignore()), - parameters, locals, stack, context_node, m.UndefinedConstant()); - - m.CallRuntime1(Runtime::kDeoptimizeFunction, this_fun_node, context_node, - state_node); - - m.Return(m.UndefinedConstant()); - - // Schedule the graph: - Schedule* schedule = m.Export(); - - return schedule; - } - - BailoutId GetCallBailoutId() { - ZoneList<Statement*>* body = info.function()->body(); - for (int i = 0; i < body->length(); i++) { - if (body->at(i)->IsExpressionStatement() && - body->at(i)->AsExpressionStatement()->expression()->IsCallRuntime()) { - return body->at(i)->AsExpressionStatement()->expression()->id(); - } - } - CHECK(false); - return BailoutId(-1); - } -}; - - -TEST(TurboTrivialRuntimeDeoptCodegenAndRun) { - HandleAndZoneScope scope; - InitializedHandleScope handles; - - FLAG_allow_natives_syntax = true; - FLAG_turbo_deoptimization = true; - - TrivialRuntimeDeoptCodegenTester t(&scope); - t.GenerateCode(); - - t.function->ReplaceCode(*t.result_code); - t.info.context()->native_context()->AddOptimizedCode(*t.result_code); - - Isolate* isolate = scope.main_isolate(); - Handle<Object> result; - bool has_pending_exception = - !Execution::Call(isolate, t.function, - isolate->factory()->undefined_value(), 0, NULL, - false).ToHandle(&result); - CHECK(!has_pending_exception); - CHECK(result->SameValue(Smi::FromInt(42))); -} - -#endif diff --git a/deps/v8/test/cctest/compiler/test-control-reducer.cc b/deps/v8/test/cctest/compiler/test-control-reducer.cc deleted file mode 100644 index e969e27106..0000000000 --- a/deps/v8/test/cctest/compiler/test-control-reducer.cc +++ /dev/null @@ -1,1641 +0,0 @@ -// Copyright 2014 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "src/v8.h" -#include "test/cctest/cctest.h" - -#include "src/base/bits.h" -#include "src/compiler/all-nodes.h" -#include "src/compiler/common-operator.h" -#include "src/compiler/control-reducer.h" -#include "src/compiler/graph.h" -#include "src/compiler/js-graph.h" -#include "src/compiler/node-properties.h" - -using namespace v8::internal; -using namespace v8::internal::compiler; - -static const size_t kNumLeafs = 4; - -enum Decision { kFalse, kUnknown, kTrue }; - -// TODO(titzer): convert this whole file into unit tests. - -static int CheckInputs(Node* node, Node* i0 = NULL, Node* i1 = NULL, - Node* i2 = NULL) { - int count = 3; - if (i2 == NULL) count = 2; - if (i1 == NULL) count = 1; - if (i0 == NULL) count = 0; - CHECK_EQ(count, node->InputCount()); - if (i0 != NULL) CHECK_EQ(i0, node->InputAt(0)); - if (i1 != NULL) CHECK_EQ(i1, node->InputAt(1)); - if (i2 != NULL) CHECK_EQ(i2, node->InputAt(2)); - return count; -} - - -static int CheckMerge(Node* node, Node* i0 = NULL, Node* i1 = NULL, - Node* i2 = NULL) { - CHECK_EQ(IrOpcode::kMerge, node->opcode()); - int count = CheckInputs(node, i0, i1, i2); - CHECK_EQ(count, node->op()->ControlInputCount()); - return count; -} - - -static int CheckLoop(Node* node, Node* i0 = NULL, Node* i1 = NULL, - Node* i2 = NULL) { - CHECK_EQ(IrOpcode::kLoop, node->opcode()); - int count = CheckInputs(node, i0, i1, i2); - CHECK_EQ(count, node->op()->ControlInputCount()); - return count; -} - - -bool IsUsedBy(Node* a, Node* b) { - auto const uses = a->uses(); - return std::find(uses.begin(), uses.end(), b) != uses.end(); -} - - -// A helper for all tests dealing with ControlTester. -class ControlReducerTester : HandleAndZoneScope { - public: - ControlReducerTester() - : isolate(main_isolate()), - common(main_zone()), - graph(main_zone()), - jsgraph(main_isolate(), &graph, &common, NULL, NULL), - start(graph.NewNode(common.Start(1))), - end(graph.NewNode(common.End(), start)), - p0(graph.NewNode(common.Parameter(0), start)), - zero(jsgraph.Int32Constant(0)), - one(jsgraph.OneConstant()), - half(jsgraph.Constant(0.5)), - self(graph.NewNode(common.Int32Constant(0xaabbccdd))), - dead(graph.NewNode(common.Dead())) { - graph.SetEnd(end); - graph.SetStart(start); - leaf[0] = zero; - leaf[1] = one; - leaf[2] = half; - leaf[3] = p0; - } - - Isolate* isolate; - CommonOperatorBuilder common; - Graph graph; - JSGraph jsgraph; - Node* start; - Node* end; - Node* p0; - Node* zero; - Node* one; - Node* half; - Node* self; - Node* dead; - Node* leaf[kNumLeafs]; - - Node* Phi(Node* a) { - return SetSelfReferences(graph.NewNode(op(1, false), a, start)); - } - - Node* Phi(Node* a, Node* b) { - return SetSelfReferences(graph.NewNode(op(2, false), a, b, start)); - } - - Node* Phi(Node* a, Node* b, Node* c) { - return SetSelfReferences(graph.NewNode(op(3, false), a, b, c, start)); - } - - Node* Phi(Node* a, Node* b, Node* c, Node* d) { - return SetSelfReferences(graph.NewNode(op(4, false), a, b, c, d, start)); - } - - Node* EffectPhi(Node* a) { - return SetSelfReferences(graph.NewNode(op(1, true), a, start)); - } - - Node* EffectPhi(Node* a, Node* b) { - return SetSelfReferences(graph.NewNode(op(2, true), a, b, start)); - } - - Node* EffectPhi(Node* a, Node* b, Node* c) { - return SetSelfReferences(graph.NewNode(op(3, true), a, b, c, start)); - } - - Node* EffectPhi(Node* a, Node* b, Node* c, Node* d) { - return SetSelfReferences(graph.NewNode(op(4, true), a, b, c, d, start)); - } - - Node* SetSelfReferences(Node* node) { - for (Edge edge : node->input_edges()) { - if (edge.to() == self) node->ReplaceInput(edge.index(), node); - } - return node; - } - - const Operator* op(int count, bool effect) { - return effect ? common.EffectPhi(count) : common.Phi(kMachAnyTagged, count); - } - - void Trim() { ControlReducer::TrimGraph(main_zone(), &jsgraph); } - - void ReduceGraph() { ControlReducer::ReduceGraph(main_zone(), &jsgraph); } - - // Checks one-step reduction of a phi. - void ReducePhi(Node* expect, Node* phi) { - Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, phi); - CHECK_EQ(expect, result); - ReducePhiIterative(expect, phi); // iterative should give the same result. - } - - // Checks one-step reduction of a phi. - void ReducePhiNonIterative(Node* expect, Node* phi) { - Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, phi); - CHECK_EQ(expect, result); - } - - void ReducePhiIterative(Node* expect, Node* phi) { - p0->ReplaceInput(0, start); // hack: parameters may be trimmed. - Node* ret = graph.NewNode(common.Return(), phi, start, start); - Node* end = graph.NewNode(common.End(), ret); - graph.SetEnd(end); - ControlReducer::ReduceGraph(main_zone(), &jsgraph); - CheckInputs(end, ret); - CheckInputs(ret, expect, start, start); - } - - void ReduceMerge(Node* expect, Node* merge) { - Node* result = ControlReducer::ReduceMerge(&jsgraph, merge); - CHECK_EQ(expect, result); - } - - void ReduceMergeIterative(Node* expect, Node* merge) { - p0->ReplaceInput(0, start); // hack: parameters may be trimmed. - Node* end = graph.NewNode(common.End(), merge); - graph.SetEnd(end); - ReduceGraph(); - CheckInputs(end, expect); - } - - void ReduceBranch(Decision expected, Node* branch) { - Node* control = branch->InputAt(1); - for (Node* use : branch->uses()) { - if (use->opcode() == IrOpcode::kIfTrue) { - Node* result = ControlReducer::ReduceIfNodeForTesting(&jsgraph, use); - if (expected == kTrue) CHECK_EQ(control, result); - if (expected == kFalse) CHECK_EQ(IrOpcode::kDead, result->opcode()); - if (expected == kUnknown) CHECK_EQ(use, result); - } else if (use->opcode() == IrOpcode::kIfFalse) { - Node* result = ControlReducer::ReduceIfNodeForTesting(&jsgraph, use); - if (expected == kFalse) CHECK_EQ(control, result); - if (expected == kTrue) CHECK_EQ(IrOpcode::kDead, result->opcode()); - if (expected == kUnknown) CHECK_EQ(use, result); - } else { - UNREACHABLE(); - } - } - } - - Node* Return(Node* val, Node* effect, Node* control) { - Node* ret = graph.NewNode(common.Return(), val, effect, control); - end->ReplaceInput(0, ret); - return ret; - } -}; - - -struct Branch { - Node* branch; - Node* if_true; - Node* if_false; - - Branch(ControlReducerTester& R, Node* cond, Node* control = NULL) { - if (control == NULL) control = R.start; - branch = R.graph.NewNode(R.common.Branch(), cond, control); - if_true = R.graph.NewNode(R.common.IfTrue(), branch); - if_false = R.graph.NewNode(R.common.IfFalse(), branch); - } -}; - - -// TODO(titzer): use the diamonds from src/compiler/diamond.h here. -struct Diamond { - Node* branch; - Node* if_true; - Node* if_false; - Node* merge; - Node* phi; - - Diamond(ControlReducerTester& R, Node* cond) { - branch = R.graph.NewNode(R.common.Branch(), cond, R.start); - if_true = R.graph.NewNode(R.common.IfTrue(), branch); - if_false = R.graph.NewNode(R.common.IfFalse(), branch); - merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false); - phi = NULL; - } - - Diamond(ControlReducerTester& R, Node* cond, Node* tv, Node* fv) { - branch = R.graph.NewNode(R.common.Branch(), cond, R.start); - if_true = R.graph.NewNode(R.common.IfTrue(), branch); - if_false = R.graph.NewNode(R.common.IfFalse(), branch); - merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false); - phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 2), tv, fv, merge); - } - - void chain(Diamond& that) { branch->ReplaceInput(1, that.merge); } - - // Nest {this} into either the if_true or if_false branch of {that}. - void nest(Diamond& that, bool if_true) { - if (if_true) { - branch->ReplaceInput(1, that.if_true); - that.merge->ReplaceInput(0, merge); - } else { - branch->ReplaceInput(1, that.if_false); - that.merge->ReplaceInput(1, merge); - } - } -}; - - -struct While { - Node* branch; - Node* if_true; - Node* exit; - Node* loop; - - While(ControlReducerTester& R, Node* cond) { - loop = R.graph.NewNode(R.common.Loop(2), R.start, R.start); - branch = R.graph.NewNode(R.common.Branch(), cond, loop); - if_true = R.graph.NewNode(R.common.IfTrue(), branch); - exit = R.graph.NewNode(R.common.IfFalse(), branch); - loop->ReplaceInput(1, if_true); - } - - void chain(Node* control) { loop->ReplaceInput(0, control); } -}; - - -// Helper for checking that nodes are *not* reachable from end. -struct DeadChecker { - Zone zone; - AllNodes nodes; - explicit DeadChecker(Graph* graph) : zone(), nodes(&zone, graph) {} - - void Check(Node* node) { CHECK(!nodes.IsLive(node)); } - - void Check(Diamond& d) { - Check(d.branch); - Check(d.if_true); - Check(d.if_false); - Check(d.merge); - if (d.phi != NULL) Check(d.phi); - } - - void CheckLive(Diamond& d, bool live_phi = true) { - CheckInputs(d.merge, d.if_true, d.if_false); - CheckInputs(d.if_true, d.branch); - CheckInputs(d.if_false, d.branch); - if (d.phi != NULL) { - if (live_phi) { - CHECK_EQ(3, d.phi->InputCount()); - CHECK_EQ(d.merge, d.phi->InputAt(2)); - } else { - Check(d.phi); - } - } - } -}; - - -TEST(Trim1_live) { - ControlReducerTester T; - CHECK(IsUsedBy(T.start, T.p0)); - T.graph.SetEnd(T.p0); - T.Trim(); - CHECK(IsUsedBy(T.start, T.p0)); - CheckInputs(T.p0, T.start); -} - - -TEST(Trim1_dead) { - ControlReducerTester T; - CHECK(IsUsedBy(T.start, T.p0)); - T.Trim(); - CHECK(!IsUsedBy(T.start, T.p0)); - CHECK(!T.p0->InputAt(0)); -} - - -TEST(Trim2_live) { - ControlReducerTester T; - Node* phi = - T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start); - CHECK(IsUsedBy(T.one, phi)); - CHECK(IsUsedBy(T.half, phi)); - CHECK(IsUsedBy(T.start, phi)); - T.graph.SetEnd(phi); - T.Trim(); - CHECK(IsUsedBy(T.one, phi)); - CHECK(IsUsedBy(T.half, phi)); - CHECK(IsUsedBy(T.start, phi)); - CheckInputs(phi, T.one, T.half, T.start); -} - - -TEST(Trim2_dead) { - ControlReducerTester T; - Node* phi = - T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, T.start); - CHECK(IsUsedBy(T.one, phi)); - CHECK(IsUsedBy(T.half, phi)); - CHECK(IsUsedBy(T.start, phi)); - T.Trim(); - CHECK(!IsUsedBy(T.one, phi)); - CHECK(!IsUsedBy(T.half, phi)); - CHECK(!IsUsedBy(T.start, phi)); - CHECK(!phi->InputAt(0)); - CHECK(!phi->InputAt(1)); - CHECK(!phi->InputAt(2)); -} - - -TEST(Trim_chain1) { - ControlReducerTester T; - const int kDepth = 15; - Node* live[kDepth]; - Node* dead[kDepth]; - Node* end = T.start; - for (int i = 0; i < kDepth; i++) { - live[i] = end = T.graph.NewNode(T.common.Merge(1), end); - dead[i] = T.graph.NewNode(T.common.Merge(1), end); - } - // end -> live[last] -> live[last-1] -> ... -> start - // dead[last] ^ dead[last-1] ^ ... ^ - T.graph.SetEnd(end); - T.Trim(); - for (int i = 0; i < kDepth; i++) { - CHECK(!IsUsedBy(live[i], dead[i])); - CHECK(!dead[i]->InputAt(0)); - CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0)); - } -} - - -TEST(Trim_chain2) { - ControlReducerTester T; - const int kDepth = 15; - Node* live[kDepth]; - Node* dead[kDepth]; - Node* l = T.start; - Node* d = T.start; - for (int i = 0; i < kDepth; i++) { - live[i] = l = T.graph.NewNode(T.common.Merge(1), l); - dead[i] = d = T.graph.NewNode(T.common.Merge(1), d); - } - // end -> live[last] -> live[last-1] -> ... -> start - // dead[last] -> dead[last-1] -> ... -> start - T.graph.SetEnd(l); - T.Trim(); - CHECK(!IsUsedBy(T.start, dead[0])); - for (int i = 0; i < kDepth; i++) { - CHECK_EQ(i == 0 ? NULL : dead[i - 1], dead[i]->InputAt(0)); - CHECK_EQ(i == 0 ? T.start : live[i - 1], live[i]->InputAt(0)); - } -} - - -TEST(Trim_cycle1) { - ControlReducerTester T; - Node* loop = T.graph.NewNode(T.common.Loop(1), T.start, T.start); - loop->ReplaceInput(1, loop); - Node* end = T.graph.NewNode(T.common.End(), loop); - T.graph.SetEnd(end); - - CHECK(IsUsedBy(T.start, loop)); - CHECK(IsUsedBy(loop, end)); - CHECK(IsUsedBy(loop, loop)); - - T.Trim(); - - // nothing should have happened to the loop itself. - CHECK(IsUsedBy(T.start, loop)); - CHECK(IsUsedBy(loop, end)); - CHECK(IsUsedBy(loop, loop)); - CheckInputs(loop, T.start, loop); - CheckInputs(end, loop); -} - - -TEST(Trim_cycle2) { - ControlReducerTester T; - Node* loop = T.graph.NewNode(T.common.Loop(2), T.start, T.start); - loop->ReplaceInput(1, loop); - Node* end = T.graph.NewNode(T.common.End(), loop); - Node* phi = - T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), T.one, T.half, loop); - T.graph.SetEnd(end); - - CHECK(IsUsedBy(T.start, loop)); - CHECK(IsUsedBy(loop, end)); - CHECK(IsUsedBy(loop, loop)); - CHECK(IsUsedBy(loop, phi)); - CHECK(IsUsedBy(T.one, phi)); - CHECK(IsUsedBy(T.half, phi)); - - T.Trim(); - - // nothing should have happened to the loop itself. - CHECK(IsUsedBy(T.start, loop)); - CHECK(IsUsedBy(loop, end)); - CHECK(IsUsedBy(loop, loop)); - CheckInputs(loop, T.start, loop); - CheckInputs(end, loop); - - // phi should have been trimmed away. - CHECK(!IsUsedBy(loop, phi)); - CHECK(!IsUsedBy(T.one, phi)); - CHECK(!IsUsedBy(T.half, phi)); - CHECK(!phi->InputAt(0)); - CHECK(!phi->InputAt(1)); - CHECK(!phi->InputAt(2)); -} - - -void CheckTrimConstant(ControlReducerTester* T, Node* k) { - Node* phi = T->graph.NewNode(T->common.Phi(kMachInt32, 1), k, T->start); - CHECK(IsUsedBy(k, phi)); - T->Trim(); - CHECK(!IsUsedBy(k, phi)); - CHECK(!phi->InputAt(0)); - CHECK(!phi->InputAt(1)); -} - - -TEST(Trim_constants) { - ControlReducerTester T; - int32_t int32_constants[] = { - 0, -1, -2, 2, 2, 3, 3, 4, 4, 5, 5, 4, 5, 6, 6, 7, 8, 7, 8, 9, - 0, -11, -12, 12, 12, 13, 13, 14, 14, 15, 15, 14, 15, 6, 6, 7, 8, 7, 8, 9}; - - for (size_t i = 0; i < arraysize(int32_constants); i++) { - CheckTrimConstant(&T, T.jsgraph.Int32Constant(int32_constants[i])); - CheckTrimConstant(&T, T.jsgraph.Float64Constant(int32_constants[i])); - CheckTrimConstant(&T, T.jsgraph.Constant(int32_constants[i])); - } - - Node* other_constants[] = { - T.jsgraph.UndefinedConstant(), T.jsgraph.TheHoleConstant(), - T.jsgraph.TrueConstant(), T.jsgraph.FalseConstant(), - T.jsgraph.NullConstant(), T.jsgraph.ZeroConstant(), - T.jsgraph.OneConstant(), T.jsgraph.NaNConstant(), - T.jsgraph.Constant(21), T.jsgraph.Constant(22.2)}; - - for (size_t i = 0; i < arraysize(other_constants); i++) { - CheckTrimConstant(&T, other_constants[i]); - } -} - - -TEST(Trim_EmptyFrameState1) { - ControlReducerTester T; - - Node* node = T.jsgraph.EmptyFrameState(); - T.Trim(); - - for (Node* input : node->inputs()) { - CHECK_NOT_NULL(input); - } -} - - -TEST(Trim_EmptyFrameState2) { - ControlReducerTester T; - CheckTrimConstant(&T, T.jsgraph.EmptyFrameState()); -} - - -TEST(CReducePhi1) { - ControlReducerTester R; - - R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0])); - R.ReducePhi(R.leaf[1], R.Phi(R.leaf[1])); - R.ReducePhi(R.leaf[2], R.Phi(R.leaf[2])); - R.ReducePhi(R.leaf[3], R.Phi(R.leaf[3])); -} - - -TEST(CReducePhi1_dead) { - ControlReducerTester R; - - R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0], R.dead)); - R.ReducePhi(R.leaf[1], R.Phi(R.leaf[1], R.dead)); - R.ReducePhi(R.leaf[2], R.Phi(R.leaf[2], R.dead)); - R.ReducePhi(R.leaf[3], R.Phi(R.leaf[3], R.dead)); - - R.ReducePhi(R.leaf[0], R.Phi(R.dead, R.leaf[0])); - R.ReducePhi(R.leaf[1], R.Phi(R.dead, R.leaf[1])); - R.ReducePhi(R.leaf[2], R.Phi(R.dead, R.leaf[2])); - R.ReducePhi(R.leaf[3], R.Phi(R.dead, R.leaf[3])); -} - - -TEST(CReducePhi1_dead2) { - ControlReducerTester R; - - R.ReducePhi(R.leaf[0], R.Phi(R.leaf[0], R.dead, R.dead)); - R.ReducePhi(R.leaf[0], R.Phi(R.dead, R.leaf[0], R.dead)); - R.ReducePhi(R.leaf[0], R.Phi(R.dead, R.dead, R.leaf[0])); -} - - -TEST(CReducePhi2a) { - ControlReducerTester R; - - for (size_t i = 0; i < kNumLeafs; i++) { - Node* a = R.leaf[i]; - R.ReducePhi(a, R.Phi(a, a)); - } -} - - -TEST(CReducePhi2b) { - ControlReducerTester R; - - for (size_t i = 0; i < kNumLeafs; i++) { - Node* a = R.leaf[i]; - R.ReducePhi(a, R.Phi(R.self, a)); - R.ReducePhi(a, R.Phi(a, R.self)); - } -} - - -TEST(CReducePhi2c) { - ControlReducerTester R; - - for (size_t i = 1; i < kNumLeafs; i++) { - Node* a = R.leaf[i], *b = R.leaf[0]; - Node* phi1 = R.Phi(b, a); - R.ReducePhi(phi1, phi1); - - Node* phi2 = R.Phi(a, b); - R.ReducePhi(phi2, phi2); - } -} - - -TEST(CReducePhi2_dead) { - ControlReducerTester R; - - for (size_t i = 0; i < kNumLeafs; i++) { - Node* a = R.leaf[i]; - R.ReducePhi(a, R.Phi(a, a, R.dead)); - R.ReducePhi(a, R.Phi(a, R.dead, a)); - R.ReducePhi(a, R.Phi(R.dead, a, a)); - } - - for (size_t i = 0; i < kNumLeafs; i++) { - Node* a = R.leaf[i]; - R.ReducePhi(a, R.Phi(R.self, a)); - R.ReducePhi(a, R.Phi(a, R.self)); - R.ReducePhi(a, R.Phi(R.self, a, R.dead)); - R.ReducePhi(a, R.Phi(a, R.self, R.dead)); - } - - for (size_t i = 1; i < kNumLeafs; i++) { - Node* a = R.leaf[i], *b = R.leaf[0]; - Node* phi1 = R.Phi(b, a, R.dead); - R.ReducePhiNonIterative(phi1, phi1); - - Node* phi2 = R.Phi(a, b, R.dead); - R.ReducePhiNonIterative(phi2, phi2); - } -} - - -TEST(CReducePhi3) { - ControlReducerTester R; - - for (size_t i = 0; i < kNumLeafs; i++) { - Node* a = R.leaf[i]; - R.ReducePhi(a, R.Phi(a, a, a)); - } - - for (size_t i = 0; i < kNumLeafs; i++) { - Node* a = R.leaf[i]; - R.ReducePhi(a, R.Phi(R.self, a, a)); - R.ReducePhi(a, R.Phi(a, R.self, a)); - R.ReducePhi(a, R.Phi(a, a, R.self)); - } - - for (size_t i = 1; i < kNumLeafs; i++) { - Node* a = R.leaf[i], *b = R.leaf[0]; - Node* phi1 = R.Phi(b, a, a); - R.ReducePhi(phi1, phi1); - - Node* phi2 = R.Phi(a, b, a); - R.ReducePhi(phi2, phi2); - - Node* phi3 = R.Phi(a, a, b); - R.ReducePhi(phi3, phi3); - } -} - - -TEST(CReducePhi4) { - ControlReducerTester R; - - for (size_t i = 0; i < kNumLeafs; i++) { - Node* a = R.leaf[i]; - R.ReducePhi(a, R.Phi(a, a, a, a)); - } - - for (size_t i = 0; i < kNumLeafs; i++) { - Node* a = R.leaf[i]; - R.ReducePhi(a, R.Phi(R.self, a, a, a)); - R.ReducePhi(a, R.Phi(a, R.self, a, a)); - R.ReducePhi(a, R.Phi(a, a, R.self, a)); - R.ReducePhi(a, R.Phi(a, a, a, R.self)); - - R.ReducePhi(a, R.Phi(R.self, R.self, a, a)); - R.ReducePhi(a, R.Phi(a, R.self, R.self, a)); - R.ReducePhi(a, R.Phi(a, a, R.self, R.self)); - R.ReducePhi(a, R.Phi(R.self, a, a, R.self)); - } - - for (size_t i = 1; i < kNumLeafs; i++) { - Node* a = R.leaf[i], *b = R.leaf[0]; - Node* phi1 = R.Phi(b, a, a, a); - R.ReducePhi(phi1, phi1); - - Node* phi2 = R.Phi(a, b, a, a); - R.ReducePhi(phi2, phi2); - - Node* phi3 = R.Phi(a, a, b, a); - R.ReducePhi(phi3, phi3); - - Node* phi4 = R.Phi(a, a, a, b); - R.ReducePhi(phi4, phi4); - } -} - - -TEST(CReducePhi_iterative1) { - ControlReducerTester R; - - R.ReducePhiIterative(R.leaf[0], R.Phi(R.leaf[0], R.Phi(R.leaf[0]))); - R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0]), R.leaf[0])); -} - - -TEST(CReducePhi_iterative2) { - ControlReducerTester R; - - R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0]), R.Phi(R.leaf[0]))); -} - - -TEST(CReducePhi_iterative3) { - ControlReducerTester R; - - R.ReducePhiIterative(R.leaf[0], - R.Phi(R.leaf[0], R.Phi(R.leaf[0], R.leaf[0]))); - R.ReducePhiIterative(R.leaf[0], - R.Phi(R.Phi(R.leaf[0], R.leaf[0]), R.leaf[0])); -} - - -TEST(CReducePhi_iterative4) { - ControlReducerTester R; - - R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0], R.leaf[0]), - R.Phi(R.leaf[0], R.leaf[0]))); - - Node* p1 = R.Phi(R.leaf[0], R.leaf[0]); - R.ReducePhiIterative(R.leaf[0], R.Phi(p1, p1)); - - Node* p2 = R.Phi(R.leaf[0], R.leaf[0], R.leaf[0]); - R.ReducePhiIterative(R.leaf[0], R.Phi(p2, p2, p2)); - - Node* p3 = R.Phi(R.leaf[0], R.leaf[0], R.leaf[0]); - R.ReducePhiIterative(R.leaf[0], R.Phi(p3, p3, R.leaf[0])); -} - - -TEST(CReducePhi_iterative_self1) { - ControlReducerTester R; - - R.ReducePhiIterative(R.leaf[0], R.Phi(R.leaf[0], R.Phi(R.leaf[0], R.self))); - R.ReducePhiIterative(R.leaf[0], R.Phi(R.Phi(R.leaf[0], R.self), R.leaf[0])); -} - - -TEST(CReducePhi_iterative_self2) { - ControlReducerTester R; - - R.ReducePhiIterative( - R.leaf[0], R.Phi(R.Phi(R.leaf[0], R.self), R.Phi(R.leaf[0], R.self))); - R.ReducePhiIterative( - R.leaf[0], R.Phi(R.Phi(R.self, R.leaf[0]), R.Phi(R.self, R.leaf[0]))); - - Node* p1 = R.Phi(R.leaf[0], R.self); - R.ReducePhiIterative(R.leaf[0], R.Phi(p1, p1)); - - Node* p2 = R.Phi(R.self, R.leaf[0]); - R.ReducePhiIterative(R.leaf[0], R.Phi(p2, p2)); -} - - -TEST(EReducePhi1) { - ControlReducerTester R; - - R.ReducePhi(R.leaf[0], R.EffectPhi(R.leaf[0])); - R.ReducePhi(R.leaf[1], R.EffectPhi(R.leaf[1])); - R.ReducePhi(R.leaf[2], R.EffectPhi(R.leaf[2])); - R.ReducePhi(R.leaf[3], R.EffectPhi(R.leaf[3])); -} - - -TEST(EReducePhi1_dead) { - ControlReducerTester R; - - R.ReducePhi(R.leaf[0], R.EffectPhi(R.leaf[0], R.dead)); - R.ReducePhi(R.leaf[1], R.EffectPhi(R.leaf[1], R.dead)); - R.ReducePhi(R.leaf[2], R.EffectPhi(R.leaf[2], R.dead)); - R.ReducePhi(R.leaf[3], R.EffectPhi(R.leaf[3], R.dead)); - - R.ReducePhi(R.leaf[0], R.EffectPhi(R.dead, R.leaf[0])); - R.ReducePhi(R.leaf[1], R.EffectPhi(R.dead, R.leaf[1])); - R.ReducePhi(R.leaf[2], R.EffectPhi(R.dead, R.leaf[2])); - R.ReducePhi(R.leaf[3], R.EffectPhi(R.dead, R.leaf[3])); -} - - -TEST(EReducePhi1_dead2) { - ControlReducerTester R; - - R.ReducePhi(R.leaf[0], R.EffectPhi(R.leaf[0], R.dead, R.dead)); - R.ReducePhi(R.leaf[0], R.EffectPhi(R.dead, R.leaf[0], R.dead)); - R.ReducePhi(R.leaf[0], R.EffectPhi(R.dead, R.dead, R.leaf[0])); -} - - -TEST(CMergeReduce_simple1) { - ControlReducerTester R; - - Node* merge = R.graph.NewNode(R.common.Merge(1), R.start); - R.ReduceMerge(R.start, merge); -} - - -TEST(CMergeReduce_simple2) { - ControlReducerTester R; - - Node* merge1 = R.graph.NewNode(R.common.Merge(1), R.start); - Node* merge2 = R.graph.NewNode(R.common.Merge(1), merge1); - R.ReduceMerge(merge1, merge2); - R.ReduceMergeIterative(R.start, merge2); -} - - -TEST(CMergeReduce_none1) { - ControlReducerTester R; - - Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, R.start); - R.ReduceMerge(merge, merge); -} - - -TEST(CMergeReduce_none2) { - ControlReducerTester R; - - Node* t1 = R.graph.NewNode(R.common.IfTrue(), R.start); - Node* t2 = R.graph.NewNode(R.common.IfTrue(), R.start); - Node* merge = R.graph.NewNode(R.common.Merge(2), t1, t2); - R.ReduceMerge(merge, merge); -} - - -TEST(CMergeReduce_self3) { - ControlReducerTester R; - - Node* merge = - R.SetSelfReferences(R.graph.NewNode(R.common.Merge(2), R.start, R.self)); - R.ReduceMerge(merge, merge); -} - - -TEST(CMergeReduce_dead1) { - ControlReducerTester R; - - Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, R.dead); - R.ReduceMerge(R.start, merge); -} - - -TEST(CMergeReduce_dead2) { - ControlReducerTester R; - - Node* merge1 = R.graph.NewNode(R.common.Merge(1), R.start); - Node* merge2 = R.graph.NewNode(R.common.Merge(2), merge1, R.dead); - R.ReduceMerge(merge1, merge2); - R.ReduceMergeIterative(R.start, merge2); -} - - -TEST(CMergeReduce_dead_rm1a) { - ControlReducerTester R; - - for (int i = 0; i < 3; i++) { - Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start); - merge->ReplaceInput(i, R.dead); - R.ReduceMerge(merge, merge); - CheckMerge(merge, R.start, R.start); - } -} - - -TEST(CMergeReduce_dead_rm1b) { - ControlReducerTester R; - - Node* t = R.graph.NewNode(R.common.IfTrue(), R.start); - Node* f = R.graph.NewNode(R.common.IfTrue(), R.start); - for (int i = 0; i < 2; i++) { - Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead); - for (int j = i + 1; j < 3; j++) { - merge->ReplaceInput(i, t); - merge->ReplaceInput(j, f); - R.ReduceMerge(merge, merge); - CheckMerge(merge, t, f); - } - } -} - - -TEST(CMergeReduce_dead_rm2) { - ControlReducerTester R; - - for (int i = 0; i < 3; i++) { - Node* merge = R.graph.NewNode(R.common.Merge(3), R.dead, R.dead, R.dead); - merge->ReplaceInput(i, R.start); - R.ReduceMerge(R.start, merge); - } -} - - -TEST(CLoopReduce_dead_rm1) { - ControlReducerTester R; - - for (int i = 0; i < 3; i++) { - Node* loop = R.graph.NewNode(R.common.Loop(3), R.dead, R.start, R.start); - R.ReduceMerge(loop, loop); - CheckLoop(loop, R.start, R.start); - } -} - - -TEST(CMergeReduce_edit_phi1) { - ControlReducerTester R; - - for (int i = 0; i < 3; i++) { - Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start); - merge->ReplaceInput(i, R.dead); - Node* phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 3), R.leaf[0], - R.leaf[1], R.leaf[2], merge); - R.ReduceMerge(merge, merge); - CHECK_EQ(IrOpcode::kPhi, phi->opcode()); - CHECK_EQ(2, phi->op()->ValueInputCount()); - CHECK_EQ(3, phi->InputCount()); - CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0)); - CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1)); - CHECK_EQ(merge, phi->InputAt(2)); - } -} - - -TEST(CMergeReduce_edit_effect_phi1) { - ControlReducerTester R; - - for (int i = 0; i < 3; i++) { - Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start); - merge->ReplaceInput(i, R.dead); - Node* phi = R.graph.NewNode(R.common.EffectPhi(3), R.leaf[0], R.leaf[1], - R.leaf[2], merge); - R.ReduceMerge(merge, merge); - CHECK_EQ(IrOpcode::kEffectPhi, phi->opcode()); - CHECK_EQ(0, phi->op()->ValueInputCount()); - CHECK_EQ(2, phi->op()->EffectInputCount()); - CHECK_EQ(3, phi->InputCount()); - CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0)); - CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1)); - CHECK_EQ(merge, phi->InputAt(2)); - } -} - - -static const int kSelectorSize = 4; - -// Helper to select K of N nodes according to a mask, useful for the test below. -struct Selector { - int mask; - int count; - explicit Selector(int m) { - mask = m; - count = v8::base::bits::CountPopulation32(m); - } - bool is_selected(int i) { return (mask & (1 << i)) != 0; } - void CheckNode(Node* node, IrOpcode::Value opcode, Node** inputs, - Node* control) { - CHECK_EQ(opcode, node->opcode()); - CHECK_EQ(count + (control != NULL ? 1 : 0), node->InputCount()); - int index = 0; - for (int i = 0; i < kSelectorSize; i++) { - if (mask & (1 << i)) { - CHECK_EQ(inputs[i], node->InputAt(index++)); - } - } - CHECK_EQ(count, index); - if (control != NULL) CHECK_EQ(control, node->InputAt(index++)); - } - int single_index() { - CHECK_EQ(1, count); - return WhichPowerOf2(mask); - } -}; - - -TEST(CMergeReduce_exhaustive_4) { - ControlReducerTester R; - Node* controls[] = { - R.graph.NewNode(R.common.Start(1)), R.graph.NewNode(R.common.Start(2)), - R.graph.NewNode(R.common.Start(3)), R.graph.NewNode(R.common.Start(4))}; - Node* values[] = {R.jsgraph.Int32Constant(11), R.jsgraph.Int32Constant(22), - R.jsgraph.Int32Constant(33), R.jsgraph.Int32Constant(44)}; - Node* effects[] = { - R.jsgraph.Float64Constant(123.4), R.jsgraph.Float64Constant(223.4), - R.jsgraph.Float64Constant(323.4), R.jsgraph.Float64Constant(423.4)}; - - for (int mask = 0; mask < (1 << (kSelectorSize - 1)); mask++) { - // Reduce a single merge with a given mask. - Node* merge = R.graph.NewNode(R.common.Merge(4), controls[0], controls[1], - controls[2], controls[3]); - Node* phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 4), values[0], - values[1], values[2], values[3], merge); - Node* ephi = R.graph.NewNode(R.common.EffectPhi(4), effects[0], effects[1], - effects[2], effects[3], merge); - - Node* phi_use = - R.graph.NewNode(R.common.Phi(kMachAnyTagged, 1), phi, R.start); - Node* ephi_use = R.graph.NewNode(R.common.EffectPhi(1), ephi, R.start); - - Selector selector(mask); - - for (int i = 0; i < kSelectorSize; i++) { // set up dead merge inputs. - if (!selector.is_selected(i)) merge->ReplaceInput(i, R.dead); - } - - Node* result = ControlReducer::ReduceMerge(&R.jsgraph, merge); - - int count = selector.count; - if (count == 0) { - // result should be dead. - CHECK_EQ(IrOpcode::kDead, result->opcode()); - } else if (count == 1) { - // merge should be replaced with one of the controls. - CHECK_EQ(controls[selector.single_index()], result); - // Phis should have been directly replaced. - CHECK_EQ(values[selector.single_index()], phi_use->InputAt(0)); - CHECK_EQ(effects[selector.single_index()], ephi_use->InputAt(0)); - } else { - // Otherwise, nodes should be edited in place. - CHECK_EQ(merge, result); - selector.CheckNode(merge, IrOpcode::kMerge, controls, NULL); - selector.CheckNode(phi, IrOpcode::kPhi, values, merge); - selector.CheckNode(ephi, IrOpcode::kEffectPhi, effects, merge); - CHECK_EQ(phi, phi_use->InputAt(0)); - CHECK_EQ(ephi, ephi_use->InputAt(0)); - CHECK_EQ(count, phi->op()->ValueInputCount()); - CHECK_EQ(count + 1, phi->InputCount()); - CHECK_EQ(count, ephi->op()->EffectInputCount()); - CHECK_EQ(count + 1, ephi->InputCount()); - } - } -} - - -TEST(CMergeReduce_edit_many_phis1) { - ControlReducerTester R; - - const int kPhiCount = 10; - Node* phis[kPhiCount]; - - for (int i = 0; i < 3; i++) { - Node* merge = R.graph.NewNode(R.common.Merge(3), R.start, R.start, R.start); - merge->ReplaceInput(i, R.dead); - for (int j = 0; j < kPhiCount; j++) { - phis[j] = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 3), R.leaf[0], - R.leaf[1], R.leaf[2], merge); - } - R.ReduceMerge(merge, merge); - for (int j = 0; j < kPhiCount; j++) { - Node* phi = phis[j]; - CHECK_EQ(IrOpcode::kPhi, phi->opcode()); - CHECK_EQ(2, phi->op()->ValueInputCount()); - CHECK_EQ(3, phi->InputCount()); - CHECK_EQ(R.leaf[i < 1 ? 1 : 0], phi->InputAt(0)); - CHECK_EQ(R.leaf[i < 2 ? 2 : 1], phi->InputAt(1)); - CHECK_EQ(merge, phi->InputAt(2)); - } - } -} - - -TEST(CMergeReduce_simple_chain1) { - ControlReducerTester R; - for (int i = 0; i < 5; i++) { - Node* merge = R.graph.NewNode(R.common.Merge(1), R.start); - for (int j = 0; j < i; j++) { - merge = R.graph.NewNode(R.common.Merge(1), merge); - } - R.ReduceMergeIterative(R.start, merge); - } -} - - -TEST(CMergeReduce_dead_chain1) { - ControlReducerTester R; - for (int i = 0; i < 5; i++) { - Node* merge = R.graph.NewNode(R.common.Merge(1), R.dead); - for (int j = 0; j < i; j++) { - merge = R.graph.NewNode(R.common.Merge(1), merge); - } - Node* end = R.graph.NewNode(R.common.End(), merge); - R.graph.SetEnd(end); - R.ReduceGraph(); - CHECK(merge->IsDead()); - CHECK(!end->InputAt(0)); // end dies. - } -} - - -TEST(CMergeReduce_dead_chain2) { - ControlReducerTester R; - for (int i = 0; i < 5; i++) { - Node* merge = R.graph.NewNode(R.common.Merge(1), R.start); - for (int j = 0; j < i; j++) { - merge = R.graph.NewNode(R.common.Merge(2), merge, R.dead); - } - R.ReduceMergeIterative(R.start, merge); - } -} - - -TEST(CBranchReduce_none1) { - ControlReducerTester R; - Diamond d(R, R.p0); - R.ReduceBranch(kUnknown, d.branch); -} - - -TEST(CBranchReduce_none2) { - ControlReducerTester R; - Diamond d1(R, R.p0); - Diamond d2(R, R.p0); - d2.chain(d1); - R.ReduceBranch(kUnknown, d2.branch); -} - - -TEST(CBranchReduce_true) { - ControlReducerTester R; - Node* true_values[] = { - R.one, R.jsgraph.Int32Constant(2), - R.jsgraph.Int32Constant(0x7fffffff), R.jsgraph.Constant(1.0), - R.jsgraph.Constant(22.1), R.jsgraph.TrueConstant()}; - - for (size_t i = 0; i < arraysize(true_values); i++) { - Diamond d(R, true_values[i]); - R.ReduceBranch(kTrue, d.branch); - } -} - - -TEST(CBranchReduce_false) { - ControlReducerTester R; - Node* false_values[] = {R.zero, R.jsgraph.Constant(0.0), - R.jsgraph.Constant(-0.0), R.jsgraph.FalseConstant()}; - - for (size_t i = 0; i < arraysize(false_values); i++) { - Diamond d(R, false_values[i]); - R.ReduceBranch(kFalse, d.branch); - } -} - - -TEST(CDiamondReduce_true) { - ControlReducerTester R; - Diamond d1(R, R.one); - R.ReduceMergeIterative(R.start, d1.merge); -} - - -TEST(CDiamondReduce_false) { - ControlReducerTester R; - Diamond d2(R, R.zero); - R.ReduceMergeIterative(R.start, d2.merge); -} - - -TEST(CChainedDiamondsReduce_true_false) { - ControlReducerTester R; - Diamond d1(R, R.one); - Diamond d2(R, R.zero); - d2.chain(d1); - - R.ReduceMergeIterative(R.start, d2.merge); -} - - -TEST(CChainedDiamondsReduce_x_false) { - ControlReducerTester R; - Diamond d1(R, R.p0); - Diamond d2(R, R.zero); - d2.chain(d1); - - R.ReduceMergeIterative(R.start, d2.merge); -} - - -TEST(CChainedDiamondsReduce_false_x) { - ControlReducerTester R; - Diamond d1(R, R.zero); - Diamond d2(R, R.p0); - d2.chain(d1); - - R.ReduceMergeIterative(R.start, d2.merge); -} - - -TEST(CChainedDiamondsReduce_phi1) { - ControlReducerTester R; - Diamond d1(R, R.zero, R.one, R.zero); // foldable branch, phi. - Diamond d2(R, d1.phi); - d2.chain(d1); - - R.ReduceMergeIterative(R.start, d2.merge); -} - - -TEST(CChainedDiamondsReduce_phi2) { - ControlReducerTester R; - Diamond d1(R, R.p0, R.one, R.one); // redundant phi. - Diamond d2(R, d1.phi); - d2.chain(d1); - - R.ReduceMergeIterative(d1.merge, d2.merge); -} - - -TEST(CNestedDiamondsReduce_true_true_false) { - ControlReducerTester R; - Diamond d1(R, R.one); - Diamond d2(R, R.zero); - d2.nest(d1, true); - - R.ReduceMergeIterative(R.start, d1.merge); -} - - -TEST(CNestedDiamondsReduce_false_true_false) { - ControlReducerTester R; - Diamond d1(R, R.one); - Diamond d2(R, R.zero); - d2.nest(d1, false); - - R.ReduceMergeIterative(R.start, d1.merge); -} - - -TEST(CNestedDiamonds_xyz) { - ControlReducerTester R; - - for (int a = 0; a < 2; a++) { - for (int b = 0; b < 2; b++) { - for (int c = 0; c < 2; c++) { - Diamond d1(R, R.jsgraph.Int32Constant(a)); - Diamond d2(R, R.jsgraph.Int32Constant(b)); - d2.nest(d1, c); - - R.ReduceMergeIterative(R.start, d1.merge); - } - } - } -} - - -TEST(CUnusedDiamond1) { - ControlReducerTester R; - // if (p0) { } else { } - Node* branch = R.graph.NewNode(R.common.Branch(), R.p0, R.start); - Node* if_true = R.graph.NewNode(R.common.IfTrue(), branch); - Node* if_false = R.graph.NewNode(R.common.IfFalse(), branch); - Node* merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false); - R.ReduceMergeIterative(R.start, merge); -} - - -TEST(CUnusedDiamond2) { - ControlReducerTester R; - // if (p0) { } else { } - Node* branch = R.graph.NewNode(R.common.Branch(), R.p0, R.start); - Node* if_true = R.graph.NewNode(R.common.IfTrue(), branch); - Node* if_false = R.graph.NewNode(R.common.IfFalse(), branch); - Node* merge = R.graph.NewNode(R.common.Merge(2), if_false, if_true); - R.ReduceMergeIterative(R.start, merge); -} - - -TEST(CDeadLoop1) { - ControlReducerTester R; - - Node* loop = R.graph.NewNode(R.common.Loop(1), R.start); - Branch b(R, R.p0, loop); - loop->ReplaceInput(0, b.if_true); // loop is not connected to start. - Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, b.if_false); - R.ReduceMergeIterative(R.start, merge); - - DeadChecker dead(&R.graph); - dead.Check(b.if_true); - dead.Check(b.if_false); - dead.Check(b.branch); - dead.Check(loop); -} - - -TEST(CDeadLoop2) { - ControlReducerTester R; - - While w(R, R.p0); - Diamond d(R, R.zero); - // if (0) { while (p0) ; } else { } - w.branch->ReplaceInput(1, d.if_true); - d.merge->ReplaceInput(0, w.exit); - - R.ReduceMergeIterative(R.start, d.merge); - - DeadChecker dead(&R.graph); - dead.Check(d); - dead.Check(w.loop); -} - - -TEST(Return1) { - ControlReducerTester R; - Node* ret = R.Return(R.one, R.start, R.start); - R.ReduceGraph(); - CheckInputs(R.graph.end(), ret); - CheckInputs(ret, R.one, R.start, R.start); -} - - -TEST(Return2) { - ControlReducerTester R; - Diamond d(R, R.one); - Node* ret = R.Return(R.half, R.start, d.merge); - R.ReduceGraph(); - - DeadChecker dead(&R.graph); - dead.Check(d.branch); - dead.Check(d.if_true); - dead.Check(d.if_false); - dead.Check(d.merge); - - CheckInputs(R.graph.end(), ret); - CheckInputs(ret, R.half, R.start, R.start); -} - - -TEST(Return_true1) { - ControlReducerTester R; - Diamond d(R, R.one, R.half, R.zero); - Node* ret = R.Return(d.phi, R.start, d.merge); - R.ReduceGraph(); - - DeadChecker dead(&R.graph); - dead.Check(d.branch); - dead.Check(d.if_true); - dead.Check(d.if_false); - dead.Check(d.merge); - dead.Check(d.phi); - - CheckInputs(R.graph.end(), ret); - CheckInputs(ret, R.half, R.start, R.start); -} - - -TEST(Return_false1) { - ControlReducerTester R; - Diamond d(R, R.zero, R.one, R.half); - Node* ret = R.Return(d.phi, R.start, d.merge); - R.ReduceGraph(); - - DeadChecker dead(&R.graph); - dead.Check(d.branch); - dead.Check(d.if_true); - dead.Check(d.if_false); - dead.Check(d.merge); - dead.Check(d.phi); - - CheckInputs(R.graph.end(), ret); - CheckInputs(ret, R.half, R.start, R.start); -} - - -TEST(Return_effect1) { - ControlReducerTester R; - Diamond d(R, R.one); - Node* e1 = R.jsgraph.Float64Constant(-100.1); - Node* e2 = R.jsgraph.Float64Constant(+100.1); - Node* effect = R.graph.NewNode(R.common.EffectPhi(2), e1, e2, d.merge); - Node* ret = R.Return(R.p0, effect, d.merge); - R.ReduceGraph(); - - DeadChecker dead(&R.graph); - dead.Check(d); - dead.Check(effect); - - CheckInputs(R.graph.end(), ret); - CheckInputs(ret, R.p0, e1, R.start); -} - - -TEST(Return_nested_diamonds1) { - ControlReducerTester R; - Diamond d2(R, R.p0, R.one, R.zero); - Diamond d3(R, R.p0, R.one, R.zero); - Diamond d1(R, R.p0, d2.phi, d3.phi); - - d2.nest(d1, true); - d3.nest(d1, false); - - Node* ret = R.Return(d1.phi, R.start, d1.merge); - - R.ReduceGraph(); // nothing should happen. - - CheckInputs(ret, d1.phi, R.start, d1.merge); - CheckInputs(d1.phi, d2.phi, d3.phi, d1.merge); - CheckInputs(d1.merge, d2.merge, d3.merge); - - DeadChecker dead(&R.graph); - dead.CheckLive(d2); - dead.CheckLive(d3); -} - - -TEST(Return_nested_diamonds1_dead1) { - ControlReducerTester R; - Diamond d2(R, R.p0); // dead diamond - Diamond d3(R, R.p0, R.one, R.zero); - Diamond d1(R, R.p0, R.one, d3.phi); - - d2.nest(d1, true); - d3.nest(d1, false); - - Node* ret = R.Return(d1.phi, R.start, d1.merge); - - R.ReduceGraph(); - - CheckInputs(ret, d1.phi, R.start, d1.merge); - CheckInputs(d1.phi, R.one, d3.phi, d1.merge); - CheckInputs(d1.merge, d1.if_true, d3.merge); - - DeadChecker dead(&R.graph); - dead.Check(d2); // d2 was a dead diamond. - dead.CheckLive(d3); -} - - -TEST(Return_nested_diamonds1_dead2) { - ControlReducerTester R; - Diamond d2(R, R.p0); // dead diamond - Diamond d3(R, R.p0); // dead diamond - Diamond d1(R, R.p0, R.one, R.zero); - - d2.nest(d1, true); - d3.nest(d1, false); - - Node* ret = R.Return(d1.phi, R.start, d1.merge); - - R.ReduceGraph(); - - CheckInputs(ret, d1.phi, R.start, d1.merge); - CheckInputs(d1.phi, R.one, R.zero, d1.merge); - CheckInputs(d1.merge, d1.if_true, d1.if_false); - - DeadChecker dead(&R.graph); - dead.Check(d2); - dead.Check(d3); -} - - -TEST(Return_nested_diamonds_true1) { - ControlReducerTester R; - Diamond d2(R, R.p0, R.one, R.zero); - Diamond d1(R, R.one, d2.phi, R.zero); - Diamond d3(R, R.p0); - - d2.nest(d1, true); - d3.nest(d1, false); - - Node* ret = R.Return(d1.phi, R.start, d1.merge); - - R.ReduceGraph(); // d1 gets folded true. - - CheckInputs(ret, d2.phi, R.start, d2.merge); - CheckInputs(d2.branch, R.p0, R.start); - - DeadChecker dead(&R.graph); - dead.Check(d1); - dead.CheckLive(d2); - dead.Check(d3); -} - - -TEST(Return_nested_diamonds_false1) { - ControlReducerTester R; - Diamond d3(R, R.p0, R.one, R.zero); - Diamond d1(R, R.zero, R.one, d3.phi); - Diamond d2(R, R.p0); - - d2.nest(d1, true); - d3.nest(d1, false); - - Node* ret = R.Return(d1.phi, R.start, d1.merge); - - R.ReduceGraph(); // d1 gets folded false. - - CheckInputs(ret, d3.phi, R.start, d3.merge); - CheckInputs(d3.branch, R.p0, R.start); - - DeadChecker dead(&R.graph); - dead.Check(d1); - dead.Check(d2); - dead.CheckLive(d3); -} - - -TEST(Return_nested_diamonds_true_true1) { - ControlReducerTester R; - Diamond d1(R, R.one, R.one, R.zero); - Diamond d2(R, R.one); - Diamond d3(R, R.p0); - - d2.nest(d1, true); - d3.nest(d1, false); - - Node* ret = R.Return(d1.phi, R.start, d1.merge); - - R.ReduceGraph(); // d1 and d2 both get folded true. - - CheckInputs(ret, R.one, R.start, R.start); - - DeadChecker dead(&R.graph); - dead.Check(d1); - dead.Check(d2); - dead.Check(d3); -} - - -TEST(Return_nested_diamonds_true_false1) { - ControlReducerTester R; - Diamond d1(R, R.one, R.one, R.zero); - Diamond d2(R, R.zero); - Diamond d3(R, R.p0); - - d2.nest(d1, true); - d3.nest(d1, false); - - Node* ret = R.Return(d1.phi, R.start, d1.merge); - - R.ReduceGraph(); // d1 gets folded true and d2 gets folded false. - - CheckInputs(ret, R.one, R.start, R.start); - - DeadChecker dead(&R.graph); - dead.Check(d1); - dead.Check(d2); - dead.Check(d3); -} - - -TEST(Return_nested_diamonds2) { - ControlReducerTester R; - Node* x2 = R.jsgraph.Float64Constant(11.1); - Node* y2 = R.jsgraph.Float64Constant(22.2); - Node* x3 = R.jsgraph.Float64Constant(33.3); - Node* y3 = R.jsgraph.Float64Constant(44.4); - - Diamond d2(R, R.p0, x2, y2); - Diamond d3(R, R.p0, x3, y3); - Diamond d1(R, R.p0, d2.phi, d3.phi); - - d2.nest(d1, true); - d3.nest(d1, false); - - Node* ret = R.Return(d1.phi, R.start, d1.merge); - - R.ReduceGraph(); // nothing should happen. - - CheckInputs(ret, d1.phi, R.start, d1.merge); - CheckInputs(d1.phi, d2.phi, d3.phi, d1.merge); - CheckInputs(d1.merge, d2.merge, d3.merge); - - DeadChecker dead(&R.graph); - dead.CheckLive(d2); - dead.CheckLive(d3); -} - - -TEST(Return_nested_diamonds_true2) { - ControlReducerTester R; - Node* x2 = R.jsgraph.Float64Constant(11.1); - Node* y2 = R.jsgraph.Float64Constant(22.2); - Node* x3 = R.jsgraph.Float64Constant(33.3); - Node* y3 = R.jsgraph.Float64Constant(44.4); - - Diamond d2(R, R.p0, x2, y2); - Diamond d3(R, R.p0, x3, y3); - Diamond d1(R, R.one, d2.phi, d3.phi); - - d2.nest(d1, true); - d3.nest(d1, false); - - Node* ret = R.Return(d1.phi, R.start, d1.merge); - - R.ReduceGraph(); // d1 gets folded true. - - CheckInputs(ret, d2.phi, R.start, d2.merge); - CheckInputs(d2.branch, R.p0, R.start); - - DeadChecker dead(&R.graph); - dead.Check(d1); - dead.CheckLive(d2); - dead.Check(d3); -} - - -TEST(Return_nested_diamonds_true_true2) { - ControlReducerTester R; - Node* x2 = R.jsgraph.Float64Constant(11.1); - Node* y2 = R.jsgraph.Float64Constant(22.2); - Node* x3 = R.jsgraph.Float64Constant(33.3); - Node* y3 = R.jsgraph.Float64Constant(44.4); - - Diamond d2(R, R.one, x2, y2); - Diamond d3(R, R.p0, x3, y3); - Diamond d1(R, R.one, d2.phi, d3.phi); - - d2.nest(d1, true); - d3.nest(d1, false); - - Node* ret = R.Return(d1.phi, R.start, d1.merge); - - R.ReduceGraph(); // d1 gets folded true. - - CheckInputs(ret, x2, R.start, R.start); - - DeadChecker dead(&R.graph); - dead.Check(d1); - dead.Check(d2); - dead.Check(d3); -} - - -TEST(Return_nested_diamonds_true_false2) { - ControlReducerTester R; - Node* x2 = R.jsgraph.Float64Constant(11.1); - Node* y2 = R.jsgraph.Float64Constant(22.2); - Node* x3 = R.jsgraph.Float64Constant(33.3); - Node* y3 = R.jsgraph.Float64Constant(44.4); - - Diamond d2(R, R.zero, x2, y2); - Diamond d3(R, R.p0, x3, y3); - Diamond d1(R, R.one, d2.phi, d3.phi); - - d2.nest(d1, true); - d3.nest(d1, false); - - Node* ret = R.Return(d1.phi, R.start, d1.merge); - - R.ReduceGraph(); // d1 gets folded true. - - CheckInputs(ret, y2, R.start, R.start); - - DeadChecker dead(&R.graph); - dead.Check(d1); - dead.Check(d2); - dead.Check(d3); -} diff --git a/deps/v8/test/cctest/compiler/test-js-constant-cache.cc b/deps/v8/test/cctest/compiler/test-js-constant-cache.cc index 630f911c5e..8774a9a9e3 100644 --- a/deps/v8/test/cctest/compiler/test-js-constant-cache.cc +++ b/deps/v8/test/cctest/compiler/test-js-constant-cache.cc @@ -21,7 +21,7 @@ class JSCacheTesterHelper { : main_graph_(zone), main_common_(zone), main_javascript_(zone), - main_typer_(isolate, &main_graph_, MaybeHandle<Context>()), + main_typer_(isolate, &main_graph_), main_machine_(zone) {} Graph main_graph_; CommonOperatorBuilder main_common_; @@ -41,7 +41,7 @@ class JSConstantCacheTester : public HandleAndZoneScope, JSGraph(main_isolate(), &main_graph_, &main_common_, &main_javascript_, &main_machine_) { main_graph_.SetStart(main_graph_.NewNode(common()->Start(0))); - main_graph_.SetEnd(main_graph_.NewNode(common()->End())); + main_graph_.SetEnd(main_graph_.NewNode(common()->End(1))); main_typer_.Run(); } @@ -335,7 +335,7 @@ TEST(JSGraph_GetCachedNodes_int32) { 25, 15, 30, 31, 45, 46, 47, 48}; for (size_t i = 0; i < arraysize(constants); i++) { - int count_before = T.graph()->NodeCount(); + size_t count_before = T.graph()->NodeCount(); NodeVector nodes_before(T.main_zone()); T.GetCachedNodes(&nodes_before); Node* n = T.Int32Constant(constants[i]); @@ -357,7 +357,7 @@ TEST(JSGraph_GetCachedNodes_float64) { 11, 11, -33.3, -33.3, -22, -11}; for (size_t i = 0; i < arraysize(constants); i++) { - int count_before = T.graph()->NodeCount(); + size_t count_before = T.graph()->NodeCount(); NodeVector nodes_before(T.main_zone()); T.GetCachedNodes(&nodes_before); Node* n = T.Float64Constant(constants[i]); @@ -379,7 +379,7 @@ TEST(JSGraph_GetCachedNodes_int64) { 19, 20, 20, 21, 21, 22, 23, 24, 25}; for (size_t i = 0; i < arraysize(constants); i++) { - int count_before = T.graph()->NodeCount(); + size_t count_before = T.graph()->NodeCount(); NodeVector nodes_before(T.main_zone()); T.GetCachedNodes(&nodes_before); Node* n = T.Int64Constant(constants[i]); @@ -401,7 +401,7 @@ TEST(JSGraph_GetCachedNodes_number) { 11, 11, -33.3, -33.3, -22, -11}; for (size_t i = 0; i < arraysize(constants); i++) { - int count_before = T.graph()->NodeCount(); + size_t count_before = T.graph()->NodeCount(); NodeVector nodes_before(T.main_zone()); T.GetCachedNodes(&nodes_before); Node* n = T.Constant(constants[i]); @@ -428,7 +428,7 @@ TEST(JSGraph_GetCachedNodes_external) { ExternalReference::address_of_one_half()}; for (size_t i = 0; i < arraysize(constants); i++) { - int count_before = T.graph()->NodeCount(); + size_t count_before = T.graph()->NodeCount(); NodeVector nodes_before(T.main_zone()); T.GetCachedNodes(&nodes_before); Node* n = T.ExternalConstant(constants[i]); diff --git a/deps/v8/test/cctest/compiler/test-js-context-specialization.cc b/deps/v8/test/cctest/compiler/test-js-context-specialization.cc index 2450e7cf57..328b0aefdd 100644 --- a/deps/v8/test/cctest/compiler/test-js-context-specialization.cc +++ b/deps/v8/test/cctest/compiler/test-js-context-specialization.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "src/compiler/js-context-specialization.h" +#include "src/compiler/js-graph.h" #include "src/compiler/js-operator.h" #include "src/compiler/node-matchers.h" #include "src/compiler/node-properties.h" @@ -22,8 +23,11 @@ class ContextSpecializationTester : public HandleAndZoneScope { javascript_(main_zone()), machine_(main_zone()), simplified_(main_zone()), - jsgraph_(main_isolate(), graph(), common(), &javascript_, &machine_) {} + jsgraph_(main_isolate(), graph(), common(), &javascript_, &machine_), + reducer_(main_zone(), graph()), + spec_(&reducer_, jsgraph(), MaybeHandle<Context>()) {} + JSContextSpecialization* spec() { return &spec_; } Factory* factory() { return main_isolate()->factory(); } CommonOperatorBuilder* common() { return &common_; } JSOperatorBuilder* javascript() { return &javascript_; } @@ -38,6 +42,8 @@ class ContextSpecializationTester : public HandleAndZoneScope { MachineOperatorBuilder machine_; SimplifiedOperatorBuilder simplified_; JSGraph jsgraph_; + GraphReducer reducer_; + JSContextSpecialization spec_; }; @@ -60,13 +66,12 @@ TEST(ReduceJSLoadContext) { Node* const_context = t.jsgraph()->Constant(native); Node* deep_const_context = t.jsgraph()->Constant(subcontext2); Node* param_context = t.graph()->NewNode(t.common()->Parameter(0), start); - JSContextSpecializer spec(t.jsgraph()); { // Mutable slot, constant context, depth = 0 => do nothing. Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, 0, false), const_context, const_context, start); - Reduction r = spec.ReduceJSLoadContext(load); + Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } @@ -74,7 +79,7 @@ TEST(ReduceJSLoadContext) { // Mutable slot, non-constant context, depth = 0 => do nothing. Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, 0, false), param_context, param_context, start); - Reduction r = spec.ReduceJSLoadContext(load); + Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } @@ -83,11 +88,11 @@ TEST(ReduceJSLoadContext) { Node* load = t.graph()->NewNode( t.javascript()->LoadContext(2, Context::GLOBAL_EVAL_FUN_INDEX, false), deep_const_context, deep_const_context, start); - Reduction r = spec.ReduceJSLoadContext(load); + Reduction r = t.spec()->Reduce(load); CHECK(r.Changed()); Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0); CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode()); - HeapObjectMatcher<Context> match(new_context_input); + HeapObjectMatcher match(new_context_input); CHECK_EQ(*native, *match.Value().handle()); ContextAccess access = OpParameter<ContextAccess>(r.replacement()); CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index())); @@ -99,11 +104,11 @@ TEST(ReduceJSLoadContext) { // Immutable slot, constant context, depth = 0 => specialize. Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true), const_context, const_context, start); - Reduction r = spec.ReduceJSLoadContext(load); + Reduction r = t.spec()->Reduce(load); CHECK(r.Changed()); CHECK(r.replacement() != load); - HeapObjectMatcher<Object> match(r.replacement()); + HeapObjectMatcher match(r.replacement()); CHECK(match.HasValue()); CHECK_EQ(*expected, *match.Value().handle()); } @@ -132,13 +137,12 @@ TEST(ReduceJSStoreContext) { Node* const_context = t.jsgraph()->Constant(native); Node* deep_const_context = t.jsgraph()->Constant(subcontext2); Node* param_context = t.graph()->NewNode(t.common()->Parameter(0), start); - JSContextSpecializer spec(t.jsgraph()); { // Mutable slot, constant context, depth = 0 => do nothing. Node* load = t.graph()->NewNode(t.javascript()->StoreContext(0, 0), const_context, const_context, start); - Reduction r = spec.ReduceJSStoreContext(load); + Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } @@ -146,7 +150,7 @@ TEST(ReduceJSStoreContext) { // Mutable slot, non-constant context, depth = 0 => do nothing. Node* load = t.graph()->NewNode(t.javascript()->StoreContext(0, 0), param_context, param_context, start); - Reduction r = spec.ReduceJSStoreContext(load); + Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } @@ -154,7 +158,7 @@ TEST(ReduceJSStoreContext) { // Immutable slot, constant context, depth = 0 => do nothing. Node* load = t.graph()->NewNode(t.javascript()->StoreContext(0, slot), const_context, const_context, start); - Reduction r = spec.ReduceJSStoreContext(load); + Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } @@ -163,11 +167,11 @@ TEST(ReduceJSStoreContext) { Node* load = t.graph()->NewNode( t.javascript()->StoreContext(2, Context::GLOBAL_EVAL_FUN_INDEX), deep_const_context, deep_const_context, start); - Reduction r = spec.ReduceJSStoreContext(load); + Reduction r = t.spec()->Reduce(load); CHECK(r.Changed()); Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0); CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode()); - HeapObjectMatcher<Context> match(new_context_input); + HeapObjectMatcher match(new_context_input); CHECK_EQ(*native, *match.Value().handle()); ContextAccess access = OpParameter<ContextAccess>(r.replacement()); CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index())); @@ -197,7 +201,6 @@ TEST(SpecializeToContext) { Node* const_context = t.jsgraph()->Constant(native); Node* param_context = t.graph()->NewNode(t.common()->Parameter(0), start); - JSContextSpecializer spec(t.jsgraph()); { // Check that specialization replaces values and forwards effects @@ -222,7 +225,7 @@ TEST(SpecializeToContext) { Node* ret = t.graph()->NewNode(t.common()->Return(), add, effect_use, start); - Node* end = t.graph()->NewNode(t.common()->End(), ret); + Node* end = t.graph()->NewNode(t.common()->End(1), ret); USE(end); t.graph()->SetEnd(end); @@ -231,7 +234,9 @@ TEST(SpecializeToContext) { CheckEffectInput(load, effect_use); // Perform the reduction on the entire graph. - GraphReducer graph_reducer(t.graph(), t.main_zone()); + GraphReducer graph_reducer(t.main_zone(), t.graph()); + JSContextSpecialization spec(&graph_reducer, t.jsgraph(), + MaybeHandle<Context>()); graph_reducer.AddReducer(&spec); graph_reducer.ReduceGraph(); @@ -242,7 +247,7 @@ TEST(SpecializeToContext) { CHECK_EQ(other_load, other_use->InputAt(0)); Node* replacement = value_use->InputAt(0); - HeapObjectMatcher<Object> match(replacement); + HeapObjectMatcher match(replacement); CHECK(match.HasValue()); CHECK_EQ(*expected, *match.Value().handle()); } diff --git a/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc b/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc index 92fdb6e874..e512de89b2 100644 --- a/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc +++ b/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc @@ -38,10 +38,10 @@ class JSTypedLoweringTester : public HandleAndZoneScope { simplified(main_zone()), common(main_zone()), graph(main_zone()), - typer(main_isolate(), &graph, MaybeHandle<Context>()), + typer(main_isolate(), &graph), context_node(NULL) { graph.SetStart(graph.NewNode(common.Start(num_parameters))); - graph.SetEnd(graph.NewNode(common.End())); + graph.SetEnd(graph.NewNode(common.End(1))); typer.Run(); } @@ -79,17 +79,19 @@ class JSTypedLoweringTester : public HandleAndZoneScope { Node* locals = graph.NewNode(common.StateValues(0)); Node* stack = graph.NewNode(common.StateValues(0)); - Node* state_node = - graph.NewNode(common.FrameState(JS_FRAME, BailoutId::None(), - OutputFrameStateCombine::Ignore()), - parameters, locals, stack, context, UndefinedConstant()); + Node* state_node = graph.NewNode( + common.FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(), + nullptr), + parameters, locals, stack, context, UndefinedConstant()); return state_node; } Node* reduce(Node* node) { JSGraph jsgraph(main_isolate(), &graph, &common, &javascript, &machine); - JSTypedLowering reducer(&jsgraph, main_zone()); + // TODO(titzer): mock the GraphReducer here for better unit testing. + GraphReducer graph_reducer(main_zone(), &graph); + JSTypedLowering reducer(&graph_reducer, &jsgraph, main_zone()); Reduction reduction = reducer.Reduce(node); if (reduction.Changed()) return reduction.replacement(); return node; @@ -318,11 +320,11 @@ class JSBitwiseShiftTypedLoweringTester : public JSTypedLoweringTester { : JSTypedLoweringTester(), language_mode_(language_mode) { int i = 0; set(i++, javascript.ShiftLeft(language_mode_), true); - set(i++, machine.Word32Shl(), false); + set(i++, simplified.NumberShiftLeft(), false); set(i++, javascript.ShiftRight(language_mode_), true); - set(i++, machine.Word32Sar(), false); + set(i++, simplified.NumberShiftRight(), false); set(i++, javascript.ShiftRightLogical(language_mode_), false); - set(i++, machine.Word32Shr(), false); + set(i++, simplified.NumberShiftRightLogical(), false); } static const int kNumberOps = 6; const Operator* ops[kNumberOps]; @@ -362,14 +364,7 @@ TEST(Int32BitwiseShifts) { Node* r1 = r->InputAt(1); CheckToI32(p0, r0, R.signedness[k]); - - if (r1->opcode() == IrOpcode::kWord32And) { - R.CheckPureBinop(IrOpcode::kWord32And, r1); - CheckToI32(p1, r1->InputAt(0), R.signedness[k + 1]); - R.CheckInt32Constant(0x1F, r1->InputAt(1)); - } else { - CheckToI32(p1, r1, R.signedness[k]); - } + CheckToI32(p1, r1, false); } } } @@ -460,8 +455,9 @@ TEST(JSToNumber_replacement) { for (size_t i = 0; i < arraysize(types); i++) { Node* n = R.Parameter(types[i]); - Node* c = R.graph.NewNode(R.javascript.ToNumber(), n, R.context(), - R.start(), R.start()); + Node* c = + R.graph.NewNode(R.javascript.ToNumber(), n, R.context(), + R.EmptyFrameState(R.context()), R.start(), R.start()); Node* effect_use = R.UseForEffect(c); Node* add = R.graph.NewNode(R.simplified.ReferenceEqual(Type::Any()), n, c); @@ -688,18 +684,20 @@ TEST_WITH_STRONG(MixedComparison1) { for (size_t j = 0; j < arraysize(types); j++) { Node* p1 = R.Parameter(types[j], 1); { - Node* cmp = R.Binop(R.javascript.LessThan(language_mode), p0, p1); + const Operator* less_than = R.javascript.LessThan(language_mode); + Node* cmp = R.Binop(less_than, p0, p1); Node* r = R.reduce(cmp); - - if (!types[i]->Maybe(Type::String()) || - !types[j]->Maybe(Type::String())) { - if (types[i]->Is(Type::String()) && types[j]->Is(Type::String())) { - R.CheckPureBinop(R.simplified.StringLessThan(), r); - } else { - R.CheckPureBinop(R.simplified.NumberLessThan(), r); - } + if (types[i]->Is(Type::String()) && types[j]->Is(Type::String())) { + R.CheckPureBinop(R.simplified.StringLessThan(), r); + } else if ((types[i]->Is(Type::Number()) && + types[j]->Is(Type::Number())) || + (!is_strong(language_mode) && + (!types[i]->Maybe(Type::String()) || + !types[j]->Maybe(Type::String())))) { + R.CheckPureBinop(R.simplified.NumberLessThan(), r); } else { - CHECK_EQ(cmp, r); // No reduction of mixed types. + // No reduction of mixed types. + CHECK_EQ(r->op(), less_than); } } } @@ -708,8 +706,6 @@ TEST_WITH_STRONG(MixedComparison1) { TEST_WITH_STRONG(RemoveToNumberEffects) { - FLAG_turbo_deoptimization = true; - JSTypedLoweringTester R; Node* effect_use = NULL; @@ -721,27 +717,16 @@ TEST_WITH_STRONG(RemoveToNumberEffects) { switch (i) { case 0: - if (FLAG_turbo_deoptimization) { - DCHECK(OperatorProperties::GetFrameStateInputCount( - R.javascript.ToNumber()) == 1); - effect_use = R.graph.NewNode(R.javascript.ToNumber(), p0, R.context(), - frame_state, ton, R.start()); - } else { + DCHECK(OperatorProperties::GetFrameStateInputCount( + R.javascript.ToNumber()) == 1); effect_use = R.graph.NewNode(R.javascript.ToNumber(), p0, R.context(), - ton, R.start()); - } + frame_state, ton, R.start()); break; case 1: - if (FLAG_turbo_deoptimization) { - DCHECK(OperatorProperties::GetFrameStateInputCount( - R.javascript.ToNumber()) == 1); - effect_use = - R.graph.NewNode(R.javascript.ToNumber(), ton, R.context(), - frame_state, ton, R.start()); - } else { - effect_use = R.graph.NewNode(R.javascript.ToNumber(), ton, - R.context(), ton, R.start()); - } + DCHECK(OperatorProperties::GetFrameStateInputCount( + R.javascript.ToNumber()) == 1); + effect_use = R.graph.NewNode(R.javascript.ToNumber(), ton, R.context(), + frame_state, ton, R.start()); break; case 2: effect_use = R.graph.NewNode(R.common.EffectPhi(1), ton, R.start()); @@ -950,8 +935,6 @@ TEST(OrderNumberBinopEffects1) { R.simplified.NumberMultiply(), R.javascript.Divide(LanguageMode::SLOPPY), R.simplified.NumberDivide(), - R.javascript.Modulus(LanguageMode::SLOPPY), - R.simplified.NumberModulus(), }; for (size_t j = 0; j < arraysize(ops); j += 2) { @@ -982,8 +965,6 @@ TEST(OrderNumberBinopEffects2) { R.simplified.NumberMultiply(), R.javascript.Divide(LanguageMode::SLOPPY), R.simplified.NumberDivide(), - R.javascript.Modulus(LanguageMode::SLOPPY), - R.simplified.NumberModulus(), }; for (size_t j = 0; j < arraysize(ops); j += 2) { diff --git a/deps/v8/test/cctest/compiler/test-jump-threading.cc b/deps/v8/test/cctest/compiler/test-jump-threading.cc index e0a4a2fc62..9fa3c9f28a 100644 --- a/deps/v8/test/cctest/compiler/test-jump-threading.cc +++ b/deps/v8/test/cctest/compiler/test-jump-threading.cc @@ -85,7 +85,7 @@ class TestCode : public HandleAndZoneScope { if (current_ == NULL) { current_ = new (main_zone()) InstructionBlock(main_zone(), rpo_number_, RpoNumber::Invalid(), - RpoNumber::Invalid(), deferred); + RpoNumber::Invalid(), deferred, false); blocks_.push_back(current_); sequence_.StartBlock(rpo_number_); } diff --git a/deps/v8/test/cctest/compiler/test-linkage.cc b/deps/v8/test/cctest/compiler/test-linkage.cc index 212ff3a8f2..252c43133e 100644 --- a/deps/v8/test/cctest/compiler/test-linkage.cc +++ b/deps/v8/test/cctest/compiler/test-linkage.cc @@ -34,8 +34,8 @@ static Handle<JSFunction> Compile(const char* source) { ->NewStringFromUtf8(CStrVector(source)) .ToHandleChecked(); Handle<SharedFunctionInfo> shared_function = Compiler::CompileScript( - source_code, Handle<String>(), 0, 0, false, false, Handle<Object>(), - Handle<Context>(isolate->native_context()), NULL, NULL, + source_code, Handle<String>(), 0, 0, v8::ScriptOriginOptions(), + Handle<Object>(), Handle<Context>(isolate->native_context()), NULL, NULL, v8::ScriptCompiler::kNoCompileOptions, NOT_NATIVES_CODE, false); return isolate->factory()->NewFunctionFromSharedFunctionInfo( shared_function, isolate->native_context()); @@ -114,5 +114,4 @@ TEST(TestLinkageStubCall) { // TODO(titzer): test linkage creation for outgoing stub calls. } - #endif // V8_TURBOFAN_TARGET diff --git a/deps/v8/test/cctest/compiler/test-loop-analysis.cc b/deps/v8/test/cctest/compiler/test-loop-analysis.cc index 06682ef5a9..6560ae337b 100644 --- a/deps/v8/test/cctest/compiler/test-loop-analysis.cc +++ b/deps/v8/test/cctest/compiler/test-loop-analysis.cc @@ -41,7 +41,7 @@ class LoopFinderTester : HandleAndZoneScope { graph(main_zone()), jsgraph(main_isolate(), &graph, &common, NULL, NULL), start(graph.NewNode(common.Start(1))), - end(graph.NewNode(common.End(), start)), + end(graph.NewNode(common.End(1), start)), p0(graph.NewNode(common.Parameter(0), start)), zero(jsgraph.Int32Constant(0)), one(jsgraph.OneConstant()), diff --git a/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc b/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc index 5f9820c72a..ad05273995 100644 --- a/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc +++ b/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc @@ -51,7 +51,7 @@ struct TestHelper : public HandleAndZoneScope { i::Variable* var = scope->Lookup(name); CHECK(var); - if (var->location() == Variable::UNALLOCATED) { + if (var->location() == VariableLocation::UNALLOCATED) { CHECK_EQ(0, expected); } else { CHECK(var->IsStackAllocated()); diff --git a/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc b/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc index beedc459e7..299f0c02ab 100644 --- a/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc +++ b/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc @@ -60,7 +60,7 @@ class ReducerTester : public HandleAndZoneScope { common(main_zone()), graph(main_zone()), javascript(main_zone()), - typer(isolate, &graph, MaybeHandle<Context>()), + typer(isolate, &graph), jsgraph(isolate, &graph, &common, &javascript, &machine), maxuint32(Constant<int32_t>(kMaxUInt32)) { Node* s = graph.NewNode(common.Start(num_parameters)); diff --git a/deps/v8/test/cctest/compiler/test-osr.cc b/deps/v8/test/cctest/compiler/test-osr.cc index d2171188f8..80dbccc633 100644 --- a/deps/v8/test/cctest/compiler/test-osr.cc +++ b/deps/v8/test/cctest/compiler/test-osr.cc @@ -51,7 +51,7 @@ class OsrDeconstructorTester : public HandleAndZoneScope { jsgraph(main_isolate(), &graph, &common, NULL, NULL), start(graph.NewNode(common.Start(1))), p0(graph.NewNode(common.Parameter(0), start)), - end(graph.NewNode(common.End(), start)), + end(graph.NewNode(common.End(1), start)), osr_normal_entry(graph.NewNode(common.OsrNormalEntry(), start, start)), osr_loop_entry(graph.NewNode(common.OsrLoopEntry(), start, start)), self(graph.NewNode(common.Int32Constant(0xaabbccdd))) { @@ -165,30 +165,6 @@ TEST(Deconstruct_osr1) { } -TEST(Deconstruct_osr1_type) { - OsrDeconstructorTester T(1); - - Node* loop = T.NewOsrLoop(1); - Node* osr_phi = - T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant()); - Type* type = Type::Signed32(); - NodeProperties::SetBounds(osr_phi, Bounds(type, type)); - - Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, loop); - T.graph.SetEnd(ret); - - OsrHelper helper(0, 0); - helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone()); - - CHECK_EQ(type, NodeProperties::GetBounds(T.osr_values[0]).lower); - CHECK_EQ(type, NodeProperties::GetBounds(T.osr_values[0]).upper); - - CheckInputs(loop, T.start, loop); - CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop); - CheckInputs(ret, osr_phi, T.start, loop); -} - - TEST(Deconstruct_osr_remove_prologue) { OsrDeconstructorTester T(1); Diamond d(&T.graph, &T.common, T.p0); @@ -370,14 +346,14 @@ TEST(Deconstruct_osr_nested1) { Node* outer_phi = outer.Phi(T.p0, T.p0, nullptr); outer.branch->ReplaceInput(0, outer_phi); - Node* osr_phi = inner.Phi(T.jsgraph.OneConstant(), T.osr_values[0], - T.jsgraph.ZeroConstant()); + Node* osr_phi = inner.Phi(T.jsgraph.TrueConstant(), T.osr_values[0], + T.jsgraph.FalseConstant()); inner.branch->ReplaceInput(0, osr_phi); outer_phi->ReplaceInput(1, osr_phi); Node* ret = T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit); - Node* end = T.graph.NewNode(T.common.End(), ret); + Node* end = T.graph.NewNode(T.common.End(1), ret); T.graph.SetEnd(end); T.DeconstructOsr(); @@ -385,7 +361,7 @@ TEST(Deconstruct_osr_nested1) { // Check structure of deconstructed graph. // Check inner OSR loop is directly connected to start. CheckInputs(inner.loop, T.start, inner.if_true); - CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), inner.loop); + CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.FalseConstant(), inner.loop); // Check control transfer to copy of outer loop. Node* new_outer_loop = FindSuccessor(inner.exit, IrOpcode::kLoop); @@ -412,8 +388,8 @@ TEST(Deconstruct_osr_nested1) { Node* new_inner_loop = FindSuccessor(new_outer_if_true, IrOpcode::kLoop); Node* new_inner_phi = FindSuccessor(new_inner_loop, IrOpcode::kPhi); - CheckInputs(new_inner_phi, T.jsgraph.OneConstant(), T.jsgraph.ZeroConstant(), - new_inner_loop); + CheckInputs(new_inner_phi, T.jsgraph.TrueConstant(), + T.jsgraph.FalseConstant(), new_inner_loop); CheckInputs(new_outer_phi, osr_phi, new_inner_phi, new_outer_loop); } @@ -429,11 +405,11 @@ TEST(Deconstruct_osr_nested2) { Node* outer_phi = outer.Phi(T.p0, T.p0, T.p0); outer.branch->ReplaceInput(0, outer_phi); - Node* osr_phi = inner.Phi(T.jsgraph.OneConstant(), T.osr_values[0], - T.jsgraph.ZeroConstant()); + Node* osr_phi = inner.Phi(T.jsgraph.TrueConstant(), T.osr_values[0], + T.jsgraph.FalseConstant()); inner.branch->ReplaceInput(0, osr_phi); outer_phi->ReplaceInput(1, osr_phi); - outer_phi->ReplaceInput(2, T.jsgraph.ZeroConstant()); + outer_phi->ReplaceInput(2, T.jsgraph.FalseConstant()); Node* x_branch = T.graph.NewNode(T.common.Branch(), osr_phi, inner.exit); Node* x_true = T.graph.NewNode(T.common.IfTrue(), x_branch); @@ -444,7 +420,7 @@ TEST(Deconstruct_osr_nested2) { Node* ret = T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit); - Node* end = T.graph.NewNode(T.common.End(), ret); + Node* end = T.graph.NewNode(T.common.End(1), ret); T.graph.SetEnd(end); T.DeconstructOsr(); @@ -452,7 +428,7 @@ TEST(Deconstruct_osr_nested2) { // Check structure of deconstructed graph. // Check inner OSR loop is directly connected to start. CheckInputs(inner.loop, T.start, inner.if_true); - CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), inner.loop); + CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.FalseConstant(), inner.loop); // Check control transfer to copy of outer loop. Node* new_merge = FindSuccessor(x_true, IrOpcode::kMerge); @@ -465,7 +441,7 @@ TEST(Deconstruct_osr_nested2) { CHECK_NE(new_outer_phi, outer_phi); Node* new_entry_phi = FindSuccessor(new_merge, IrOpcode::kPhi); - CheckInputs(new_entry_phi, osr_phi, T.jsgraph.ZeroConstant(), new_merge); + CheckInputs(new_entry_phi, osr_phi, T.jsgraph.FalseConstant(), new_merge); CHECK_EQ(new_merge, new_outer_loop->InputAt(0)); @@ -486,10 +462,10 @@ TEST(Deconstruct_osr_nested2) { Node* new_inner_loop = FindSuccessor(new_outer_if_true, IrOpcode::kLoop); Node* new_inner_phi = FindSuccessor(new_inner_loop, IrOpcode::kPhi); - CheckInputs(new_inner_phi, T.jsgraph.OneConstant(), T.jsgraph.ZeroConstant(), - new_inner_loop); + CheckInputs(new_inner_phi, T.jsgraph.TrueConstant(), + T.jsgraph.FalseConstant(), new_inner_loop); CheckInputs(new_outer_phi, new_entry_phi, new_inner_phi, - T.jsgraph.ZeroConstant(), new_outer_loop); + T.jsgraph.FalseConstant(), new_outer_loop); } @@ -523,8 +499,8 @@ TEST(Deconstruct_osr_nested3) { // middle loop. Node* loop1 = T.graph.NewNode(T.common.Loop(2), loop0.if_true, T.self); loop1->ReplaceInput(0, loop0.if_true); - Node* loop1_phi = - T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), loop0_cntr, loop0_cntr); + Node* loop1_phi = T.graph.NewNode(T.common.Phi(kMachAnyTagged, 2), loop0_cntr, + loop0_cntr, loop1); // innermost (OSR) loop. While loop2(T, T.p0, true, 1); @@ -549,7 +525,7 @@ TEST(Deconstruct_osr_nested3) { Node* ret = T.graph.NewNode(T.common.Return(), loop0_cntr, T.start, loop0.exit); - Node* end = T.graph.NewNode(T.common.End(), ret); + Node* end = T.graph.NewNode(T.common.End(1), ret); T.graph.SetEnd(end); T.DeconstructOsr(); diff --git a/deps/v8/test/cctest/compiler/test-pipeline.cc b/deps/v8/test/cctest/compiler/test-pipeline.cc index b67af6ecf7..84550d502a 100644 --- a/deps/v8/test/cctest/compiler/test-pipeline.cc +++ b/deps/v8/test/cctest/compiler/test-pipeline.cc @@ -5,23 +5,18 @@ #include "src/v8.h" #include "test/cctest/cctest.h" -#include "src/ast-numbering.h" #include "src/compiler.h" #include "src/compiler/pipeline.h" #include "src/handles.h" #include "src/parser.h" -#include "src/rewriter.h" -#include "src/scopes.h" using namespace v8::internal; using namespace v8::internal::compiler; -TEST(PipelineAdd) { - HandleAndZoneScope handles; - const char* source = "(function(a,b) { return a + b; })"; +static void RunPipeline(Zone* zone, const char* source) { Handle<JSFunction> function = v8::Utils::OpenHandle( *v8::Handle<v8::Function>::Cast(CompileRun(source))); - ParseInfo parse_info(handles.main_zone(), function); + ParseInfo parse_info(zone, function); CHECK(Compiler::ParseAndAnalyze(&parse_info)); CompilationInfo info(&parse_info); @@ -34,3 +29,17 @@ TEST(PipelineAdd) { USE(pipeline); #endif } + + +TEST(PipelineTyped) { + HandleAndZoneScope handles; + FLAG_turbo_types = true; + RunPipeline(handles.main_zone(), "(function(a,b) { return a + b; })"); +} + + +TEST(PipelineGeneric) { + HandleAndZoneScope handles; + FLAG_turbo_types = false; + RunPipeline(handles.main_zone(), "(function(a,b) { return a + b; })"); +} diff --git a/deps/v8/test/cctest/compiler/test-representation-change.cc b/deps/v8/test/cctest/compiler/test-representation-change.cc index 55f054a74b..216f9fd847 100644 --- a/deps/v8/test/cctest/compiler/test-representation-change.cc +++ b/deps/v8/test/cctest/compiler/test-representation-change.cc @@ -69,7 +69,7 @@ class RepresentationChangerTester : public HandleAndZoneScope, } void CheckHeapConstant(Node* n, HeapObject* expected) { - HeapObjectMatcher<HeapObject> m(n); + HeapObjectMatcher m(n); CHECK(m.HasValue()); CHECK_EQ(expected, *m.Value().handle()); } @@ -100,9 +100,9 @@ class RepresentationChangerTester : public HandleAndZoneScope, CHECK_EQ(n, c); } }; -} -} -} // namespace v8::internal::compiler +} // namespace compiler +} // namespace internal +} // namespace v8 static const MachineType all_reps[] = {kRepBit, kRepWord32, kRepWord64, diff --git a/deps/v8/test/cctest/compiler/test-run-deopt.cc b/deps/v8/test/cctest/compiler/test-run-deopt.cc index 14c024cdbc..d895924324 100644 --- a/deps/v8/test/cctest/compiler/test-run-deopt.cc +++ b/deps/v8/test/cctest/compiler/test-run-deopt.cc @@ -7,13 +7,12 @@ #include "test/cctest/cctest.h" #include "test/cctest/compiler/function-tester.h" -using namespace v8; using namespace v8::internal; using namespace v8::internal::compiler; #if V8_TURBOFAN_TARGET -static void IsOptimized(const FunctionCallbackInfo<v8::Value>& args) { +static void IsOptimized(const v8::FunctionCallbackInfo<v8::Value>& args) { JavaScriptFrameIterator it(CcTest::i_isolate()); JavaScriptFrame* frame = it.frame(); return args.GetReturnValue().Set(frame->is_optimized()); @@ -21,56 +20,99 @@ static void IsOptimized(const FunctionCallbackInfo<v8::Value>& args) { static void InstallIsOptimizedHelper(v8::Isolate* isolate) { - Local<v8::Context> context = isolate->GetCurrentContext(); - Local<v8::FunctionTemplate> t = FunctionTemplate::New(isolate, IsOptimized); + v8::Local<v8::Context> context = isolate->GetCurrentContext(); + v8::Local<v8::FunctionTemplate> t = + v8::FunctionTemplate::New(isolate, IsOptimized); context->Global()->Set(v8_str("IsOptimized"), t->GetFunction()); } -TEST(TurboSimpleDeopt) { +TEST(DeoptSimple) { FLAG_allow_natives_syntax = true; - FLAG_turbo_deoptimization = true; FunctionTester T( "(function f(a) {" - "var b = 1;" - "if (!IsOptimized()) return 0;" - "%DeoptimizeFunction(f);" - "if (IsOptimized()) return 0;" - "return a + b; })"); + " var b = 1;" + " if (!IsOptimized()) return 0;" + " %DeoptimizeFunction(f);" + " if (IsOptimized()) return 0;" + " return a + b;" + "})"); InstallIsOptimizedHelper(CcTest::isolate()); T.CheckCall(T.Val(2), T.Val(1)); } -TEST(TurboSimpleDeoptInExpr) { +TEST(DeoptSimpleInExpr) { FLAG_allow_natives_syntax = true; - FLAG_turbo_deoptimization = true; FunctionTester T( "(function f(a) {" - "var b = 1;" - "var c = 2;" - "if (!IsOptimized()) return 0;" - "var d = b + (%DeoptimizeFunction(f), c);" - "if (IsOptimized()) return 0;" - "return d + a; })"); + " var b = 1;" + " var c = 2;" + " if (!IsOptimized()) return 0;" + " var d = b + (%DeoptimizeFunction(f), c);" + " if (IsOptimized()) return 0;" + " return d + a;" + "})"); InstallIsOptimizedHelper(CcTest::isolate()); T.CheckCall(T.Val(6), T.Val(3)); } + +TEST(DeoptExceptionHandlerCatch) { + FLAG_allow_natives_syntax = true; + FLAG_turbo_try_catch = true; + + FunctionTester T( + "(function f() {" + " var is_opt = IsOptimized;" + " try {" + " DeoptAndThrow(f);" + " } catch (e) {" + " return is_opt();" + " }" + "})"); + + CompileRun("function DeoptAndThrow(f) { %DeoptimizeFunction(f); throw 0; }"); + InstallIsOptimizedHelper(CcTest::isolate()); + T.CheckCall(T.false_value()); +} + + +TEST(DeoptExceptionHandlerFinally) { + FLAG_allow_natives_syntax = true; + FLAG_turbo_try_finally = true; + + FunctionTester T( + "(function f() {" + " var is_opt = IsOptimized;" + " try {" + " DeoptAndThrow(f);" + " } finally {" + " return is_opt();" + " }" + "})"); + + CompileRun("function DeoptAndThrow(f) { %DeoptimizeFunction(f); throw 0; }"); + InstallIsOptimizedHelper(CcTest::isolate()); +#if 0 // TODO(4195,mstarzinger): Reproduces on MIPS64, re-enable once fixed. + T.CheckCall(T.false_value()); +#endif +} + #endif -TEST(TurboTrivialDeopt) { +TEST(DeoptTrivial) { FLAG_allow_natives_syntax = true; - FLAG_turbo_deoptimization = true; FunctionTester T( "(function foo() {" - "%DeoptimizeFunction(foo);" - "return 1; })"); + " %DeoptimizeFunction(foo);" + " return 1;" + "})"); T.CheckCall(T.Val(1)); } diff --git a/deps/v8/test/cctest/compiler/test-run-inlining.cc b/deps/v8/test/cctest/compiler/test-run-inlining.cc index a6d76e4d57..7f8ae25619 100644 --- a/deps/v8/test/cctest/compiler/test-run-inlining.cc +++ b/deps/v8/test/cctest/compiler/test-run-inlining.cc @@ -13,7 +13,7 @@ using namespace v8::internal::compiler; namespace { -// Helper to determine inline count via JavaScriptFrame::GetInlineCount. +// Helper to determine inline count via JavaScriptFrame::GetFunctions. // Note that a count of 1 indicates that no inlining has occured. void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) { StackTraceFrameIterator it(CcTest::i_isolate()); @@ -21,14 +21,17 @@ void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) { JavaScriptFrame* topmost = it.frame(); while (!it.done()) { JavaScriptFrame* frame = it.frame(); + List<JSFunction*> functions(2); + frame->GetFunctions(&functions); PrintF("%d %s, inline count: %d\n", frames_seen, frame->function()->shared()->DebugName()->ToCString().get(), - frame->GetInlineCount()); + functions.length()); frames_seen++; it.Advance(); } - CHECK_EQ(args[0]->ToInt32(args.GetIsolate())->Value(), - topmost->GetInlineCount()); + List<JSFunction*> functions(2); + topmost->GetFunctions(&functions); + CHECK_EQ(args[0]->ToInt32(args.GetIsolate())->Value(), functions.length()); } @@ -40,9 +43,8 @@ void InstallAssertInlineCountHelper(v8::Isolate* isolate) { } -const uint32_t kBuiltinInlineFlags = CompilationInfo::kBuiltinInliningEnabled | - CompilationInfo::kContextSpecializing | - CompilationInfo::kTypingEnabled; +const uint32_t kRestrictedInliningFlags = + CompilationInfo::kContextSpecializing | CompilationInfo::kTypingEnabled; const uint32_t kInlineFlags = CompilationInfo::kInliningEnabled | CompilationInfo::kContextSpecializing | @@ -52,7 +54,6 @@ const uint32_t kInlineFlags = CompilationInfo::kInliningEnabled | TEST(SimpleInlining) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function(){" " function foo(s) { AssertInlineCount(2); return s; };" @@ -67,7 +68,6 @@ TEST(SimpleInlining) { TEST(SimpleInliningDeopt) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function(){" " function foo(s) { %DeoptimizeFunction(bar); return s; };" @@ -81,8 +81,21 @@ TEST(SimpleInliningDeopt) { } +TEST(SimpleInliningDeoptSelf) { + FunctionTester T( + "(function(){" + " function foo(s) { %_DeoptimizeNow(); return s; };" + " function bar(s, t) { return foo(s); };" + " return bar;" + "})();", + kInlineFlags); + + InstallAssertInlineCountHelper(CcTest::isolate()); + T.CheckCall(T.Val(1), T.Val(1), T.Val(2)); +} + + TEST(SimpleInliningContext) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s) { AssertInlineCount(2); var x = 12; return s + x; };" @@ -97,7 +110,6 @@ TEST(SimpleInliningContext) { TEST(SimpleInliningContextDeopt) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s) {" @@ -115,7 +127,6 @@ TEST(SimpleInliningContextDeopt) { TEST(CaptureContext) { - FLAG_turbo_deoptimization = true; FunctionTester T( "var f = (function () {" " var x = 42;" @@ -133,7 +144,6 @@ TEST(CaptureContext) { // TODO(sigurds) For now we do not inline any native functions. If we do at // some point, change this test. TEST(DontInlineEval) { - FLAG_turbo_deoptimization = true; FunctionTester T( "var x = 42;" "(function () {" @@ -148,7 +158,6 @@ TEST(DontInlineEval) { TEST(InlineOmitArguments) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 42;" @@ -163,7 +172,6 @@ TEST(InlineOmitArguments) { TEST(InlineOmitArgumentsDeopt) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s,t,u,v) { AssertInlineCount(2);" @@ -181,7 +189,6 @@ TEST(InlineOmitArgumentsDeopt) { TEST(InlineSurplusArguments) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 42;" @@ -197,7 +204,6 @@ TEST(InlineSurplusArguments) { TEST(InlineSurplusArgumentsDeopt) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s) { AssertInlineCount(2); %DeoptimizeFunction(bar);" @@ -217,7 +223,6 @@ TEST(InlineSurplusArgumentsDeopt) { TEST(InlineTwice) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 42;" @@ -232,7 +237,6 @@ TEST(InlineTwice) { TEST(InlineTwiceDependent) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 42;" @@ -248,7 +252,6 @@ TEST(InlineTwiceDependent) { TEST(InlineTwiceDependentDiamond) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 41;" @@ -265,7 +268,6 @@ TEST(InlineTwiceDependentDiamond) { TEST(InlineTwiceDependentDiamondDifferent) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 41;" @@ -282,7 +284,6 @@ TEST(InlineTwiceDependentDiamondDifferent) { TEST(InlineLoopGuardedEmpty) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s) { AssertInlineCount(2); if (s) while (s); return s; };" @@ -297,7 +298,6 @@ TEST(InlineLoopGuardedEmpty) { TEST(InlineLoopGuardedOnce) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s,t) { AssertInlineCount(2); if (t > 0) while (s > 0) {" @@ -313,7 +313,6 @@ TEST(InlineLoopGuardedOnce) { TEST(InlineLoopGuardedTwice) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s,t) { AssertInlineCount(2); if (t > 0) while (s > 0) {" @@ -329,7 +328,6 @@ TEST(InlineLoopGuardedTwice) { TEST(InlineLoopUnguardedEmpty) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s) { AssertInlineCount(2); while (s); return s; };" @@ -344,7 +342,6 @@ TEST(InlineLoopUnguardedEmpty) { TEST(InlineLoopUnguardedOnce) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s) { AssertInlineCount(2); while (s) {" @@ -360,7 +357,6 @@ TEST(InlineLoopUnguardedOnce) { TEST(InlineLoopUnguardedTwice) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s) { AssertInlineCount(2); while (s > 0) {" @@ -376,7 +372,6 @@ TEST(InlineLoopUnguardedTwice) { TEST(InlineStrictIntoNonStrict) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = Object.create({}, { y: { value:42, writable:false } });" @@ -393,7 +388,6 @@ TEST(InlineStrictIntoNonStrict) { TEST(InlineNonStrictIntoStrict) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = Object.create({}, { y: { value:42, writable:false } });" @@ -409,7 +403,6 @@ TEST(InlineNonStrictIntoStrict) { TEST(InlineIntrinsicIsSmi) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 42;" @@ -424,7 +417,6 @@ TEST(InlineIntrinsicIsSmi) { TEST(InlineIntrinsicIsNonNegativeSmi) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = 42;" @@ -439,7 +431,6 @@ TEST(InlineIntrinsicIsNonNegativeSmi) { TEST(InlineIntrinsicIsArray) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " var x = [1,2,3];" @@ -474,7 +465,6 @@ TEST(InlineIntrinsicIsArray) { TEST(InlineWithArguments) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s,t,u) { AssertInlineCount(2);" @@ -494,15 +484,14 @@ TEST(InlineWithArguments) { TEST(InlineBuiltin) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s,t,u) { AssertInlineCount(2); return true; }" " function bar() { return foo(); };" - " %SetInlineBuiltinFlag(foo);" + " %SetForceInlineFlag(foo);" " return bar;" "})();", - kBuiltinInlineFlags); + kRestrictedInliningFlags); InstallAssertInlineCountHelper(CcTest::isolate()); T.CheckCall(T.true_value()); @@ -510,20 +499,80 @@ TEST(InlineBuiltin) { TEST(InlineNestedBuiltin) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function () {" " function foo(s,t,u) { AssertInlineCount(3); return true; }" " function baz(s,t,u) { return foo(s,t,u); }" " function bar() { return baz(); };" - " %SetInlineBuiltinFlag(foo);" - " %SetInlineBuiltinFlag(baz);" + " %SetForceInlineFlag(foo);" + " %SetForceInlineFlag(baz);" " return bar;" "})();", - kBuiltinInlineFlags); + kRestrictedInliningFlags); InstallAssertInlineCountHelper(CcTest::isolate()); T.CheckCall(T.true_value()); } + +TEST(StrongModeArity) { + FLAG_strong_mode = true; + FunctionTester T( + "(function () {" + " function foo(x, y) { 'use strong'; return x; }" + " function bar(x, y) { return foo(x); }" + " return bar;" + "})();", + kInlineFlags); + T.CheckThrows(T.undefined(), T.undefined()); +} + + +TEST(StrongModeArityOuter) { + FLAG_strong_mode = true; + FunctionTester T( + "(function () {" + " 'use strong';" + " function foo(x, y) { return x; }" + " function bar(x, y) { return foo(x); }" + " return bar;" + "})();", + kInlineFlags); + T.CheckThrows(T.undefined(), T.undefined()); +} + + +TEST(InlineSelfRecursive) { + FunctionTester T( + "(function () {" + " function foo(x) { " + " AssertInlineCount(1);" + " if (x == 1) return foo(12);" + " return x;" + " }" + " return foo;" + "})();", + kInlineFlags); + + InstallAssertInlineCountHelper(CcTest::isolate()); + T.CheckCall(T.Val(12), T.Val(1)); +} + + +TEST(InlineMutuallyRecursive) { + FunctionTester T( + "(function () {" + " function bar(x) { AssertInlineCount(2); return foo(x); }" + " function foo(x) { " + " if (x == 1) return bar(42);" + " return x;" + " }" + " return foo;" + "})();", + kInlineFlags); + + InstallAssertInlineCountHelper(CcTest::isolate()); + T.CheckCall(T.Val(42), T.Val(1)); +} + #endif // V8_TURBOFAN_TARGET diff --git a/deps/v8/test/cctest/compiler/test-run-intrinsics.cc b/deps/v8/test/cctest/compiler/test-run-intrinsics.cc index 7fc5cc9758..1fa37748c6 100644 --- a/deps/v8/test/cctest/compiler/test-run-intrinsics.cc +++ b/deps/v8/test/cctest/compiler/test-run-intrinsics.cc @@ -12,7 +12,6 @@ uint32_t flags = CompilationInfo::kInliningEnabled; TEST(CallFunction) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_CallFunction(a, 1, 2, 3, b); })", flags); CompileRun("function f(a,b,c) { return a + b + c + this.d; }"); @@ -23,7 +22,6 @@ TEST(CallFunction) { TEST(ClassOf) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_ClassOf(a); })", flags); T.CheckCall(T.Val("Function"), T.NewObject("(function() {})")); @@ -38,7 +36,6 @@ TEST(ClassOf) { TEST(HeapObjectGetMap) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_HeapObjectGetMap(a); })", flags); Factory* factory = T.main_isolate()->factory(); @@ -58,7 +55,6 @@ static int* LookupCounter(const char* name) { TEST(IncrementStatsCounter) { - FLAG_turbo_deoptimization = true; FLAG_native_code_counters = true; reinterpret_cast<v8::Isolate*>(CcTest::InitIsolateOnce()) ->SetCounterFunction(LookupCounter); @@ -76,9 +72,9 @@ TEST(IncrementStatsCounter) { TEST(IsArray) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_IsArray(a); })", flags); + T.CheckFalse(T.NewObject("new Date()")); T.CheckFalse(T.NewObject("(function() {})")); T.CheckTrue(T.NewObject("([1])")); T.CheckFalse(T.NewObject("({})")); @@ -90,10 +86,25 @@ TEST(IsArray) { } +TEST(IsDate) { + FunctionTester T("(function(a) { return %_IsDate(a); })", flags); + + T.CheckTrue(T.NewObject("new Date()")); + T.CheckFalse(T.NewObject("(function() {})")); + T.CheckFalse(T.NewObject("([1])")); + T.CheckFalse(T.NewObject("({})")); + T.CheckFalse(T.NewObject("(/x/)")); + T.CheckFalse(T.undefined()); + T.CheckFalse(T.null()); + T.CheckFalse(T.Val("x")); + T.CheckFalse(T.Val(1)); +} + + TEST(IsFunction) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_IsFunction(a); })", flags); + T.CheckFalse(T.NewObject("new Date()")); T.CheckTrue(T.NewObject("(function() {})")); T.CheckFalse(T.NewObject("([1])")); T.CheckFalse(T.NewObject("({})")); @@ -106,7 +117,6 @@ TEST(IsFunction) { TEST(IsMinusZero) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_IsMinusZero(a); })", flags); T.CheckFalse(T.Val(1)); @@ -119,7 +129,6 @@ TEST(IsMinusZero) { TEST(IsNonNegativeSmi) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_IsNonNegativeSmi(a); })", flags); T.CheckTrue(T.Val(1)); @@ -132,7 +141,6 @@ TEST(IsNonNegativeSmi) { TEST(IsObject) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_IsObject(a); })", flags); T.CheckFalse(T.NewObject("(function() {})")); @@ -147,9 +155,9 @@ TEST(IsObject) { TEST(IsRegExp) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_IsRegExp(a); })", flags); + T.CheckFalse(T.NewObject("new Date()")); T.CheckFalse(T.NewObject("(function() {})")); T.CheckFalse(T.NewObject("([1])")); T.CheckFalse(T.NewObject("({})")); @@ -162,20 +170,23 @@ TEST(IsRegExp) { TEST(IsSmi) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_IsSmi(a); })", flags); + T.CheckFalse(T.NewObject("new Date()")); + T.CheckFalse(T.NewObject("(function() {})")); + T.CheckFalse(T.NewObject("([1])")); + T.CheckFalse(T.NewObject("({})")); + T.CheckFalse(T.NewObject("(/x/)")); + T.CheckFalse(T.undefined()); T.CheckTrue(T.Val(1)); T.CheckFalse(T.Val(1.1)); T.CheckFalse(T.Val(-0.0)); T.CheckTrue(T.Val(-2)); T.CheckFalse(T.Val(-2.3)); - T.CheckFalse(T.undefined()); } TEST(MapGetInstanceType) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function(a) { return %_MapGetInstanceType(%_HeapObjectGetMap(a)); })", flags); @@ -189,7 +200,6 @@ TEST(MapGetInstanceType) { TEST(ObjectEquals) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_ObjectEquals(a,b); })", flags); CompileRun("var o = {}"); @@ -203,7 +213,6 @@ TEST(ObjectEquals) { TEST(OneByteSeqStringGetChar) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_OneByteSeqStringGetChar(a,b); })", flags); @@ -219,7 +228,6 @@ TEST(OneByteSeqStringGetChar) { TEST(OneByteSeqStringSetChar) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { %_OneByteSeqStringSetChar(a,88,b); })", flags); @@ -236,7 +244,6 @@ TEST(OneByteSeqStringSetChar) { TEST(NewConsString) { - FLAG_turbo_deoptimization = true; FunctionTester T( "(function() { " " return %_NewConsString(14, true, 'abcdefghi', 'jklmn');" @@ -248,7 +255,6 @@ TEST(NewConsString) { TEST(SetValueOf) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_SetValueOf(a,b); })", flags); T.CheckCall(T.Val("a"), T.NewObject("(new String)"), T.Val("a")); @@ -258,7 +264,6 @@ TEST(SetValueOf) { TEST(StringAdd) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_StringAdd(a,b); })", flags); T.CheckCall(T.Val("aaabbb"), T.Val("aaa"), T.Val("bbb")); @@ -268,7 +273,6 @@ TEST(StringAdd) { TEST(StringCharAt) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_StringCharAt(a,b); })", flags); T.CheckCall(T.Val("e"), T.Val("huge fan!"), T.Val(3)); @@ -278,7 +282,6 @@ TEST(StringCharAt) { TEST(StringCharCodeAt) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_StringCharCodeAt(a,b); })", flags); @@ -289,7 +292,6 @@ TEST(StringCharCodeAt) { TEST(StringCharFromCode) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_StringCharFromCode(a); })", flags); T.CheckCall(T.Val("a"), T.Val(97)); @@ -299,7 +301,6 @@ TEST(StringCharFromCode) { TEST(StringCompare) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_StringCompare(a,b); })", flags); T.CheckCall(T.Val(-1), T.Val("aaa"), T.Val("bbb")); @@ -309,7 +310,6 @@ TEST(StringCompare) { TEST(SubString) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_SubString(a,b,b+3); })", flags); T.CheckCall(T.Val("aaa"), T.Val("aaabbb"), T.Val(0.0)); @@ -319,7 +319,6 @@ TEST(SubString) { TEST(TwoByteSeqStringGetChar) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { return %_TwoByteSeqStringGetChar(a,b); })", flags); @@ -335,7 +334,6 @@ TEST(TwoByteSeqStringGetChar) { TEST(TwoByteSeqStringSetChar) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a,b) { %_TwoByteSeqStringSetChar(a,88,b); })", flags); @@ -352,7 +350,6 @@ TEST(TwoByteSeqStringSetChar) { TEST(ValueOf) { - FLAG_turbo_deoptimization = true; FunctionTester T("(function(a) { return %_ValueOf(a); })", flags); T.CheckCall(T.Val("a"), T.Val("a")); diff --git a/deps/v8/test/cctest/compiler/test-run-jscalls.cc b/deps/v8/test/cctest/compiler/test-run-jscalls.cc index a622af8995..8de2d7a214 100644 --- a/deps/v8/test/cctest/compiler/test-run-jscalls.cc +++ b/deps/v8/test/cctest/compiler/test-run-jscalls.cc @@ -242,6 +242,7 @@ TEST(ContextLoadedFromActivation) { i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value); i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun); jsfun->set_code(T.function->code()); + jsfun->set_shared(T.function->shared()); context->Global()->Set(v8_str("foo"), v8::Utils::ToLocal(jsfun)); CompileRun("var x = 24;"); ExpectInt32("foo();", 24); @@ -263,6 +264,7 @@ TEST(BuiltinLoadedFromActivation) { i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value); i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun); jsfun->set_code(T.function->code()); + jsfun->set_shared(T.function->shared()); context->Global()->Set(v8_str("foo"), v8::Utils::ToLocal(jsfun)); CompileRun("var x = 24;"); ExpectObject("foo()", context->Global()); diff --git a/deps/v8/test/cctest/compiler/test-run-jsexceptions.cc b/deps/v8/test/cctest/compiler/test-run-jsexceptions.cc index 2e2e10e9de..0e1977b720 100644 --- a/deps/v8/test/cctest/compiler/test-run-jsexceptions.cc +++ b/deps/v8/test/cctest/compiler/test-run-jsexceptions.cc @@ -10,19 +10,14 @@ using namespace v8::internal; using namespace v8::internal::compiler; TEST(Throw) { - i::FLAG_turbo_exceptions = true; FunctionTester T("(function(a,b) { if (a) { throw b; } else { return b; }})"); -// TODO(mstarzinger) -#if 0 T.CheckThrows(T.true_value(), T.NewObject("new Error")); -#endif T.CheckCall(T.Val(23), T.false_value(), T.Val(23)); } TEST(ThrowMessagePosition) { - i::FLAG_turbo_exceptions = true; static const char* src = "(function(a, b) { \n" " if (a == 1) throw 1; \n" @@ -48,7 +43,6 @@ TEST(ThrowMessagePosition) { TEST(ThrowMessageDirectly) { - i::FLAG_turbo_exceptions = true; static const char* src = "(function(a, b) {" " if (a) { throw b; } else { throw new Error(b); }" @@ -56,19 +50,17 @@ TEST(ThrowMessageDirectly) { FunctionTester T(src); v8::Handle<v8::Message> message; -// TODO(mstarzinger) -#if 0 message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?")); CHECK(message->Get()->Equals(v8_str("Uncaught Error: Wat?"))); message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!")); CHECK(message->Get()->Equals(v8_str("Uncaught Kaboom!"))); -#endif } TEST(ThrowMessageIndirectly) { - i::FLAG_turbo_exceptions = true; + i::FLAG_turbo_try_catch = true; + i::FLAG_turbo_try_finally = true; static const char* src = "(function(a, b) {" " try {" @@ -80,23 +72,16 @@ TEST(ThrowMessageIndirectly) { FunctionTester T(src); v8::Handle<v8::Message> message; -// TODO(mstarzinger) -#if 0 message = T.CheckThrowsReturnMessage(T.false_value(), T.Val("Wat?")); CHECK(message->Get()->Equals(v8_str("Uncaught Error: Wat?"))); message = T.CheckThrowsReturnMessage(T.true_value(), T.Val("Kaboom!")); CHECK(message->Get()->Equals(v8_str("Uncaught Kaboom!"))); -#endif } -// TODO(mstarzinger): Increase test coverage by having similar tests within the -// mjsunit suite to also test integration with other components (e.g. OSR). - - TEST(Catch) { - i::FLAG_turbo_exceptions = true; + i::FLAG_turbo_try_catch = true; const char* src = "(function(a,b) {" " var r = '-';" @@ -115,7 +100,7 @@ TEST(Catch) { TEST(CatchNested) { - i::FLAG_turbo_exceptions = true; + i::FLAG_turbo_try_catch = true; const char* src = "(function(a,b) {" " var r = '-';" @@ -139,7 +124,7 @@ TEST(CatchNested) { TEST(CatchBreak) { - i::FLAG_turbo_exceptions = true; + i::FLAG_turbo_try_catch = true; const char* src = "(function(a,b) {" " var r = '-';" @@ -164,7 +149,7 @@ TEST(CatchBreak) { TEST(CatchCall) { - i::FLAG_turbo_exceptions = true; + i::FLAG_turbo_try_catch = true; const char* src = "(function(fun) {" " var r = '-';" @@ -186,7 +171,7 @@ TEST(CatchCall) { TEST(Finally) { - i::FLAG_turbo_exceptions = true; + i::FLAG_turbo_try_finally = true; const char* src = "(function(a,b) {" " var r = '-';" @@ -204,7 +189,7 @@ TEST(Finally) { TEST(FinallyBreak) { - i::FLAG_turbo_exceptions = true; + i::FLAG_turbo_try_finally = true; const char* src = "(function(a,b) {" " var r = '-';" @@ -228,8 +213,7 @@ TEST(FinallyBreak) { TEST(DeoptTry) { - i::FLAG_turbo_exceptions = true; - i::FLAG_turbo_deoptimization = true; + i::FLAG_turbo_try_catch = true; const char* src = "(function f(a) {" " try {" @@ -246,8 +230,7 @@ TEST(DeoptTry) { TEST(DeoptCatch) { - i::FLAG_turbo_exceptions = true; - i::FLAG_turbo_deoptimization = true; + i::FLAG_turbo_try_catch = true; const char* src = "(function f(a) {" " try {" @@ -264,8 +247,7 @@ TEST(DeoptCatch) { TEST(DeoptFinallyReturn) { - i::FLAG_turbo_exceptions = true; - i::FLAG_turbo_deoptimization = true; + i::FLAG_turbo_try_finally = true; const char* src = "(function f(a) {" " try {" @@ -282,8 +264,7 @@ TEST(DeoptFinallyReturn) { TEST(DeoptFinallyReThrow) { - i::FLAG_turbo_exceptions = true; - i::FLAG_turbo_deoptimization = true; + i::FLAG_turbo_try_finally = true; const char* src = "(function f(a) {" " try {" diff --git a/deps/v8/test/cctest/compiler/test-run-jsops.cc b/deps/v8/test/cctest/compiler/test-run-jsops.cc index 032db82db3..56ac31cbc9 100644 --- a/deps/v8/test/cctest/compiler/test-run-jsops.cc +++ b/deps/v8/test/cctest/compiler/test-run-jsops.cc @@ -523,9 +523,7 @@ TEST(RegExpLiteral) { TEST(ClassLiteral) { - FLAG_harmony_classes = true; FLAG_harmony_sloppy = true; - FLAG_harmony_object_literals = true; const char* src = "(function(a,b) {" " class C {" diff --git a/deps/v8/test/cctest/compiler/test-run-machops.cc b/deps/v8/test/cctest/compiler/test-run-machops.cc index 8d051bc90b..b1fc36968f 100644 --- a/deps/v8/test/cctest/compiler/test-run-machops.cc +++ b/deps/v8/test/cctest/compiler/test-run-machops.cc @@ -82,6 +82,63 @@ TEST(CodeGenInt32Binop) { } +#if V8_TURBOFAN_BACKEND_64 +static Node* Int64Input(RawMachineAssemblerTester<int64_t>* m, int index) { + switch (index) { + case 0: + return m->Parameter(0); + case 1: + return m->Parameter(1); + case 2: + return m->Int64Constant(0); + case 3: + return m->Int64Constant(1); + case 4: + return m->Int64Constant(-1); + case 5: + return m->Int64Constant(0xff); + case 6: + return m->Int64Constant(0x0123456789abcdefLL); + case 7: + return m->Load(kMachInt64, m->PointerConstant(NULL)); + default: + return NULL; + } +} + + +TEST(CodeGenInt64Binop) { + RawMachineAssemblerTester<void> m; + + const Operator* kOps[] = { + m.machine()->Word64And(), m.machine()->Word64Or(), + m.machine()->Word64Xor(), m.machine()->Word64Shl(), + m.machine()->Word64Shr(), m.machine()->Word64Sar(), + m.machine()->Word64Equal(), m.machine()->Int64Add(), + m.machine()->Int64Sub(), m.machine()->Int64Mul(), m.machine()->Int64Div(), + m.machine()->Uint64Div(), m.machine()->Int64Mod(), + m.machine()->Uint64Mod(), m.machine()->Int64LessThan(), + m.machine()->Int64LessThanOrEqual(), m.machine()->Uint64LessThan(), + m.machine()->Uint64LessThanOrEqual()}; + + for (size_t i = 0; i < arraysize(kOps); ++i) { + for (int j = 0; j < 8; j++) { + for (int k = 0; k < 8; k++) { + RawMachineAssemblerTester<int64_t> m(kMachInt64, kMachInt64); + Node* a = Int64Input(&m, j); + Node* b = Int64Input(&m, k); + m.Return(m.NewNode(kOps[i], a, b)); + m.GenerateCode(); + } + } + } +} + + +// TODO(titzer): add tests that run 64-bit integer operations. +#endif // V8_TURBOFAN_BACKEND_64 + + TEST(RunGoto) { RawMachineAssemblerTester<int32_t> m; int constant = 99999; @@ -164,15 +221,14 @@ template <typename R> static void BuildDiamondPhi(RawMachineAssemblerTester<R>* m, Node* cond_node, MachineType type, Node* true_node, Node* false_node) { - MLabel blocka, blockb; - MLabel* end = m->Exit(); + MLabel blocka, blockb, end; m->Branch(cond_node, &blocka, &blockb); m->Bind(&blocka); - m->Goto(end); + m->Goto(&end); m->Bind(&blockb); - m->Goto(end); + m->Goto(&end); - m->Bind(end); + m->Bind(&end); Node* phi = m->Phi(type, true_node, false_node); m->Return(phi); } @@ -237,16 +293,15 @@ TEST(RunLoopPhiConst) { Node* false_node = m.Int32Constant(false_val); // x = false_val; while(false) { x = true_val; } return x; - MLabel body, header; - MLabel* end = m.Exit(); + MLabel body, header, end; m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(kMachInt32, false_node, true_node); - m.Branch(cond_node, &body, end); + m.Branch(cond_node, &body, &end); m.Bind(&body); m.Goto(&header); - m.Bind(end); + m.Bind(&end); m.Return(phi); CHECK_EQ(false_val, m.Call()); @@ -256,20 +311,19 @@ TEST(RunLoopPhiConst) { TEST(RunLoopPhiParam) { RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32, kMachInt32); - MLabel blocka, blockb; - MLabel* end = m.Exit(); + MLabel blocka, blockb, end; m.Goto(&blocka); m.Bind(&blocka); Node* phi = m.Phi(kMachInt32, m.Parameter(1), m.Parameter(2)); Node* cond = m.Phi(kMachInt32, m.Parameter(0), m.Int32Constant(0)); - m.Branch(cond, &blockb, end); + m.Branch(cond, &blockb, &end); m.Bind(&blockb); m.Goto(&blocka); - m.Bind(end); + m.Bind(&end); m.Return(phi); int32_t c1 = 0xa81903b4; @@ -287,22 +341,21 @@ TEST(RunLoopPhiInduction) { int false_val = 0x10777; // x = false_val; while(false) { x++; } return x; - MLabel header, body; - MLabel* end = m.Exit(); + MLabel header, body, end; Node* false_node = m.Int32Constant(false_val); m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(kMachInt32, false_node, false_node); - m.Branch(m.Int32Constant(0), &body, end); + m.Branch(m.Int32Constant(0), &body, &end); m.Bind(&body); Node* add = m.Int32Add(phi, m.Int32Constant(1)); phi->ReplaceInput(1, add); m.Goto(&header); - m.Bind(end); + m.Bind(&end); m.Return(phi); CHECK_EQ(false_val, m.Call()); @@ -314,21 +367,20 @@ TEST(RunLoopIncrement) { Int32BinopTester bt(&m); // x = 0; while(x ^ param) { x++; } return x; - MLabel header, body; - MLabel* end = m.Exit(); + MLabel header, body, end; Node* zero = m.Int32Constant(0); m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(kMachInt32, zero, zero); - m.Branch(m.WordXor(phi, bt.param0), &body, end); + m.Branch(m.WordXor(phi, bt.param0), &body, &end); m.Bind(&body); phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1))); m.Goto(&header); - m.Bind(end); + m.Bind(&end); bt.AddReturn(phi); CHECK_EQ(11, bt.call(11, 0)); @@ -342,21 +394,20 @@ TEST(RunLoopIncrement2) { Int32BinopTester bt(&m); // x = 0; while(x < param) { x++; } return x; - MLabel header, body; - MLabel* end = m.Exit(); + MLabel header, body, end; Node* zero = m.Int32Constant(0); m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(kMachInt32, zero, zero); - m.Branch(m.Int32LessThan(phi, bt.param0), &body, end); + m.Branch(m.Int32LessThan(phi, bt.param0), &body, &end); m.Bind(&body); phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1))); m.Goto(&header); - m.Bind(end); + m.Bind(&end); bt.AddReturn(phi); CHECK_EQ(11, bt.call(11, 0)); @@ -371,21 +422,20 @@ TEST(RunLoopIncrement3) { Int32BinopTester bt(&m); // x = 0; while(x < param) { x++; } return x; - MLabel header, body; - MLabel* end = m.Exit(); + MLabel header, body, end; Node* zero = m.Int32Constant(0); m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(kMachInt32, zero, zero); - m.Branch(m.Uint32LessThan(phi, bt.param0), &body, end); + m.Branch(m.Uint32LessThan(phi, bt.param0), &body, &end); m.Bind(&body); phi->ReplaceInput(1, m.Int32Add(phi, m.Int32Constant(1))); m.Goto(&header); - m.Bind(end); + m.Bind(&end); bt.AddReturn(phi); CHECK_EQ(11, bt.call(11, 0)); @@ -400,20 +450,19 @@ TEST(RunLoopDecrement) { Int32BinopTester bt(&m); // x = param; while(x) { x--; } return x; - MLabel header, body; - MLabel* end = m.Exit(); + MLabel header, body, end; m.Goto(&header); m.Bind(&header); Node* phi = m.Phi(kMachInt32, bt.param0, m.Int32Constant(0)); - m.Branch(phi, &body, end); + m.Branch(phi, &body, &end); m.Bind(&body); phi->ReplaceInput(1, m.Int32Sub(phi, m.Int32Constant(1))); m.Goto(&header); - m.Bind(end); + m.Bind(&end); bt.AddReturn(phi); CHECK_EQ(0, bt.call(11, 0)); @@ -426,8 +475,7 @@ TEST(RunLoopIncrementFloat32) { RawMachineAssemblerTester<int32_t> m; // x = -3.0f; while(x < 10f) { x = x + 0.5f; } return (int) (double) x; - MLabel header, body; - MLabel* end = m.Exit(); + MLabel header, body, end; Node* minus_3 = m.Float32Constant(-3.0f); Node* ten = m.Float32Constant(10.0f); @@ -435,13 +483,13 @@ TEST(RunLoopIncrementFloat32) { m.Bind(&header); Node* phi = m.Phi(kMachFloat32, minus_3, ten); - m.Branch(m.Float32LessThan(phi, ten), &body, end); + m.Branch(m.Float32LessThan(phi, ten), &body, &end); m.Bind(&body); phi->ReplaceInput(1, m.Float32Add(phi, m.Float32Constant(0.5f))); m.Goto(&header); - m.Bind(end); + m.Bind(&end); m.Return(m.ChangeFloat64ToInt32(m.ChangeFloat32ToFloat64(phi))); CHECK_EQ(10, m.Call()); @@ -452,8 +500,7 @@ TEST(RunLoopIncrementFloat64) { RawMachineAssemblerTester<int32_t> m; // x = -3.0; while(x < 10) { x = x + 0.5; } return (int) x; - MLabel header, body; - MLabel* end = m.Exit(); + MLabel header, body, end; Node* minus_3 = m.Float64Constant(-3.0); Node* ten = m.Float64Constant(10.0); @@ -461,13 +508,13 @@ TEST(RunLoopIncrementFloat64) { m.Bind(&header); Node* phi = m.Phi(kMachFloat64, minus_3, ten); - m.Branch(m.Float64LessThan(phi, ten), &body, end); + m.Branch(m.Float64LessThan(phi, ten), &body, &end); m.Bind(&body); phi->ReplaceInput(1, m.Float64Add(phi, m.Float64Constant(0.5))); m.Goto(&header); - m.Bind(end); + m.Bind(&end); m.Return(m.ChangeFloat64ToInt32(phi)); CHECK_EQ(10, m.Call()); @@ -4395,7 +4442,7 @@ TEST(RunTestIntPtrArithmetic) { RawMachineAssemblerTester<int32_t*> m; Node* input = m.PointerConstant(&inputs[0]); Node* output = m.PointerConstant(&outputs[kInputSize - 1]); - Node* elem_size = m.ConvertInt32ToIntPtr(m.Int32Constant(sizeof(inputs[0]))); + Node* elem_size = m.IntPtrConstant(sizeof(inputs[0])); for (int i = 0; i < kInputSize; i++) { m.Store(kMachInt32, output, m.Load(kMachInt32, input)); input = m.IntPtrAdd(input, elem_size); @@ -4412,7 +4459,7 @@ TEST(RunTestIntPtrArithmetic) { TEST(RunSpillLotsOfThings) { static const int kInputSize = 1000; - RawMachineAssemblerTester<void> m; + RawMachineAssemblerTester<int32_t> m; Node* accs[kInputSize]; int32_t outputs[kInputSize]; Node* one = m.Int32Constant(1); @@ -4793,7 +4840,8 @@ TEST(RunTruncateFloat64ToInt32P) { {-1.7976931348623157e+308, 0}}; double input = -1.0; RawMachineAssemblerTester<int32_t> m; - m.Return(m.TruncateFloat64ToInt32(m.LoadFromPointer(&input, kMachFloat64))); + m.Return(m.TruncateFloat64ToInt32(TruncationMode::kJavaScript, + m.LoadFromPointer(&input, kMachFloat64))); for (size_t i = 0; i < arraysize(kValues); ++i) { input = kValues[i].from; uint64_t expected = static_cast<int64_t>(kValues[i].raw); @@ -5080,7 +5128,7 @@ TEST(RunFloat64RoundDown1) { double input = -1.0; double result = 0.0; RawMachineAssemblerTester<int32_t> m; - if (!m.machine()->HasFloat64RoundDown()) return; + if (!m.machine()->Float64RoundDown().IsSupported()) return; m.StoreToPointer(&result, kMachFloat64, m.Float64RoundDown(m.LoadFromPointer(&input, kMachFloat64))); m.Return(m.Int32Constant(0)); @@ -5097,7 +5145,7 @@ TEST(RunFloat64RoundDown2) { double input = -1.0; double result = 0.0; RawMachineAssemblerTester<int32_t> m; - if (!m.machine()->HasFloat64RoundDown()) return; + if (!m.machine()->Float64RoundDown().IsSupported()) return; m.StoreToPointer(&result, kMachFloat64, m.Float64Sub(m.Float64Constant(-0.0), m.Float64RoundDown(m.Float64Sub( @@ -5117,7 +5165,7 @@ TEST(RunFloat64RoundTruncate) { double input = -1.0; double result = 0.0; RawMachineAssemblerTester<int32_t> m; - if (!m.machine()->HasFloat64RoundTruncate()) return; + if (!m.machine()->Float64RoundTruncate().IsSupported()) return; m.StoreToPointer( &result, kMachFloat64, m.Float64RoundTruncate(m.LoadFromPointer(&input, kMachFloat64))); @@ -5135,7 +5183,7 @@ TEST(RunFloat64RoundTiesAway) { double input = -1.0; double result = 0.0; RawMachineAssemblerTester<int32_t> m; - if (!m.machine()->HasFloat64RoundTiesAway()) return; + if (!m.machine()->Float64RoundTiesAway().IsSupported()) return; m.StoreToPointer( &result, kMachFloat64, m.Float64RoundTiesAway(m.LoadFromPointer(&input, kMachFloat64))); @@ -5148,4 +5196,83 @@ TEST(RunFloat64RoundTiesAway) { } } + +#if !USE_SIMULATOR + +namespace { + +int32_t const kMagicFoo0 = 0xdeadbeef; + + +int32_t foo0() { return kMagicFoo0; } + + +int32_t foo1(int32_t x) { return x; } + + +int32_t foo2(int32_t x, int32_t y) { return x - y; } + + +int32_t foo8(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, int32_t f, + int32_t g, int32_t h) { + return a + b + c + d + e + f + g + h; +} + +} // namespace + + +TEST(RunCallCFunction0) { + auto* foo0_ptr = &foo0; + RawMachineAssemblerTester<int32_t> m; + Node* function = m.LoadFromPointer(&foo0_ptr, kMachPtr); + m.Return(m.CallCFunction0(kMachInt32, function)); + CHECK_EQ(kMagicFoo0, m.Call()); +} + + +TEST(RunCallCFunction1) { + auto* foo1_ptr = &foo1; + RawMachineAssemblerTester<int32_t> m(kMachInt32); + Node* function = m.LoadFromPointer(&foo1_ptr, kMachPtr); + m.Return(m.CallCFunction1(kMachInt32, kMachInt32, function, m.Parameter(0))); + FOR_INT32_INPUTS(i) { + int32_t const expected = *i; + CHECK_EQ(expected, m.Call(expected)); + } +} + + +TEST(RunCallCFunction2) { + auto* foo2_ptr = &foo2; + RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32); + Node* function = m.LoadFromPointer(&foo2_ptr, kMachPtr); + m.Return(m.CallCFunction2(kMachInt32, kMachInt32, kMachInt32, function, + m.Parameter(0), m.Parameter(1))); + FOR_INT32_INPUTS(i) { + int32_t const x = *i; + FOR_INT32_INPUTS(j) { + int32_t const y = *j; + CHECK_EQ(x - y, m.Call(x, y)); + } + } +} + + +TEST(RunCallCFunction8) { + auto* foo8_ptr = &foo8; + RawMachineAssemblerTester<int32_t> m(kMachInt32); + Node* function = m.LoadFromPointer(&foo8_ptr, kMachPtr); + Node* param = m.Parameter(0); + m.Return(m.CallCFunction8(kMachInt32, kMachInt32, kMachInt32, kMachInt32, + kMachInt32, kMachInt32, kMachInt32, kMachInt32, + kMachInt32, function, param, param, param, param, + param, param, param, param)); + FOR_INT32_INPUTS(i) { + int32_t const x = *i; + CHECK_EQ(x * 8, m.Call(x)); + } +} + +#endif // USE_SIMULATOR + #endif // V8_TURBOFAN_TARGET diff --git a/deps/v8/test/cctest/compiler/test-run-stubs.cc b/deps/v8/test/cctest/compiler/test-run-stubs.cc index c81f0f184d..9c7998d7af 100644 --- a/deps/v8/test/cctest/compiler/test-run-stubs.cc +++ b/deps/v8/test/cctest/compiler/test-run-stubs.cc @@ -6,7 +6,10 @@ #include "src/code-stubs.h" #include "src/compiler/common-operator.h" #include "src/compiler/graph.h" +#include "src/compiler/js-graph.h" +#include "src/compiler/js-operator.h" #include "src/compiler/linkage.h" +#include "src/compiler/machine-operator.h" #include "src/compiler/pipeline.h" #include "src/parser.h" #include "test/cctest/compiler/function-tester.h" @@ -17,60 +20,54 @@ using namespace v8::internal; using namespace v8::internal::compiler; -static Handle<JSFunction> GetFunction(Isolate* isolate, const char* name) { - v8::ExtensionConfiguration no_extensions; - Handle<Context> ctx = isolate->bootstrapper()->CreateEnvironment( - MaybeHandle<JSGlobalProxy>(), v8::Handle<v8::ObjectTemplate>(), - &no_extensions); - Handle<JSBuiltinsObject> builtins = handle(ctx->builtins()); - MaybeHandle<Object> fun = Object::GetProperty(isolate, builtins, name); - Handle<JSFunction> function = Handle<JSFunction>::cast(fun.ToHandleChecked()); - // Just to make sure nobody calls this... - function->set_code(isolate->builtins()->builtin(Builtins::kIllegal)); - return function; -} - - -class StringLengthStubTF : public CodeStub { - public: - explicit StringLengthStubTF(Isolate* isolate) : CodeStub(isolate) {} +TEST(RunMathFloorStub) { + HandleAndZoneScope scope; + Isolate* isolate = scope.main_isolate(); - StringLengthStubTF(uint32_t key, Isolate* isolate) : CodeStub(key, isolate) {} + // Create code and an accompanying descriptor. + MathFloorStub stub(isolate); + Handle<Code> code = stub.GenerateCode(); + Zone* zone = scope.main_zone(); - CallInterfaceDescriptor GetCallInterfaceDescriptor() override { - return LoadDescriptor(isolate()); - }; + CompilationInfo info(&stub, isolate, zone); + CallDescriptor* descriptor = Linkage::ComputeIncoming(zone, &info); - Handle<Code> GenerateCode() override { - Zone zone; - // Build a "hybrid" CompilationInfo for a JSFunction/CodeStub pair. - ParseInfo parse_info(&zone, GetFunction(isolate(), "STRING_LENGTH_STUB")); - CompilationInfo info(&parse_info); - info.SetStub(this); - // Run a "mini pipeline", extracted from compiler.cc. - CHECK(Parser::ParseStatic(info.parse_info())); - CHECK(Compiler::Analyze(info.parse_info())); - return Pipeline(&info).GenerateCode(); - } + // Create a function to call the code using the descriptor. + Graph graph(zone); + CommonOperatorBuilder common(zone); + JSOperatorBuilder javascript(zone); + MachineOperatorBuilder machine(zone); + JSGraph js(isolate, &graph, &common, &javascript, &machine); - Major MajorKey() const override { return StringLength; }; - Code::Kind GetCodeKind() const override { return Code::HANDLER; } - InlineCacheState GetICState() const override { return MONOMORPHIC; } - ExtraICState GetExtraICState() const override { return Code::LOAD_IC; } - Code::StubType GetStubType() const override { return Code::FAST; } + // FunctionTester (ab)uses a 2-argument function + Node* start = graph.NewNode(common.Start(4)); + // Parameter 0 is the number to round + Node* numberParam = graph.NewNode(common.Parameter(1), start); + Unique<HeapObject> u = Unique<HeapObject>::CreateImmovable(code); + Node* theCode = graph.NewNode(common.HeapConstant(u)); + Node* dummyContext = graph.NewNode(common.NumberConstant(0.0)); + Node* call = graph.NewNode(common.Call(descriptor), theCode, + js.UndefinedConstant(), js.UndefinedConstant(), + numberParam, dummyContext, start, start); + Node* ret = graph.NewNode(common.Return(), call, call, start); + Node* end = graph.NewNode(common.End(1), ret); + graph.SetStart(start); + graph.SetEnd(end); + FunctionTester ft(&graph); - private: - DISALLOW_COPY_AND_ASSIGN(StringLengthStubTF); -}; + Handle<Object> value = ft.Val(1.5); + Handle<Object> result = ft.Call(value, value).ToHandleChecked(); + CHECK_EQ(1, Smi::cast(*result)->value()); +} -TEST(RunStringLengthStubTF) { +TEST(RunStringLengthTFStub) { HandleAndZoneScope scope; Isolate* isolate = scope.main_isolate(); Zone* zone = scope.main_zone(); // Create code and an accompanying descriptor. - StringLengthStubTF stub(isolate); + StringLengthTFStub stub(isolate); Handle<Code> code = stub.GenerateCode(); CompilationInfo info(&stub, isolate, zone); CallDescriptor* descriptor = Linkage::ComputeIncoming(zone, &info); @@ -78,18 +75,21 @@ TEST(RunStringLengthStubTF) { // Create a function to call the code using the descriptor. Graph graph(zone); CommonOperatorBuilder common(zone); - // FunctionTester (ab)uses a 2-argument function - Node* start = graph.NewNode(common.Start(2)); + // FunctionTester (ab)uses a 4-argument function + Node* start = graph.NewNode(common.Start(6)); // Parameter 0 is the receiver Node* receiverParam = graph.NewNode(common.Parameter(1), start); Node* nameParam = graph.NewNode(common.Parameter(2), start); + Node* slotParam = graph.NewNode(common.Parameter(3), start); + Node* vectorParam = graph.NewNode(common.Parameter(4), start); Unique<HeapObject> u = Unique<HeapObject>::CreateImmovable(code); Node* theCode = graph.NewNode(common.HeapConstant(u)); Node* dummyContext = graph.NewNode(common.NumberConstant(0.0)); - Node* call = graph.NewNode(common.Call(descriptor), theCode, receiverParam, - nameParam, dummyContext, start, start); + Node* call = + graph.NewNode(common.Call(descriptor), theCode, receiverParam, nameParam, + slotParam, vectorParam, dummyContext, start, start); Node* ret = graph.NewNode(common.Return(), call, call, start); - Node* end = graph.NewNode(common.End(), ret); + Node* end = graph.NewNode(common.End(1), ret); graph.SetStart(start); graph.SetEnd(end); FunctionTester ft(&graph); @@ -99,8 +99,49 @@ TEST(RunStringLengthStubTF) { Handle<JSReceiver> receiverArg = Object::ToObject(isolate, ft.Val(testString)).ToHandleChecked(); Handle<String> nameArg = ft.Val("length"); - Handle<Object> result = ft.Call(receiverArg, nameArg).ToHandleChecked(); + Handle<Object> slot = ft.Val(0.0); + Handle<Object> vector = ft.Val(0.0); + Handle<Object> result = + ft.Call(receiverArg, nameArg, slot, vector).ToHandleChecked(); CHECK_EQ(static_cast<int>(strlen(testString)), Smi::cast(*result)->value()); } + +TEST(RunStringAddTFStub) { + HandleAndZoneScope scope; + Isolate* isolate = scope.main_isolate(); + Zone* zone = scope.main_zone(); + + // Create code and an accompanying descriptor. + StringAddTFStub stub(isolate, STRING_ADD_CHECK_BOTH, NOT_TENURED); + Handle<Code> code = stub.GenerateCode(); + CompilationInfo info(&stub, isolate, zone); + CallDescriptor* descriptor = Linkage::ComputeIncoming(zone, &info); + + // Create a function to call the code using the descriptor. + Graph graph(zone); + CommonOperatorBuilder common(zone); + // FunctionTester (ab)uses a 2-argument function + Node* start = graph.NewNode(common.Start(4)); + // Parameter 0 is the receiver + Node* leftParam = graph.NewNode(common.Parameter(1), start); + Node* rightParam = graph.NewNode(common.Parameter(2), start); + Unique<HeapObject> u = Unique<HeapObject>::CreateImmovable(code); + Node* theCode = graph.NewNode(common.HeapConstant(u)); + Node* dummyContext = graph.NewNode(common.NumberConstant(0.0)); + Node* call = graph.NewNode(common.Call(descriptor), theCode, leftParam, + rightParam, dummyContext, start, start); + Node* ret = graph.NewNode(common.Return(), call, call, start); + Node* end = graph.NewNode(common.End(1), ret); + graph.SetStart(start); + graph.SetEnd(end); + FunctionTester ft(&graph); + + // Actuall call through to the stub, verifying its result. + Handle<String> leftArg = ft.Val("links"); + Handle<String> rightArg = ft.Val("rechts"); + Handle<Object> result = ft.Call(leftArg, rightArg).ToHandleChecked(); + CHECK(String::Equals(ft.Val("linksrechts"), Handle<String>::cast(result))); +} + #endif // V8_TURBOFAN_TARGET diff --git a/deps/v8/test/cctest/compiler/test-simplified-lowering.cc b/deps/v8/test/cctest/compiler/test-simplified-lowering.cc index 9242248d60..022e01690b 100644 --- a/deps/v8/test/cctest/compiler/test-simplified-lowering.cc +++ b/deps/v8/test/cctest/compiler/test-simplified-lowering.cc @@ -33,12 +33,9 @@ template <typename ReturnType> class SimplifiedLoweringTester : public GraphBuilderTester<ReturnType> { public: SimplifiedLoweringTester(MachineType p0 = kMachNone, - MachineType p1 = kMachNone, - MachineType p2 = kMachNone, - MachineType p3 = kMachNone, - MachineType p4 = kMachNone) - : GraphBuilderTester<ReturnType>(p0, p1, p2, p3, p4), - typer(this->isolate(), this->graph(), MaybeHandle<Context>()), + MachineType p1 = kMachNone) + : GraphBuilderTester<ReturnType>(p0, p1), + typer(this->isolate(), this->graph()), javascript(this->zone()), jsgraph(this->isolate(), this->graph(), this->common(), &javascript, this->machine()), @@ -63,7 +60,7 @@ class SimplifiedLoweringTester : public GraphBuilderTester<ReturnType> { lowering.LowerAllNodes(); ChangeLowering lowering(&jsgraph); - GraphReducer reducer(this->graph(), this->zone()); + GraphReducer reducer(this->zone(), this->graph()); reducer.AddReducer(&lowering); reducer.ReduceGraph(); Verifier::Run(this->graph()); @@ -538,8 +535,7 @@ class AccessTester : public HandleAndZoneScope { E GetElement(int index) { BoundsCheck(index); if (tagged) { - E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress()); - return raw[index]; + return GetTaggedElement(index); } else { return untagged_array[index]; } @@ -572,8 +568,19 @@ class AccessTester : public HandleAndZoneScope { CHECK_LT(index, static_cast<int>(num_elements)); CHECK_EQ(static_cast<int>(ByteSize()), tagged_array->length()); } + + E GetTaggedElement(int index) { + E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress()); + return raw[index]; + } }; +template <> +double AccessTester<double>::GetTaggedElement(int index) { + return ReadDoubleValue(tagged_array->GetDataStartAddress() + + index * sizeof(double)); +} + template <typename E> static void RunAccessTest(MachineType rep, E* original_elements, size_t num) { @@ -703,14 +710,14 @@ class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders { explicit TestingGraph(Type* p0_type, Type* p1_type = Type::None(), Type* p2_type = Type::None()) : GraphAndBuilders(main_zone()), - typer(main_isolate(), graph(), MaybeHandle<Context>()), + typer(main_isolate(), graph()), javascript(main_zone()), jsgraph(main_isolate(), graph(), common(), &javascript, machine()) { start = graph()->NewNode(common()->Start(2)); graph()->SetStart(start); ret = graph()->NewNode(common()->Return(), jsgraph.Constant(0), start, start); - end = graph()->NewNode(common()->End(), ret); + end = graph()->NewNode(common()->End(1), ret); graph()->SetEnd(end); p0 = graph()->NewNode(common()->Parameter(0), start); p1 = graph()->NewNode(common()->Parameter(1), start); @@ -1269,7 +1276,6 @@ TEST(LowerStringOps_to_call_and_compare) { t.CheckLoweringBinop(compare_eq, t.simplified()->StringEqual()); t.CheckLoweringBinop(compare_lt, t.simplified()->StringLessThan()); t.CheckLoweringBinop(compare_le, t.simplified()->StringLessThanOrEqual()); - t.CheckLoweringBinop(IrOpcode::kCall, t.simplified()->StringAdd()); } } @@ -1443,8 +1449,8 @@ TEST(LowerLoadField_to_load) { FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(), Type::Any(), kMachineReps[i]}; - Node* load = - t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, t.start); + Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, + t.start, t.start); Node* use = t.Use(load, kMachineReps[i]); t.Return(use); t.Lower(); @@ -1624,8 +1630,8 @@ TEST(InsertChangeForLoadField) { FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(), Type::Any(), kMachFloat64}; - Node* load = - t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, t.start); + Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, + t.start, t.start); t.Return(load); t.Lower(); CHECK_EQ(IrOpcode::kLoad, load->opcode()); @@ -1679,10 +1685,10 @@ TEST(UpdatePhi) { FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(), kTypes[i], kMachineTypes[i]}; - Node* load0 = - t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, t.start); - Node* load1 = - t.graph()->NewNode(t.simplified()->LoadField(access), t.p1, t.start); + Node* load0 = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, + t.start, t.start); + Node* load1 = t.graph()->NewNode(t.simplified()->LoadField(access), t.p1, + t.start, t.start); Node* phi = t.graph()->NewNode(t.common()->Phi(kMachAnyTagged, 2), load0, load1, t.start); t.Return(t.Use(phi, kMachineTypes[i])); diff --git a/deps/v8/test/cctest/gay-fixed.cc b/deps/v8/test/cctest/gay-fixed.cc index 81463ac1fa..86ebb24cd8 100644 --- a/deps/v8/test/cctest/gay-fixed.cc +++ b/deps/v8/test/cctest/gay-fixed.cc @@ -100046,4 +100046,5 @@ Vector<const PrecomputedFixed> PrecomputedFixedRepresentations() { } -} } // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/cctest/gay-precision.cc b/deps/v8/test/cctest/gay-precision.cc index 6ab2715fea..68d29f8cd5 100644 --- a/deps/v8/test/cctest/gay-precision.cc +++ b/deps/v8/test/cctest/gay-precision.cc @@ -100047,4 +100047,5 @@ Vector<const PrecomputedPrecision> PrecomputedPrecisionRepresentations() { number_elements); } -} } // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/cctest/gay-shortest.cc b/deps/v8/test/cctest/gay-shortest.cc index 896ea4c514..456055392c 100644 --- a/deps/v8/test/cctest/gay-shortest.cc +++ b/deps/v8/test/cctest/gay-shortest.cc @@ -100047,4 +100047,5 @@ Vector<const PrecomputedShortest> PrecomputedShortestRepresentations() { number_elements); } -} } // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/cctest/print-extension.cc b/deps/v8/test/cctest/print-extension.cc index d1af3596e8..33f33cafc2 100644 --- a/deps/v8/test/cctest/print-extension.cc +++ b/deps/v8/test/cctest/print-extension.cc @@ -48,4 +48,5 @@ void PrintExtension::Print(const v8::FunctionCallbackInfo<v8::Value>& args) { printf("\n"); } -} } // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/cctest/profiler-extension.cc b/deps/v8/test/cctest/profiler-extension.cc index 263fc4f38d..c8cb0fb7ca 100644 --- a/deps/v8/test/cctest/profiler-extension.cc +++ b/deps/v8/test/cctest/profiler-extension.cc @@ -72,4 +72,5 @@ void ProfilerExtension::StopProfiling( : v8::String::Empty(args.GetIsolate())); } -} } // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/cctest/test-accessors.cc b/deps/v8/test/cctest/test-accessors.cc index ac631757b2..14303e2371 100644 --- a/deps/v8/test/cctest/test-accessors.cc +++ b/deps/v8/test/cctest/test-accessors.cc @@ -552,7 +552,7 @@ THREADED_TEST(AccessorPropertyCrossContext) { v8::Handle<v8::Function> fun = v8::Function::New(isolate, check_contexts); LocalContext switch_context; switch_context->Global()->Set(v8_str("fun"), fun); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); expected_current_context = env.local(); expected_calling_context = switch_context.local(); CompileRun( diff --git a/deps/v8/test/cctest/test-api-interceptors.cc b/deps/v8/test/cctest/test-api-interceptors.cc index aba08e23d7..2e9bc74a92 100644 --- a/deps/v8/test/cctest/test-api-interceptors.cc +++ b/deps/v8/test/cctest/test-api-interceptors.cc @@ -1007,10 +1007,11 @@ THREADED_TEST(PropertyHandlerInPrototype) { } +bool is_bootstrapping = false; static void PrePropertyHandlerGet( Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) { ApiTestFuzzer::Fuzz(); - if (v8_str("pre")->Equals(key)) { + if (!is_bootstrapping && v8_str("pre")->Equals(key)) { info.GetReturnValue().Set(v8_str("PrePropertyHandler: pre")); } } @@ -1018,7 +1019,7 @@ static void PrePropertyHandlerGet( static void PrePropertyHandlerQuery( Local<Name> key, const v8::PropertyCallbackInfo<v8::Integer>& info) { - if (v8_str("pre")->Equals(key)) { + if (!is_bootstrapping && v8_str("pre")->Equals(key)) { info.GetReturnValue().Set(static_cast<int32_t>(v8::None)); } } @@ -1030,7 +1031,9 @@ THREADED_TEST(PrePropertyHandler) { v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate); desc->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration( PrePropertyHandlerGet, 0, PrePropertyHandlerQuery)); + is_bootstrapping = true; LocalContext env(NULL, desc->InstanceTemplate()); + is_bootstrapping = false; CompileRun("var pre = 'Object: pre'; var on = 'Object: on';"); v8::Handle<Value> result_pre = CompileRun("pre"); CHECK(v8_str("PrePropertyHandler: pre")->Equals(result_pre)); @@ -1658,6 +1661,12 @@ THREADED_TEST(IndexedInterceptorWithNoSetter) { } +static bool AccessAlwaysBlocked(Local<v8::Object> global, Local<Value> name, + v8::AccessType type, Local<Value> data) { + return false; +} + + THREADED_TEST(IndexedInterceptorWithAccessorCheck) { v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope scope(isolate); @@ -1665,9 +1674,10 @@ THREADED_TEST(IndexedInterceptorWithAccessorCheck) { templ->SetHandler( v8::IndexedPropertyHandlerConfiguration(IdentityIndexedPropertyGetter)); + templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, nullptr); + LocalContext context; Local<v8::Object> obj = templ->NewInstance(); - obj->TurnOnAccessCheck(); context->Global()->Set(v8_str("obj"), obj); const char* code = @@ -1686,46 +1696,6 @@ THREADED_TEST(IndexedInterceptorWithAccessorCheck) { } -THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) { - i::FLAG_allow_natives_syntax = true; - v8::Isolate* isolate = CcTest::isolate(); - v8::HandleScope scope(isolate); - Local<ObjectTemplate> templ = ObjectTemplate::New(isolate); - templ->SetHandler( - v8::IndexedPropertyHandlerConfiguration(IdentityIndexedPropertyGetter)); - - LocalContext context; - Local<v8::Object> obj = templ->NewInstance(); - context->Global()->Set(v8_str("obj"), obj); - - const char* code = - "var result = 'PASSED';" - "for (var i = 0; i < 100; i++) {" - " var expected = i;" - " if (i == 5) {" - " %EnableAccessChecks(obj);" - " }" - " try {" - " var v = obj[i];" - " if (i == 5) {" - " result = 'Should not have reached this!';" - " break;" - " } else if (v != expected) {" - " result = 'Wrong value ' + v + ' at iteration ' + i;" - " break;" - " }" - " } catch (e) {" - " if (i != 5) {" - " result = e;" - " }" - " }" - " if (i == 5) %DisableAccessChecks(obj);" - "}" - "result"; - ExpectString(code, "PASSED"); -} - - THREADED_TEST(IndexedInterceptorWithDifferentIndices) { v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope scope(isolate); @@ -2021,9 +1991,9 @@ THREADED_TEST(Enumerators) { "k.a = 0;" "k[5] = 0;" "k.b = 0;" - "k[4294967295] = 0;" + "k[4294967294] = 0;" "k.c = 0;" - "k[4294967296] = 0;" + "k[4294967295] = 0;" "k.d = 0;" "k[140000] = 0;" "k.e = 0;" @@ -2046,7 +2016,7 @@ THREADED_TEST(Enumerators) { CHECK(v8_str("10")->Equals(result->Get(v8::Integer::New(isolate, 1)))); CHECK(v8_str("140000")->Equals(result->Get(v8::Integer::New(isolate, 2)))); CHECK( - v8_str("4294967295")->Equals(result->Get(v8::Integer::New(isolate, 3)))); + v8_str("4294967294")->Equals(result->Get(v8::Integer::New(isolate, 3)))); // Indexed interceptor properties in the order they are returned // from the enumerator interceptor. CHECK(v8_str("0")->Equals(result->Get(v8::Integer::New(isolate, 4)))); @@ -2056,7 +2026,7 @@ THREADED_TEST(Enumerators) { CHECK(v8_str("b")->Equals(result->Get(v8::Integer::New(isolate, 7)))); CHECK(v8_str("c")->Equals(result->Get(v8::Integer::New(isolate, 8)))); CHECK( - v8_str("4294967296")->Equals(result->Get(v8::Integer::New(isolate, 9)))); + v8_str("4294967295")->Equals(result->Get(v8::Integer::New(isolate, 9)))); CHECK(v8_str("d")->Equals(result->Get(v8::Integer::New(isolate, 10)))); CHECK(v8_str("e")->Equals(result->Get(v8::Integer::New(isolate, 11)))); CHECK(v8_str("30000000000") @@ -2533,7 +2503,8 @@ static int interceptor_call_count = 0; static void InterceptorICRefErrorGetter( Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { ApiTestFuzzer::Fuzz(); - if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) { + if (!is_bootstrapping && v8_str("x")->Equals(name) && + interceptor_call_count++ < 20) { info.GetReturnValue().Set(call_ic_function2); } } @@ -2548,7 +2519,9 @@ THREADED_TEST(InterceptorICReferenceErrors) { v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate); templ->SetHandler( v8::NamedPropertyHandlerConfiguration(InterceptorICRefErrorGetter)); + is_bootstrapping = true; LocalContext context(0, templ, v8::Handle<Value>()); + is_bootstrapping = false; call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run(); v8::Handle<Value> value = CompileRun( "function f() {" @@ -2577,6 +2550,7 @@ static int interceptor_ic_exception_get_count = 0; static void InterceptorICExceptionGetter( Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { ApiTestFuzzer::Fuzz(); + if (is_bootstrapping) return; if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) { info.GetReturnValue().Set(call_ic_function3); } @@ -2596,7 +2570,9 @@ THREADED_TEST(InterceptorICGetterExceptions) { v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate); templ->SetHandler( v8::NamedPropertyHandlerConfiguration(InterceptorICExceptionGetter)); + is_bootstrapping = true; LocalContext context(0, templ, v8::Handle<Value>()); + is_bootstrapping = false; call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run(); v8::Handle<Value> value = CompileRun( "function f() {" @@ -2975,7 +2951,7 @@ THREADED_TEST(NamedAllCanReadInterceptor) { LocalContext context; AccessCheckData access_check_data; - access_check_data.result = false; + access_check_data.result = true; access_check_data.count = 0; ShouldInterceptData intercept_data_0; @@ -3007,7 +2983,7 @@ THREADED_TEST(NamedAllCanReadInterceptor) { auto checked = v8::ObjectTemplate::New(isolate); checked->SetAccessCheckCallbacks( SimpleAccessChecker, nullptr, - BuildWrappedObject<AccessCheckData>(isolate, &access_check_data), false); + BuildWrappedObject<AccessCheckData>(isolate, &access_check_data)); context->Global()->Set(v8_str("intercepted_0"), intercepted_0->NewInstance()); context->Global()->Set(v8_str("intercepted_1"), intercepted_1->NewInstance()); @@ -3018,14 +2994,12 @@ THREADED_TEST(NamedAllCanReadInterceptor) { "checked.__proto__ = intercepted_1;" "intercepted_1.__proto__ = intercepted_0;"); - checked_instance->TurnOnAccessCheck(); - CHECK_EQ(0, access_check_data.count); + CHECK_EQ(3, access_check_data.count); - access_check_data.result = true; ExpectInt32("checked.whatever", 17); CHECK(!CompileRun("Object.getOwnPropertyDescriptor(checked, 'whatever')") ->IsUndefined()); - CHECK_EQ(2, access_check_data.count); + CHECK_EQ(5, access_check_data.count); access_check_data.result = false; ExpectInt32("checked.whatever", intercept_data_0.value); @@ -3034,7 +3008,7 @@ THREADED_TEST(NamedAllCanReadInterceptor) { CompileRun("Object.getOwnPropertyDescriptor(checked, 'whatever')"); CHECK(try_catch.HasCaught()); } - CHECK_EQ(4, access_check_data.count); + CHECK_EQ(7, access_check_data.count); intercept_data_1.should_intercept = true; ExpectInt32("checked.whatever", intercept_data_1.value); @@ -3043,7 +3017,7 @@ THREADED_TEST(NamedAllCanReadInterceptor) { CompileRun("Object.getOwnPropertyDescriptor(checked, 'whatever')"); CHECK(try_catch.HasCaught()); } - CHECK_EQ(6, access_check_data.count); + CHECK_EQ(9, access_check_data.count); } @@ -3053,7 +3027,7 @@ THREADED_TEST(IndexedAllCanReadInterceptor) { LocalContext context; AccessCheckData access_check_data; - access_check_data.result = false; + access_check_data.result = true; access_check_data.count = 0; ShouldInterceptData intercept_data_0; @@ -3085,7 +3059,7 @@ THREADED_TEST(IndexedAllCanReadInterceptor) { auto checked = v8::ObjectTemplate::New(isolate); checked->SetAccessCheckCallbacks( SimpleAccessChecker, nullptr, - BuildWrappedObject<AccessCheckData>(isolate, &access_check_data), false); + BuildWrappedObject<AccessCheckData>(isolate, &access_check_data)); context->Global()->Set(v8_str("intercepted_0"), intercepted_0->NewInstance()); context->Global()->Set(v8_str("intercepted_1"), intercepted_1->NewInstance()); @@ -3096,27 +3070,30 @@ THREADED_TEST(IndexedAllCanReadInterceptor) { "checked.__proto__ = intercepted_1;" "intercepted_1.__proto__ = intercepted_0;"); - checked_instance->TurnOnAccessCheck(); - CHECK_EQ(0, access_check_data.count); + CHECK_EQ(3, access_check_data.count); access_check_data.result = true; ExpectInt32("checked[15]", 17); CHECK(!CompileRun("Object.getOwnPropertyDescriptor(checked, '15')") ->IsUndefined()); - CHECK_EQ(3, access_check_data.count); + CHECK_EQ(5, access_check_data.count); access_check_data.result = false; ExpectInt32("checked[15]", intercept_data_0.value); - // Note: this should throw but without a LookupIterator it's complicated. - CHECK(!CompileRun("Object.getOwnPropertyDescriptor(checked, '15')") - ->IsUndefined()); - CHECK_EQ(6, access_check_data.count); + { + v8::TryCatch try_catch(isolate); + CompileRun("Object.getOwnPropertyDescriptor(checked, '15')"); + CHECK(try_catch.HasCaught()); + } + CHECK_EQ(7, access_check_data.count); intercept_data_1.should_intercept = true; ExpectInt32("checked[15]", intercept_data_1.value); - // Note: this should throw but without a LookupIterator it's complicated. - CHECK(!CompileRun("Object.getOwnPropertyDescriptor(checked, '15')") - ->IsUndefined()); + { + v8::TryCatch try_catch(isolate); + CompileRun("Object.getOwnPropertyDescriptor(checked, '15')"); + CHECK(try_catch.HasCaught()); + } CHECK_EQ(9, access_check_data.count); } diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index 145d9bc64d..e464a67e00 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -190,7 +190,7 @@ static void TestSignature(const char* loop_js, Local<Value> receiver, signature_callback_count = 0; signature_expected_receiver = receiver; bool expected_to_throw = receiver.IsEmpty(); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun(source.start()); CHECK_EQ(expected_to_throw, try_catch.HasCaught()); if (!expected_to_throw) { @@ -697,7 +697,7 @@ THREADED_TEST(NewExternalForVeryLongString) { auto isolate = CcTest::isolate(); { v8::HandleScope scope(isolate); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); RandomLengthOneByteResource r(1 << 30); v8::Local<v8::String> str = v8::String::NewExternal(isolate, &r); CHECK(str.IsEmpty()); @@ -706,7 +706,7 @@ THREADED_TEST(NewExternalForVeryLongString) { { v8::HandleScope scope(isolate); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); RandomLengthResource r(1 << 30); v8::Local<v8::String> str = v8::String::NewExternal(isolate, &r); CHECK(str.IsEmpty()); @@ -1590,6 +1590,17 @@ THREADED_TEST(StringObject) { } +TEST(StringObjectDelete) { + LocalContext context; + v8::HandleScope scope(context->GetIsolate()); + v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")"); + CHECK(boxed_string->IsStringObject()); + v8::Handle<v8::Object> str_obj = boxed_string.As<v8::Object>(); + CHECK(!str_obj->Delete(2)); + CHECK(!str_obj->Delete(v8_num(2))); +} + + THREADED_TEST(NumberObject) { LocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -2248,12 +2259,24 @@ THREADED_TEST(IdentityHash) { } -THREADED_TEST(GlobalProxyIdentityHash) { +void GlobalProxyIdentityHash(bool set_in_js) { LocalContext env; v8::Isolate* isolate = env->GetIsolate(); + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); v8::HandleScope scope(isolate); Handle<Object> global_proxy = env->Global(); - int hash1 = global_proxy->GetIdentityHash(); + i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy); + env->Global()->Set(v8_str("global"), global_proxy); + i::Handle<i::Object> original_hash; + if (set_in_js) { + CompileRun("var m = new Set(); m.add(global);"); + original_hash = i::Handle<i::Object>(i_global_proxy->GetHash(), i_isolate); + } else { + original_hash = i::Handle<i::Object>( + i::Object::GetOrCreateHash(i_isolate, i_global_proxy)); + } + CHECK(original_hash->IsSmi()); + int32_t hash1 = i::Handle<i::Smi>::cast(original_hash)->value(); // Hash should be retained after being detached. env->DetachGlobal(); int hash2 = global_proxy->GetIdentityHash(); @@ -2267,6 +2290,12 @@ THREADED_TEST(GlobalProxyIdentityHash) { } +THREADED_TEST(GlobalProxyIdentityHash) { + GlobalProxyIdentityHash(true); + GlobalProxyIdentityHash(false); +} + + TEST(SymbolIdentityHash) { LocalContext env; v8::Isolate* isolate = env->GetIsolate(); @@ -2434,65 +2463,6 @@ THREADED_TEST(SymbolTemplateProperties) { } -THREADED_TEST(PrivateProperties) { - LocalContext env; - v8::Isolate* isolate = env->GetIsolate(); - v8::HandleScope scope(isolate); - - v8::Local<v8::Object> obj = v8::Object::New(isolate); - v8::Local<v8::Private> priv1 = v8::Private::New(isolate); - v8::Local<v8::Private> priv2 = - v8::Private::New(isolate, v8_str("my-private")); - - CcTest::heap()->CollectAllGarbage(); - - CHECK(priv2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-private"))); - - // Make sure delete of a non-existent private symbol property works. - CHECK(obj->DeletePrivate(priv1)); - CHECK(!obj->HasPrivate(priv1)); - - CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 1503))); - CHECK(obj->HasPrivate(priv1)); - CHECK_EQ(1503, obj->GetPrivate(priv1)->Int32Value()); - CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 2002))); - CHECK(obj->HasPrivate(priv1)); - CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value()); - - CHECK_EQ(0u, obj->GetOwnPropertyNames()->Length()); - unsigned num_props = obj->GetPropertyNames()->Length(); - CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"), - v8::Integer::New(isolate, 20))); - CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length()); - CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length()); - - CcTest::heap()->CollectAllGarbage(); - - // Add another property and delete it afterwards to force the object in - // slow case. - CHECK(obj->SetPrivate(priv2, v8::Integer::New(isolate, 2008))); - CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value()); - CHECK_EQ(2008, obj->GetPrivate(priv2)->Int32Value()); - CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value()); - CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length()); - - CHECK(obj->HasPrivate(priv1)); - CHECK(obj->HasPrivate(priv2)); - CHECK(obj->DeletePrivate(priv2)); - CHECK(obj->HasPrivate(priv1)); - CHECK(!obj->HasPrivate(priv2)); - CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value()); - CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length()); - - // Private properties are inherited (for the time being). - v8::Local<v8::Object> child = v8::Object::New(isolate); - child->SetPrototype(obj); - CHECK(child->HasPrivate(priv1)); - CHECK_EQ(2002, child->GetPrivate(priv1)->Int32Value()); - CHECK_EQ(0u, child->GetOwnPropertyNames()->Length()); -} - - THREADED_TEST(GlobalSymbols) { LocalContext env; v8::Isolate* isolate = env->GetIsolate(); @@ -2541,28 +2511,6 @@ THREADED_TEST(WellKnownSymbols) { } -THREADED_TEST(GlobalPrivates) { - LocalContext env; - v8::Isolate* isolate = env->GetIsolate(); - v8::HandleScope scope(isolate); - - v8::Local<String> name = v8_str("my-private"); - v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name); - v8::Local<v8::Object> obj = v8::Object::New(isolate); - CHECK(obj->SetPrivate(glob, v8::Integer::New(isolate, 3))); - - v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name); - CHECK(obj->HasPrivate(glob2)); - - v8::Local<v8::Private> priv = v8::Private::New(isolate, name); - CHECK(!obj->HasPrivate(priv)); - - CompileRun("var intern = %CreateGlobalPrivateSymbol('my-private')"); - v8::Local<Value> intern = env->Global()->Get(v8_str("intern")); - CHECK(!obj->Has(intern)); -} - - class ScopedArrayBufferContents { public: explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents) @@ -2846,6 +2794,136 @@ THREADED_TEST(ArrayBuffer_NeuteringScript) { } +class ScopedSharedArrayBufferContents { + public: + explicit ScopedSharedArrayBufferContents( + const v8::SharedArrayBuffer::Contents& contents) + : contents_(contents) {} + ~ScopedSharedArrayBufferContents() { free(contents_.Data()); } + void* Data() const { return contents_.Data(); } + size_t ByteLength() const { return contents_.ByteLength(); } + + private: + const v8::SharedArrayBuffer::Contents contents_; +}; + + +THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) { + i::FLAG_harmony_sharedarraybuffer = true; + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope handle_scope(isolate); + + Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024); + CheckInternalFieldsAreZero(ab); + CHECK_EQ(1024, static_cast<int>(ab->ByteLength())); + CHECK(!ab->IsExternal()); + CcTest::heap()->CollectAllGarbage(); + + ScopedSharedArrayBufferContents ab_contents(ab->Externalize()); + CHECK(ab->IsExternal()); + + CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength())); + uint8_t* data = static_cast<uint8_t*>(ab_contents.Data()); + DCHECK(data != NULL); + env->Global()->Set(v8_str("ab"), ab); + + v8::Handle<v8::Value> result = CompileRun("ab.byteLength"); + CHECK_EQ(1024, result->Int32Value()); + + result = CompileRun( + "var u8 = new Uint8Array(ab);" + "u8[0] = 0xFF;" + "u8[1] = 0xAA;" + "u8.length"); + CHECK_EQ(1024, result->Int32Value()); + CHECK_EQ(0xFF, data[0]); + CHECK_EQ(0xAA, data[1]); + data[0] = 0xCC; + data[1] = 0x11; + result = CompileRun("u8[0] + u8[1]"); + CHECK_EQ(0xDD, result->Int32Value()); +} + + +THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) { + i::FLAG_harmony_sharedarraybuffer = true; + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope handle_scope(isolate); + + + v8::Local<v8::Value> result = CompileRun( + "var ab1 = new SharedArrayBuffer(2);" + "var u8_a = new Uint8Array(ab1);" + "u8_a[0] = 0xAA;" + "u8_a[1] = 0xFF; u8_a.buffer"); + Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result); + CheckInternalFieldsAreZero(ab1); + CHECK_EQ(2, static_cast<int>(ab1->ByteLength())); + CHECK(!ab1->IsExternal()); + ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize()); + CHECK(ab1->IsExternal()); + + result = CompileRun("ab1.byteLength"); + CHECK_EQ(2, result->Int32Value()); + result = CompileRun("u8_a[0]"); + CHECK_EQ(0xAA, result->Int32Value()); + result = CompileRun("u8_a[1]"); + CHECK_EQ(0xFF, result->Int32Value()); + result = CompileRun( + "var u8_b = new Uint8Array(ab1);" + "u8_b[0] = 0xBB;" + "u8_a[0]"); + CHECK_EQ(0xBB, result->Int32Value()); + result = CompileRun("u8_b[1]"); + CHECK_EQ(0xFF, result->Int32Value()); + + CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength())); + uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data()); + CHECK_EQ(0xBB, ab1_data[0]); + CHECK_EQ(0xFF, ab1_data[1]); + ab1_data[0] = 0xCC; + ab1_data[1] = 0x11; + result = CompileRun("u8_a[0] + u8_a[1]"); + CHECK_EQ(0xDD, result->Int32Value()); +} + + +THREADED_TEST(SharedArrayBuffer_External) { + i::FLAG_harmony_sharedarraybuffer = true; + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope handle_scope(isolate); + + i::ScopedVector<uint8_t> my_data(100); + memset(my_data.start(), 0, 100); + Local<v8::SharedArrayBuffer> ab3 = + v8::SharedArrayBuffer::New(isolate, my_data.start(), 100); + CheckInternalFieldsAreZero(ab3); + CHECK_EQ(100, static_cast<int>(ab3->ByteLength())); + CHECK(ab3->IsExternal()); + + env->Global()->Set(v8_str("ab3"), ab3); + + v8::Handle<v8::Value> result = CompileRun("ab3.byteLength"); + CHECK_EQ(100, result->Int32Value()); + + result = CompileRun( + "var u8_b = new Uint8Array(ab3);" + "u8_b[0] = 0xBB;" + "u8_b[1] = 0xCC;" + "u8_b.length"); + CHECK_EQ(100, result->Int32Value()); + CHECK_EQ(0xBB, my_data[0]); + CHECK_EQ(0xCC, my_data[1]); + my_data[0] = 0xCC; + my_data[1] = 0x11; + result = CompileRun("u8_b[0] + u8_b[1]"); + CHECK_EQ(0xDD, result->Int32Value()); +} + + THREADED_TEST(HiddenProperties) { LocalContext env; v8::Isolate* isolate = env->GetIsolate(); @@ -3934,7 +4012,7 @@ THREADED_TEST(ScriptException) { LocalContext env; v8::HandleScope scope(env->GetIsolate()); Local<Script> script = v8_compile("throw 'panama!';"); - v8::TryCatch try_catch; + v8::TryCatch try_catch(env->GetIsolate()); Local<Value> result = script->Run(); CHECK(result.IsEmpty()); CHECK(try_catch.HasCaught()); @@ -3947,7 +4025,7 @@ TEST(TryCatchCustomException) { LocalContext env; v8::Isolate* isolate = env->GetIsolate(); v8::HandleScope scope(isolate); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun( "function CustomError() { this.a = 'b'; }" "(function f() { throw new CustomError(); })();"); @@ -4039,8 +4117,9 @@ TEST(MessageHandler2) { static void check_message_3(v8::Handle<v8::Message> message, v8::Handle<Value> data) { CHECK(message->IsSharedCrossOrigin()); - CHECK(message->GetScriptOrigin().ResourceIsSharedCrossOrigin()->Value()); - CHECK(message->GetScriptOrigin().ResourceIsEmbedderDebugScript()->Value()); + CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin()); + CHECK(message->GetScriptOrigin().Options().IsEmbedderDebugScript()); + CHECK(message->GetScriptOrigin().Options().IsOpaque()); CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue()); CHECK_EQ(7.40, message->GetScriptOrigin().SourceMapUrl()->NumberValue()); message_received = true; @@ -4057,7 +4136,7 @@ TEST(MessageHandler3) { v8::ScriptOrigin origin = v8::ScriptOrigin( v8_str("6.75"), v8::Integer::New(isolate, 1), v8::Integer::New(isolate, 2), v8::True(isolate), Handle<v8::Integer>(), - v8::True(isolate), v8_str("7.40")); + v8::True(isolate), v8_str("7.40"), v8::True(isolate)); v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"), &origin); script->Run(); @@ -4117,11 +4196,11 @@ TEST(MessageHandler5) { CHECK(!message_received); v8::V8::AddMessageListener(check_message_5a); LocalContext context; - v8::ScriptOrigin origin = + v8::ScriptOrigin origin1 = v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1), v8::Integer::New(isolate, 2), v8::True(isolate)); v8::Handle<v8::Script> script = - Script::Compile(v8_str("throw 'error'"), &origin); + Script::Compile(v8_str("throw 'error'"), &origin1); script->Run(); CHECK(message_received); // clear out the message listener @@ -4129,9 +4208,10 @@ TEST(MessageHandler5) { message_received = false; v8::V8::AddMessageListener(check_message_5b); - origin = v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1), - v8::Integer::New(isolate, 2), v8::False(isolate)); - script = Script::Compile(v8_str("throw 'error'"), &origin); + v8::ScriptOrigin origin2 = + v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1), + v8::Integer::New(isolate, 2), v8::False(isolate)); + script = Script::Compile(v8_str("throw 'error'"), &origin2); script->Run(); CHECK(message_received); // clear out the message listener @@ -4277,7 +4357,7 @@ THREADED_TEST(PropertyAttributes) { Local<Value> fake_prop = v8_num(1); CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop)); // exception - TryCatch try_catch; + TryCatch try_catch(context->GetIsolate()); Local<Value> exception = CompileRun("({ toString: function() { throw 'exception';} })"); CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception)); @@ -4672,7 +4752,7 @@ void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) { return; } v8::HandleScope scope(args.GetIsolate()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(args.GetIsolate()); Local<Value> result = CompileRun(args[0]->ToString(args.GetIsolate())); CHECK(!try_catch.HasCaught() || result.IsEmpty()); args.GetReturnValue().Set(try_catch.HasCaught()); @@ -4705,7 +4785,7 @@ THREADED_TEST(APIThrowTryCatch) { templ->Set(v8_str("ThrowFromC"), v8::FunctionTemplate::New(isolate, ThrowFromC)); LocalContext context(0, templ); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun("ThrowFromC();"); CHECK(try_catch.HasCaught()); } @@ -4870,6 +4950,26 @@ TEST(CustomErrorMessage) { } +static void check_custom_rethrowing_message(v8::Handle<v8::Message> message, + v8::Handle<v8::Value> data) { + const char* uncaught_error = "Uncaught exception"; + CHECK(message->Get()->Equals(v8_str(uncaught_error))); +} + + +TEST(CustomErrorRethrowsOnToString) { + LocalContext context; + v8::HandleScope scope(context->GetIsolate()); + v8::V8::AddMessageListener(check_custom_rethrowing_message); + + CompileRun( + "var e = { toString: function() { throw e; } };" + "try { throw e; } finally {}"); + + v8::V8::RemoveMessageListeners(check_custom_rethrowing_message); +} + + static void receive_message(v8::Handle<v8::Message> message, v8::Handle<v8::Value> data) { message->Get(); @@ -4901,7 +5001,7 @@ TEST(APIThrowMessageAndVerboseTryCatch) { templ->Set(v8_str("ThrowFromC"), v8::FunctionTemplate::New(isolate, ThrowFromC)); LocalContext context(0, templ); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); try_catch.SetVerbose(true); Local<Value> result = CompileRun("ThrowFromC();"); CHECK(try_catch.HasCaught()); @@ -4916,7 +5016,7 @@ TEST(APIStackOverflowAndVerboseTryCatch) { LocalContext context; v8::HandleScope scope(context->GetIsolate()); v8::V8::AddMessageListener(receive_message); - v8::TryCatch try_catch; + v8::TryCatch try_catch(context->GetIsolate()); try_catch.SetVerbose(true); Local<Value> result = CompileRun("function foo() { foo(); } foo();"); CHECK(try_catch.HasCaught()); @@ -4934,7 +5034,7 @@ THREADED_TEST(ExternalScriptException) { v8::FunctionTemplate::New(isolate, ThrowFromC)); LocalContext context(0, templ); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';"); CHECK(result.IsEmpty()); CHECK(try_catch.HasCaught()); @@ -4956,7 +5056,7 @@ void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) { Local<Value> fun = global->Get(v8_str("JSThrowCountDown")); v8::Handle<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]}; if (count % cInterval == 0) { - v8::TryCatch try_catch; + v8::TryCatch try_catch(args.GetIsolate()); Local<Value> result = fun.As<Function>()->Call(global, 4, argv); int expected = args[3]->Int32Value(); if (try_catch.HasCaught()) { @@ -4993,7 +5093,7 @@ void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) { THREADED_TEST(EvalInTryFinally) { LocalContext context; v8::HandleScope scope(context->GetIsolate()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(context->GetIsolate()); CompileRun( "(function() {" " try {" @@ -5121,7 +5221,7 @@ THREADED_TEST(ThrowValues) { THREADED_TEST(CatchZero) { LocalContext context; v8::HandleScope scope(context->GetIsolate()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(context->GetIsolate()); CHECK(!try_catch.HasCaught()); CompileRun("throw 10"); CHECK(try_catch.HasCaught()); @@ -5137,7 +5237,7 @@ THREADED_TEST(CatchZero) { THREADED_TEST(CatchExceptionFromWith) { LocalContext context; v8::HandleScope scope(context->GetIsolate()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(context->GetIsolate()); CHECK(!try_catch.HasCaught()); CompileRun("var o = {}; with (o) { throw 42; }"); CHECK(try_catch.HasCaught()); @@ -5147,7 +5247,7 @@ THREADED_TEST(CatchExceptionFromWith) { THREADED_TEST(TryCatchAndFinallyHidingException) { LocalContext context; v8::HandleScope scope(context->GetIsolate()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(context->GetIsolate()); CHECK(!try_catch.HasCaught()); CompileRun("function f(k) { try { this[k]; } finally { return 0; } };"); CompileRun("f({toString: function() { throw 42; }});"); @@ -5156,7 +5256,7 @@ THREADED_TEST(TryCatchAndFinallyHidingException) { void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) { - v8::TryCatch try_catch; + v8::TryCatch try_catch(args.GetIsolate()); } @@ -5167,7 +5267,7 @@ THREADED_TEST(TryCatchAndFinally) { context->Global()->Set( v8_str("native_with_try_catch"), v8::FunctionTemplate::New(isolate, WithTryCatch)->GetFunction()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CHECK(!try_catch.HasCaught()); CompileRun( "try {\n" @@ -5181,7 +5281,7 @@ THREADED_TEST(TryCatchAndFinally) { static void TryCatchNested1Helper(int depth) { if (depth > 0) { - v8::TryCatch try_catch; + v8::TryCatch try_catch(CcTest::isolate()); try_catch.SetVerbose(true); TryCatchNested1Helper(depth - 1); CHECK(try_catch.HasCaught()); @@ -5194,7 +5294,7 @@ static void TryCatchNested1Helper(int depth) { static void TryCatchNested2Helper(int depth) { if (depth > 0) { - v8::TryCatch try_catch; + v8::TryCatch try_catch(CcTest::isolate()); try_catch.SetVerbose(true); TryCatchNested2Helper(depth - 1); CHECK(try_catch.HasCaught()); @@ -5212,7 +5312,7 @@ TEST(TryCatchNested) { { // Test nested try-catch with a native throw in the end. - v8::TryCatch try_catch; + v8::TryCatch try_catch(context->GetIsolate()); TryCatchNested1Helper(5); CHECK(try_catch.HasCaught()); CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1")); @@ -5220,7 +5320,7 @@ TEST(TryCatchNested) { { // Test nested try-catch with a JavaScript throw in the end. - v8::TryCatch try_catch; + v8::TryCatch try_catch(context->GetIsolate()); TryCatchNested2Helper(5); CHECK(try_catch.HasCaught()); CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2")); @@ -5243,7 +5343,7 @@ void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) { void TryCatchMixedNestingHelper( const v8::FunctionCallbackInfo<v8::Value>& args) { ApiTestFuzzer::Fuzz(); - v8::TryCatch try_catch; + v8::TryCatch try_catch(args.GetIsolate()); CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0); CHECK(try_catch.HasCaught()); TryCatchMixedNestingCheck(&try_catch); @@ -5260,7 +5360,7 @@ TEST(TryCatchMixedNesting) { v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope scope(isolate); v8::V8::Initialize(); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); Local<ObjectTemplate> templ = ObjectTemplate::New(isolate); templ->Set(v8_str("TryCatchMixedNestingHelper"), v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper)); @@ -5272,7 +5372,7 @@ TEST(TryCatchMixedNesting) { void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) { ApiTestFuzzer::Fuzz(); - v8::TryCatch try_catch; + v8::TryCatch try_catch(args.GetIsolate()); args.GetIsolate()->ThrowException(v8_str("boom")); CHECK(try_catch.HasCaught()); } @@ -5282,7 +5382,7 @@ TEST(TryCatchNative) { v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope scope(isolate); v8::V8::Initialize(); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); Local<ObjectTemplate> templ = ObjectTemplate::New(isolate); templ->Set(v8_str("TryCatchNativeHelper"), v8::FunctionTemplate::New(isolate, TryCatchNativeHelper)); @@ -5295,7 +5395,7 @@ TEST(TryCatchNative) { void TryCatchNativeResetHelper( const v8::FunctionCallbackInfo<v8::Value>& args) { ApiTestFuzzer::Fuzz(); - v8::TryCatch try_catch; + v8::TryCatch try_catch(args.GetIsolate()); args.GetIsolate()->ThrowException(v8_str("boom")); CHECK(try_catch.HasCaught()); try_catch.Reset(); @@ -5307,7 +5407,7 @@ TEST(TryCatchNativeReset) { v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope scope(isolate); v8::V8::Initialize(); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); Local<ObjectTemplate> templ = ObjectTemplate::New(isolate); templ->Set(v8_str("TryCatchNativeResetHelper"), v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper)); @@ -5433,7 +5533,7 @@ THREADED_TEST(DefinePropertyOnAPIAccessor) { CHECK_EQ(result->BooleanValue(), false); // Make sure that it is not possible to redefine again - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); result = script_define->Run(); CHECK(try_catch.HasCaught()); String::Utf8Value exception_value(try_catch.Exception()); @@ -5482,7 +5582,7 @@ THREADED_TEST(DefinePropertyOnDefineGetterSetter) { CHECK_EQ(result->BooleanValue(), false); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); result = script_define->Run(); CHECK(try_catch.HasCaught()); String::Utf8Value exception_value(try_catch.Exception()); @@ -5604,7 +5704,7 @@ THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) { ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"))); { - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun( "Object.defineProperty(obj1, 'x'," "{get: function() { return 'func'; }})"); @@ -5614,7 +5714,7 @@ THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) { 0, strcmp(*exception_value, "TypeError: Cannot redefine property: x")); } { - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun( "Object.defineProperty(obj2, 'x'," "{get: function() { return 'func'; }})"); @@ -7384,10 +7484,10 @@ THREADED_TEST(ToArrayIndex) { str = v8_str("-42"); index = str->ToArrayIndex(); CHECK(index.IsEmpty()); - str = v8_str("4294967295"); + str = v8_str("4294967294"); index = str->ToArrayIndex(); CHECK(!index.IsEmpty()); - CHECK_EQ(4294967295.0, index->Uint32Value()); + CHECK_EQ(4294967294.0, index->Uint32Value()); v8::Handle<v8::Number> num = v8::Number::New(isolate, 1); index = num->ToArrayIndex(); CHECK(!index.IsEmpty()); @@ -7450,7 +7550,7 @@ THREADED_TEST(ExceptionCreateMessage) { v8::Local<v8::Object> global = context->Global(); global->Set(v8_str("throwV8Exception"), fun->GetFunction()); - TryCatch try_catch; + TryCatch try_catch(context->GetIsolate()); CompileRun( "function f1() {\n" " throwV8Exception();\n" @@ -7504,6 +7604,22 @@ THREADED_TEST(ExceptionCreateMessage) { } +THREADED_TEST(ExceptionCreateMessageLength) { + LocalContext context; + v8::HandleScope scope(context->GetIsolate()); + + // Test that the message is not truncated. + TryCatch try_catch(context->GetIsolate()); + CompileRun( + "var message = 'm';" + "while (message.length < 1000) message += message;" + "throw message;"); + CHECK(try_catch.HasCaught()); + + CHECK_LT(1000, try_catch.Message()->Get()->Length()); +} + + static void YGetter(Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) { ApiTestFuzzer::Fuzz(); @@ -7684,7 +7800,7 @@ TEST(ExceptionInNativeScript) { TEST(CompilationErrorUsingTryCatchHandler) { LocalContext env; v8::HandleScope scope(env->GetIsolate()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(env->GetIsolate()); v8_compile("This doesn't &*&@#$&*^ compile."); CHECK(*try_catch.Exception()); CHECK(try_catch.HasCaught()); @@ -7694,7 +7810,7 @@ TEST(CompilationErrorUsingTryCatchHandler) { TEST(TryCatchFinallyUsingTryCatchHandler) { LocalContext env; v8::HandleScope scope(env->GetIsolate()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(env->GetIsolate()); CompileRun("try { throw ''; } catch (e) {}"); CHECK(!try_catch.HasCaught()); CompileRun("try { throw ''; } finally {}"); @@ -7726,7 +7842,7 @@ TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) { templ->Set(v8_str("CEvaluate"), v8::FunctionTemplate::New(isolate, CEvaluate)); LocalContext context(0, templ); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun("try {" " CEvaluate('throw 1;');" "} finally {" @@ -7853,7 +7969,7 @@ THREADED_TEST(SecurityChecks) { Context::Scope scope_env2(env2); // Call cross_domain_call, it should throw an exception - v8::TryCatch try_catch; + v8::TryCatch try_catch(env1->GetIsolate()); Function::Cast(*spy2)->Call(env2->Global(), 0, NULL); CHECK(try_catch.HasCaught()); } @@ -8105,7 +8221,7 @@ TEST(ContextDetachGlobal) { { Local<Value> get_prop = global1->Get(v8_str("getProp")); CHECK(get_prop->IsFunction()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(env1->GetIsolate()); Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL); CHECK(!try_catch.HasCaught()); CHECK_EQ(1, r->Int32Value()); @@ -8229,7 +8345,6 @@ TEST(DetachedAccesses) { } Local<Object> env2_global = env2->Global(); - env2_global->TurnOnAccessCheck(); env2->DetachGlobal(); Local<Value> result; @@ -8639,8 +8754,6 @@ THREADED_TEST(AccessControlGetOwnPropertyNames) { TEST(SuperAccessControl) { i::FLAG_allow_natives_syntax = true; - i::FLAG_harmony_classes = true; - i::FLAG_harmony_object_literals = true; v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope handle_scope(isolate); v8::Handle<v8::ObjectTemplate> obj_template = @@ -8650,7 +8763,7 @@ TEST(SuperAccessControl) { env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance()); { - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun( "var f = { m() { return super.hasOwnProperty; } }.m;" "var m = %ToMethod(f, prohibited);" @@ -8659,7 +8772,7 @@ TEST(SuperAccessControl) { } { - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun( "var f = {m() { return super[42]; } }.m;" "var m = %ToMethod(f, prohibited);" @@ -8668,7 +8781,7 @@ TEST(SuperAccessControl) { } { - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun( "var f = {m() { super.hasOwnProperty = function () {}; } }.m;" "var m = %ToMethod(f, prohibited);" @@ -8677,7 +8790,7 @@ TEST(SuperAccessControl) { } { - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun( "Object.defineProperty(Object.prototype, 'x', { set : function(){}});" "var f = {" @@ -8694,8 +8807,6 @@ TEST(SuperAccessControl) { TEST(Regress470113) { - i::FLAG_harmony_classes = true; - i::FLAG_harmony_object_literals = true; v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope handle_scope(isolate); v8::Handle<v8::ObjectTemplate> obj_template = @@ -8705,7 +8816,7 @@ TEST(Regress470113) { env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance()); { - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun( "'use strict';\n" "class C extends Object {\n" @@ -9446,7 +9557,7 @@ THREADED_TEST(SetPrototypeThrows) { CHECK(o0->SetPrototype(o1)); // If setting the prototype leads to the cycle, SetPrototype should // return false and keep VM in sane state. - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CHECK(!o1->SetPrototype(o0)); CHECK(!try_catch.HasCaught()); DCHECK(!CcTest::i_isolate()->has_pending_exception()); @@ -9466,7 +9577,7 @@ THREADED_TEST(FunctionRemovePrototype) { context->Global()->Set(v8_str("fun"), fun); CHECK(!CompileRun("'prototype' in fun")->BooleanValue()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun("new fun()"); CHECK(try_catch.HasCaught()); @@ -9488,7 +9599,7 @@ THREADED_TEST(GetterSetterExceptions) { "x.__defineGetter__('get', Throw);"); Local<v8::Object> x = Local<v8::Object>::Cast(context->Global()->Get(v8_str("x"))); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); x->Set(v8_str("set"), v8::Integer::New(isolate, 8)); x->Get(v8_str("get")); x->Set(v8_str("set"), v8::Integer::New(isolate, 8)); @@ -9554,7 +9665,7 @@ THREADED_TEST(ConstructorForObject) { instance_template->SetCallAsFunctionHandler(ConstructorCallback); Local<Object> instance = instance_template->NewInstance(); context->Global()->Set(v8_str("obj"), instance); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); Local<Value> value; CHECK(!try_catch.HasCaught()); @@ -9630,7 +9741,7 @@ THREADED_TEST(ConstructorForObject) { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate); Local<Object> instance = instance_template->NewInstance(); context->Global()->Set(v8_str("obj2"), instance); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); Local<Value> value; CHECK(!try_catch.HasCaught()); @@ -9655,7 +9766,7 @@ THREADED_TEST(ConstructorForObject) { instance_template->SetCallAsFunctionHandler(ThrowValue); Local<Object> instance = instance_template->NewInstance(); context->Global()->Set(v8_str("obj3"), instance); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); Local<Value> value; CHECK(!try_catch.HasCaught()); @@ -9680,7 +9791,7 @@ THREADED_TEST(ConstructorForObject) { Local<Function> function = function_template->GetFunction(); Local<Object> instance1 = function; context->Global()->Set(v8_str("obj4"), instance1); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); Local<Value> value; CHECK(!try_catch.HasCaught()); @@ -9764,7 +9875,7 @@ THREADED_TEST(EvalAliasedDynamic) { CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value()); CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(current->GetIsolate()); script = v8_compile( "function f(x) { " " var bar = 2;" @@ -9807,7 +9918,7 @@ THREADED_TEST(CrossEval) { // Check that global variables in current context are not visible in other // context. - v8::TryCatch try_catch; + v8::TryCatch try_catch(CcTest::isolate()); script = v8_compile("var bar = 42; other.eval('bar');"); Local<Value> result = script->Run(); CHECK(try_catch.HasCaught()); @@ -9881,7 +9992,7 @@ THREADED_TEST(EvalInDetachedGlobal) { v8::Handle<v8::Value> x_value = CompileRun("fun('x')"); CHECK_EQ(42, x_value->Int32Value()); context0->DetachGlobal(); - v8::TryCatch catcher; + v8::TryCatch catcher(isolate); x_value = CompileRun("fun('x')"); CHECK_EQ(42, x_value->Int32Value()); context1->Exit(); @@ -9939,7 +10050,7 @@ THREADED_TEST(CallAsFunction) { instance_template->SetCallAsFunctionHandler(call_as_function); Local<v8::Object> instance = t->GetFunction()->NewInstance(); context->Global()->Set(v8_str("obj"), instance); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); Local<Value> value; CHECK(!try_catch.HasCaught()); @@ -9994,7 +10105,7 @@ THREADED_TEST(CallAsFunction) { USE(instance_template); Local<v8::Object> instance = t->GetFunction()->NewInstance(); context->Global()->Set(v8_str("obj2"), instance); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); Local<Value> value; CHECK(!try_catch.HasCaught()); @@ -10025,7 +10136,7 @@ THREADED_TEST(CallAsFunction) { instance_template->SetCallAsFunctionHandler(ThrowValue); Local<v8::Object> instance = t->GetFunction()->NewInstance(); context->Global()->Set(v8_str("obj3"), instance); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); Local<Value> value; CHECK(!try_catch.HasCaught()); @@ -10123,7 +10234,7 @@ THREADED_TEST(CallableObject) { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate); instance_template->SetCallAsFunctionHandler(call_as_function); Local<Object> instance = instance_template->NewInstance(); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CHECK(instance->IsCallable()); CHECK(!try_catch.HasCaught()); @@ -10132,7 +10243,7 @@ THREADED_TEST(CallableObject) { { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate); Local<Object> instance = instance_template->NewInstance(); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CHECK(!instance->IsCallable()); CHECK(!try_catch.HasCaught()); @@ -10143,7 +10254,7 @@ THREADED_TEST(CallableObject) { FunctionTemplate::New(isolate, call_as_function); Local<Function> function = function_template->GetFunction(); Local<Object> instance = function; - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CHECK(instance->IsCallable()); CHECK(!try_catch.HasCaught()); @@ -10153,7 +10264,7 @@ THREADED_TEST(CallableObject) { Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate); Local<Function> function = function_template->GetFunction(); Local<Object> instance = function; - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CHECK(instance->IsCallable()); CHECK(!try_catch.HasCaught()); @@ -10544,7 +10655,7 @@ THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) { v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun( "o.foo = 17;" "var receiver = {};" @@ -10587,7 +10698,7 @@ THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) { v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun( "o.foo = 17;" "var receiver = {};" @@ -10719,7 +10830,7 @@ THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) { v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun( "o.foo = 17;" "var receiver = {};" @@ -10758,7 +10869,7 @@ THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) { v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun( "o.foo = 17;" "var receiver = {};" @@ -10806,7 +10917,7 @@ THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) { "o\n").As<Object>(); CHECK(!with_js_getter.IsEmpty()); - TryCatch try_catch; + TryCatch try_catch(context->GetIsolate()); Local<Value> result = instance->GetRealNamedProperty(v8_str("f")); CHECK(try_catch.HasCaught()); @@ -10859,7 +10970,7 @@ THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) { static void ThrowingCallbackWithTryCatch( const v8::FunctionCallbackInfo<v8::Value>& args) { - TryCatch try_catch; + TryCatch try_catch(args.GetIsolate()); // Verboseness is important: it triggers message delivery which can call into // external code. try_catch.SetVerbose(true); @@ -10874,7 +10985,7 @@ static int call_depth; static void WithTryCatch(Handle<Message> message, Handle<Value> data) { - TryCatch try_catch; + TryCatch try_catch(CcTest::isolate()); } @@ -11163,7 +11274,7 @@ TEST(ObjectProtoToStringES6) { Local<Value> obj = v8::Object::New(isolate); obj.As<v8::Object>()->SetAccessor(toStringTag, ThrowingSymbolAccessorGetter); { - TryCatch try_catch; + TryCatch try_catch(isolate); value = obj.As<v8::Object>()->ObjectProtoToString(); CHECK(value.IsEmpty()); CHECK(try_catch.HasCaught()); @@ -11174,7 +11285,7 @@ TEST(ObjectProtoToStringES6) { obj.As<v8::Object>()->SetAccessor( toStringTag, SymbolAccessorGetterReturnsDefault, 0, v8_str("Test")); { - TryCatch try_catch; + TryCatch try_catch(isolate); value = obj.As<v8::Object>()->ObjectProtoToString(); CHECK(value->IsString() && value->Equals(v8_str("[object Test]"))); CHECK(!try_catch.HasCaught()); @@ -11183,7 +11294,7 @@ TEST(ObjectProtoToStringES6) { // JS @@toStringTag value obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj"); { - TryCatch try_catch; + TryCatch try_catch(isolate); value = obj.As<v8::Object>()->ObjectProtoToString(); CHECK(value->IsString() && value->Equals(v8_str("[object Test]"))); CHECK(!try_catch.HasCaught()); @@ -11195,7 +11306,7 @@ TEST(ObjectProtoToStringES6) { " get: function() { throw 'Test'; }" "}); obj"); { - TryCatch try_catch; + TryCatch try_catch(isolate); value = obj.As<v8::Object>()->ObjectProtoToString(); CHECK(value.IsEmpty()); CHECK(try_catch.HasCaught()); @@ -11207,7 +11318,7 @@ TEST(ObjectProtoToStringES6) { " get: function() { return 'Test'; }" "}); obj"); { - TryCatch try_catch; + TryCatch try_catch(isolate); value = obj.As<v8::Object>()->ObjectProtoToString(); CHECK(value->IsString() && value->Equals(v8_str("[object Test]"))); CHECK(!try_catch.HasCaught()); @@ -11421,7 +11532,8 @@ static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) { v8::Locker nested_locker(isolate); v8::HandleScope scope(isolate); v8::Handle<Value> exception; - { v8::TryCatch try_catch; + { + v8::TryCatch try_catch(isolate); v8::Handle<Value> value = CompileRun(code); CHECK(value.IsEmpty()); CHECK(try_catch.HasCaught()); @@ -12447,7 +12559,7 @@ THREADED_TEST(Regress54) { TEST(CatchStackOverflow) { LocalContext context; v8::HandleScope scope(context->GetIsolate()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(context->GetIsolate()); v8::Handle<v8::Value> result = CompileRun( "function f() {" " return f();" @@ -12462,7 +12574,7 @@ static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script, const char* resource_name, int line_offset) { v8::HandleScope scope(CcTest::isolate()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(CcTest::isolate()); v8::Handle<v8::Value> result = script->Run(); CHECK(result.IsEmpty()); CHECK(try_catch.HasCaught()); @@ -12522,7 +12634,7 @@ THREADED_TEST(TryCatchSourceInfo) { THREADED_TEST(TryCatchSourceInfoForEOSError) { LocalContext context; v8::HandleScope scope(context->GetIsolate()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(context->GetIsolate()); v8::Script::Compile(v8_str("!\n")); CHECK(try_catch.HasCaught()); v8::Handle<v8::Message> message = try_catch.Message(); @@ -12714,71 +12826,6 @@ THREADED_TEST(AccessChecksReenabledCorrectly) { } -THREADED_TEST(TurnOnAccessCheck) { - v8::Isolate* isolate = CcTest::isolate(); - v8::HandleScope handle_scope(isolate); - - // Create an environment with access check to the global object disabled by - // default. - v8::Handle<v8::ObjectTemplate> global_template = - v8::ObjectTemplate::New(isolate); - global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL, - v8::Handle<v8::Value>(), false); - v8::Local<Context> context = Context::New(isolate, NULL, global_template); - Context::Scope context_scope(context); - - // Set up a property and a number of functions. - context->Global()->Set(v8_str("a"), v8_num(1)); - CompileRun("function f1() {return a;}" - "function f2() {return a;}" - "function g1() {return h();}" - "function g2() {return h();}" - "function h() {return 1;}"); - Local<Function> f1 = - Local<Function>::Cast(context->Global()->Get(v8_str("f1"))); - Local<Function> f2 = - Local<Function>::Cast(context->Global()->Get(v8_str("f2"))); - Local<Function> g1 = - Local<Function>::Cast(context->Global()->Get(v8_str("g1"))); - Local<Function> g2 = - Local<Function>::Cast(context->Global()->Get(v8_str("g2"))); - Local<Function> h = - Local<Function>::Cast(context->Global()->Get(v8_str("h"))); - - // Get the global object. - v8::Handle<v8::Object> global = context->Global(); - - // Call f1 one time and f2 a number of times. This will ensure that f1 still - // uses the runtime system to retreive property a whereas f2 uses global load - // inline cache. - CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1))); - for (int i = 0; i < 4; i++) { - CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1))); - } - - // Same for g1 and g2. - CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1))); - for (int i = 0; i < 4; i++) { - CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1))); - } - - // Detach the global and turn on access check. - Local<Object> hidden_global = Local<Object>::Cast( - context->Global()->GetPrototype()); - context->DetachGlobal(); - hidden_global->TurnOnAccessCheck(); - - // Failing access check results in exception. - CHECK(f1->Call(global, 0, NULL).IsEmpty()); - CHECK(f2->Call(global, 0, NULL).IsEmpty()); - CHECK(g1->Call(global, 0, NULL).IsEmpty()); - CHECK(g2->Call(global, 0, NULL).IsEmpty()); - - // No failing access check when just returning a constant. - CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1))); -} - - // Tests that ScriptData can be serialized and deserialized. TEST(PreCompileSerialization) { v8::V8::Initialize(); @@ -13106,7 +13153,7 @@ TEST(RegExpInterruption) { regexp_interruption_data.string_resource = new UC16VectorResource( i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content))); - v8::TryCatch try_catch; + v8::TryCatch try_catch(CcTest::isolate()); timeout_thread.Start(); CompileRun("/((a*)*)*b/.exec(a)"); @@ -13216,8 +13263,9 @@ TEST(ForceSet) { CHECK_EQ(3, global->Get(access_property)->Int32Value()); CHECK_EQ(1, force_set_set_count); CHECK_EQ(2, force_set_get_count); - // Forcing the property to be set should override the accessor without - // calling it + // ForceSet doesn't call the accessors for now. + // TODO(verwaest): Update once blink doesn't rely on ForceSet to delete api + // accessors. global->ForceSet(access_property, v8::Int32::New(isolate, 8)); CHECK_EQ(8, global->Get(access_property)->Int32Value()); CHECK_EQ(1, force_set_set_count); @@ -13226,18 +13274,19 @@ TEST(ForceSet) { TEST(ForceSetWithInterceptor) { - force_set_get_count = 0; - force_set_set_count = 0; - pass_on_get = false; - v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope scope(isolate); v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate); templ->SetHandler(v8::NamedPropertyHandlerConfiguration( ForceSetInterceptGetter, ForceSetInterceptSetter)); + pass_on_get = true; LocalContext context(NULL, templ); v8::Handle<v8::Object> global = context->Global(); + force_set_get_count = 0; + force_set_set_count = 0; + pass_on_get = false; + v8::Handle<v8::String> some_property = v8::String::NewFromUtf8(isolate, "a"); CHECK_EQ(0, force_set_set_count); @@ -13276,6 +13325,228 @@ TEST(ForceSetWithInterceptor) { } +TEST(CreateDataProperty) { + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope handle_scope(isolate); + + CompileRun( + "var a = {};" + "var b = [];" + "Object.defineProperty(a, 'foo', {value: 23});" + "Object.defineProperty(a, 'bar', {value: 23, configurable: true});"); + + v8::Local<v8::Object> obj = + v8::Local<v8::Object>::Cast(env->Global()->Get(v8_str("a"))); + v8::Local<v8::Array> arr = + v8::Local<v8::Array>::Cast(env->Global()->Get(v8_str("b"))); + { + // Can't change a non-configurable properties. + v8::TryCatch try_catch(isolate); + CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"), + v8::Integer::New(isolate, 42)).FromJust()); + CHECK(!try_catch.HasCaught()); + CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"), + v8::Integer::New(isolate, 42)).FromJust()); + CHECK(!try_catch.HasCaught()); + v8::Local<v8::Value> val = + obj->Get(env.local(), v8_str("bar")).ToLocalChecked(); + CHECK(val->IsNumber()); + CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust()); + } + + { + // Set a regular property. + v8::TryCatch try_catch(isolate); + CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"), + v8::Integer::New(isolate, 42)).FromJust()); + CHECK(!try_catch.HasCaught()); + v8::Local<v8::Value> val = + obj->Get(env.local(), v8_str("blub")).ToLocalChecked(); + CHECK(val->IsNumber()); + CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust()); + } + + { + // Set an indexed property. + v8::TryCatch try_catch(isolate); + CHECK(obj->CreateDataProperty(env.local(), v8_str("1"), + v8::Integer::New(isolate, 42)).FromJust()); + CHECK(!try_catch.HasCaught()); + v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked(); + CHECK(val->IsNumber()); + CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust()); + } + + { + // Special cases for arrays. + v8::TryCatch try_catch(isolate); + CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"), + v8::Integer::New(isolate, 1)).FromJust()); + CHECK(!try_catch.HasCaught()); + } + { + // Special cases for arrays: index exceeds the array's length + v8::TryCatch try_catch(isolate); + CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23)) + .FromJust()); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(2U, arr->Length()); + v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked(); + CHECK(val->IsNumber()); + CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust()); + + // Set an existing entry. + CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42)) + .FromJust()); + CHECK(!try_catch.HasCaught()); + val = arr->Get(env.local(), 0).ToLocalChecked(); + CHECK(val->IsNumber()); + CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust()); + } + + CompileRun("Object.freeze(a);"); + { + // Can't change non-extensible objects. + v8::TryCatch try_catch(isolate); + CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"), + v8::Integer::New(isolate, 42)).FromJust()); + CHECK(!try_catch.HasCaught()); + } + + v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate); + templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL); + v8::Local<v8::Object> access_checked = + templ->NewInstance(env.local()).ToLocalChecked(); + { + v8::TryCatch try_catch(isolate); + CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"), + v8::Integer::New(isolate, 42)) + .IsNothing()); + CHECK(try_catch.HasCaught()); + } +} + + +TEST(DefineOwnProperty) { + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope handle_scope(isolate); + + CompileRun( + "var a = {};" + "var b = [];" + "Object.defineProperty(a, 'foo', {value: 23});" + "Object.defineProperty(a, 'bar', {value: 23, configurable: true});"); + + v8::Local<v8::Object> obj = + v8::Local<v8::Object>::Cast(env->Global()->Get(v8_str("a"))); + v8::Local<v8::Array> arr = + v8::Local<v8::Array>::Cast(env->Global()->Get(v8_str("b"))); + { + // Can't change a non-configurable properties. + v8::TryCatch try_catch(isolate); + CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"), + v8::Integer::New(isolate, 42)).FromJust()); + CHECK(!try_catch.HasCaught()); + CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"), + v8::Integer::New(isolate, 42)).FromJust()); + CHECK(!try_catch.HasCaught()); + v8::Local<v8::Value> val = + obj->Get(env.local(), v8_str("bar")).ToLocalChecked(); + CHECK(val->IsNumber()); + CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust()); + } + + { + // Set a regular property. + v8::TryCatch try_catch(isolate); + CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"), + v8::Integer::New(isolate, 42)).FromJust()); + CHECK(!try_catch.HasCaught()); + v8::Local<v8::Value> val = + obj->Get(env.local(), v8_str("blub")).ToLocalChecked(); + CHECK(val->IsNumber()); + CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust()); + } + + { + // Set an indexed property. + v8::TryCatch try_catch(isolate); + CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"), + v8::Integer::New(isolate, 42)).FromJust()); + CHECK(!try_catch.HasCaught()); + v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked(); + CHECK(val->IsNumber()); + CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust()); + } + + { + // Special cases for arrays. + v8::TryCatch try_catch(isolate); + CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"), + v8::Integer::New(isolate, 1)).FromJust()); + CHECK(!try_catch.HasCaught()); + } + { + // Special cases for arrays: index exceeds the array's length + v8::TryCatch try_catch(isolate); + CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"), + v8::Integer::New(isolate, 23)).FromJust()); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(2U, arr->Length()); + v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked(); + CHECK(val->IsNumber()); + CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust()); + + // Set an existing entry. + CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"), + v8::Integer::New(isolate, 42)).FromJust()); + CHECK(!try_catch.HasCaught()); + val = arr->Get(env.local(), 0).ToLocalChecked(); + CHECK(val->IsNumber()); + CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust()); + } + + { + // Set a non-writable property. + v8::TryCatch try_catch(isolate); + CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"), + v8::Integer::New(isolate, 42), + v8::ReadOnly).FromJust()); + CHECK(!try_catch.HasCaught()); + v8::Local<v8::Value> val = + obj->Get(env.local(), v8_str("lala")).ToLocalChecked(); + CHECK(val->IsNumber()); + CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust()); + CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes( + env.local(), v8_str("lala")).FromJust()); + CHECK(!try_catch.HasCaught()); + } + + CompileRun("Object.freeze(a);"); + { + // Can't change non-extensible objects. + v8::TryCatch try_catch(isolate); + CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"), + v8::Integer::New(isolate, 42)).FromJust()); + CHECK(!try_catch.HasCaught()); + } + + v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate); + templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL); + v8::Local<v8::Object> access_checked = + templ->NewInstance(env.local()).ToLocalChecked(); + { + v8::TryCatch try_catch(isolate); + CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"), + v8::Integer::New(isolate, 42)) + .IsNothing()); + CHECK(try_catch.HasCaught()); + } +} + + static v8::Local<Context> calling_context0; static v8::Local<Context> calling_context1; static v8::Local<Context> calling_context2; @@ -13789,7 +14060,8 @@ THREADED_TEST(FixedFloat64Array) { } -template <typename ElementType, typename TypedArray, class ExternalArrayClass> +template <typename ElementType, typename TypedArray, class ExternalArrayClass, + class ArrayBufferType> void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low, int64_t high) { const int kElementCount = 50; @@ -13800,8 +14072,8 @@ void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low, v8::Isolate* isolate = env->GetIsolate(); v8::HandleScope handle_scope(isolate); - Local<v8::ArrayBuffer> ab = - v8::ArrayBuffer::New(isolate, backing_store.start(), + Local<ArrayBufferType> ab = + ArrayBufferType::New(isolate, backing_store.start(), (kElementCount + 2) * sizeof(ElementType)); Local<TypedArray> ta = TypedArray::New(ab, 2*sizeof(ElementType), kElementCount); @@ -13822,56 +14094,58 @@ void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low, THREADED_TEST(Uint8Array) { - TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array>( - i::kExternalUint8Array, 0, 0xFF); + TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array, + v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF); } THREADED_TEST(Int8Array) { - TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array>( - i::kExternalInt8Array, -0x80, 0x7F); + TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array, + v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F); } THREADED_TEST(Uint16Array) { - TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::ExternalUint16Array>( - i::kExternalUint16Array, 0, 0xFFFF); + TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::ExternalUint16Array, + v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF); } THREADED_TEST(Int16Array) { - TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array>( - i::kExternalInt16Array, -0x8000, 0x7FFF); + TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array, + v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000, + 0x7FFF); } THREADED_TEST(Uint32Array) { - TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array>( - i::kExternalUint32Array, 0, UINT_MAX); + TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array, + v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX); } THREADED_TEST(Int32Array) { - TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array>( - i::kExternalInt32Array, INT_MIN, INT_MAX); + TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array, + v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN, + INT_MAX); } THREADED_TEST(Float32Array) { - TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array>( - i::kExternalFloat32Array, -500, 500); + TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array, + v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500); } THREADED_TEST(Float64Array) { - TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array>( - i::kExternalFloat64Array, -500, 500); + TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array, + v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500); } THREADED_TEST(Uint8ClampedArray) { TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray, - i::ExternalUint8ClampedArray>( + i::ExternalUint8ClampedArray, v8::ArrayBuffer>( i::kExternalUint8ClampedArray, 0, 0xFF); } @@ -13887,6 +14161,97 @@ THREADED_TEST(DataView) { Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize); + Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize); + CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv); + CHECK_EQ(2u, dv->ByteOffset()); + CHECK_EQ(kSize, static_cast<int>(dv->ByteLength())); + CHECK(ab->Equals(dv->Buffer())); +} + + +THREADED_TEST(SharedUint8Array) { + i::FLAG_harmony_sharedarraybuffer = true; + TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array, + v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF); +} + + +THREADED_TEST(SharedInt8Array) { + i::FLAG_harmony_sharedarraybuffer = true; + TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array, + v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80, + 0x7F); +} + + +THREADED_TEST(SharedUint16Array) { + i::FLAG_harmony_sharedarraybuffer = true; + TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::ExternalUint16Array, + v8::SharedArrayBuffer>(i::kExternalUint16Array, 0, + 0xFFFF); +} + + +THREADED_TEST(SharedInt16Array) { + i::FLAG_harmony_sharedarraybuffer = true; + TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array, + v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000, + 0x7FFF); +} + + +THREADED_TEST(SharedUint32Array) { + i::FLAG_harmony_sharedarraybuffer = true; + TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array, + v8::SharedArrayBuffer>(i::kExternalUint32Array, 0, + UINT_MAX); +} + + +THREADED_TEST(SharedInt32Array) { + i::FLAG_harmony_sharedarraybuffer = true; + TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array, + v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN, + INT_MAX); +} + + +THREADED_TEST(SharedFloat32Array) { + i::FLAG_harmony_sharedarraybuffer = true; + TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array, + v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500, + 500); +} + + +THREADED_TEST(SharedFloat64Array) { + i::FLAG_harmony_sharedarraybuffer = true; + TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array, + v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500, + 500); +} + + +THREADED_TEST(SharedUint8ClampedArray) { + i::FLAG_harmony_sharedarraybuffer = true; + TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray, + i::ExternalUint8ClampedArray, v8::SharedArrayBuffer>( + i::kExternalUint8ClampedArray, 0, 0xFF); +} + + +THREADED_TEST(SharedDataView) { + i::FLAG_harmony_sharedarraybuffer = true; + const int kSize = 50; + + i::ScopedVector<uint8_t> backing_store(kSize + 2); + + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope handle_scope(isolate); + + Local<v8::SharedArrayBuffer> ab = + v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize); Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize); CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv); @@ -13949,7 +14314,7 @@ THREADED_TEST(ScriptContextDependence) { THREADED_TEST(StackTrace) { LocalContext context; v8::HandleScope scope(context->GetIsolate()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(context->GetIsolate()); const char *source = "function foo() { FAIL.FAIL; }; foo();"; v8::Handle<v8::String> src = v8::String::NewFromUtf8(context->GetIsolate(), source); @@ -14928,7 +15293,7 @@ TEST(DynamicWithSourceURLInStackTraceString) { i::ScopedVector<char> code(1024); i::SNPrintF(code, source, "//# sourceURL=source_url"); - v8::TryCatch try_catch; + v8::TryCatch try_catch(context->GetIsolate()); CompileRunWithOrigin(code.start(), "", 0, 0); CHECK(try_catch.HasCaught()); v8::String::Utf8Value stack(try_catch.StackTrace()); @@ -14949,7 +15314,7 @@ TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) { "outer();\n" "//# sourceURL=outer_url"; - v8::TryCatch try_catch; + v8::TryCatch try_catch(context->GetIsolate()); CompileRun(source); CHECK(try_catch.HasCaught()); @@ -14973,7 +15338,7 @@ TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) { "outer();\n" "//# sourceURL=outer_url"; - v8::TryCatch try_catch; + v8::TryCatch try_catch(context->GetIsolate()); CompileRun(source); CHECK(try_catch.HasCaught()); @@ -14996,6 +15361,7 @@ static void CreateGarbageInOldSpace() { // Test that idle notification can be handled and eventually collects garbage. TEST(TestIdleNotification) { + if (!i::FLAG_incremental_marking) return; const intptr_t MB = 1024 * 1024; const double IdlePauseInSeconds = 1.0; LocalContext env; @@ -15006,6 +15372,9 @@ TEST(TestIdleNotification) { CHECK_GT(size_with_garbage, initial_size + MB); bool finished = false; for (int i = 0; i < 200 && !finished; i++) { + if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) { + CcTest::heap()->StartIdleIncrementalMarking(); + } finished = env->GetIsolate()->IdleNotificationDeadline( (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() / static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) + @@ -15284,9 +15653,6 @@ TEST(ExternalInternalizedStringCollectedAtTearDown) { TEST(ExternalInternalizedStringCollectedAtGC) { - // TODO(mvstanton): vector ics need weak support. - if (i::FLAG_vector_ics) return; - int destroyed = 0; { LocalContext env; v8::HandleScope handle_scope(env->GetIsolate()); @@ -15345,7 +15711,7 @@ THREADED_TEST(QuietSignalingNaNs) { LocalContext context; v8::Isolate* isolate = context->GetIsolate(); v8::HandleScope scope(isolate); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); // Special double values. double snan = DoubleFromBits(0x7ff00000, 0x00000001); @@ -15432,7 +15798,7 @@ THREADED_TEST(QuietSignalingNaNs) { static void SpaghettiIncident( const v8::FunctionCallbackInfo<v8::Value>& args) { v8::HandleScope scope(args.GetIsolate()); - v8::TryCatch tc; + v8::TryCatch tc(args.GetIsolate()); v8::Handle<v8::String> str(args[0]->ToString(args.GetIsolate())); USE(str); if (tc.HasCaught()) @@ -15449,7 +15815,7 @@ THREADED_TEST(SpaghettiStackReThrow) { context->Global()->Set( v8::String::NewFromUtf8(isolate, "s"), v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun( "var i = 0;" "var o = {" @@ -15535,7 +15901,7 @@ TEST(Regress528) { v8::Local<Context> context = Context::New(isolate); context->Enter(); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun(source_exception); CHECK(try_catch.HasCaught()); v8::Handle<v8::Message> message = try_catch.Message(); @@ -15566,7 +15932,8 @@ THREADED_TEST(ScriptOrigin) { v8::Integer::New(env->GetIsolate(), 1), v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()), v8::Handle<v8::Integer>(), v8::True(env->GetIsolate()), - v8::String::NewFromUtf8(env->GetIsolate(), "http://sourceMapUrl")); + v8::String::NewFromUtf8(env->GetIsolate(), "http://sourceMapUrl"), + v8::True(env->GetIsolate())); v8::Handle<v8::String> script = v8::String::NewFromUtf8( env->GetIsolate(), "function f() {}\n\nfunction g() {}"); v8::Script::Compile(script, &origin)->Run(); @@ -15579,8 +15946,9 @@ THREADED_TEST(ScriptOrigin) { CHECK_EQ(0, strcmp("test", *v8::String::Utf8Value(script_origin_f.ResourceName()))); CHECK_EQ(1, script_origin_f.ResourceLineOffset()->Int32Value()); - CHECK(script_origin_f.ResourceIsSharedCrossOrigin()->Value()); - CHECK(script_origin_f.ResourceIsEmbedderDebugScript()->Value()); + CHECK(script_origin_f.Options().IsSharedCrossOrigin()); + CHECK(script_origin_f.Options().IsEmbedderDebugScript()); + CHECK(script_origin_f.Options().IsOpaque()); printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined()); CHECK_EQ(0, strcmp("http://sourceMapUrl", @@ -15590,8 +15958,9 @@ THREADED_TEST(ScriptOrigin) { CHECK_EQ(0, strcmp("test", *v8::String::Utf8Value(script_origin_g.ResourceName()))); CHECK_EQ(1, script_origin_g.ResourceLineOffset()->Int32Value()); - CHECK(script_origin_g.ResourceIsSharedCrossOrigin()->Value()); - CHECK(script_origin_g.ResourceIsEmbedderDebugScript()->Value()); + CHECK(script_origin_g.Options().IsSharedCrossOrigin()); + CHECK(script_origin_g.Options().IsEmbedderDebugScript()); + CHECK(script_origin_g.Options().IsOpaque()); CHECK_EQ(0, strcmp("http://sourceMapUrl", *v8::String::Utf8Value(script_origin_g.SourceMapUrl()))); } @@ -16419,6 +16788,8 @@ void FailedAccessCheckCallbackGC(Local<v8::Object> target, v8::AccessType type, Local<v8::Value> data) { CcTest::heap()->CollectAllGarbage(); + CcTest::isolate()->ThrowException( + v8::Exception::Error(v8_str("cross context"))); } @@ -16437,7 +16808,7 @@ TEST(GCInFailedAccessCheckCallback) { v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate); global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL, - v8::Handle<v8::Value>(), false); + v8::Handle<v8::Value>()); // Create a context and set an x property on it's global object. LocalContext context0(NULL, global_template); @@ -16449,28 +16820,42 @@ TEST(GCInFailedAccessCheckCallback) { LocalContext context1(NULL, global_template); context1->Global()->Set(v8_str("other"), global0); + v8::TryCatch try_catch(isolate); + // Get property with failed access check. - ExpectUndefined("other.x"); + CHECK(CompileRun("other.x").IsEmpty()); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); // Get element with failed access check. - ExpectUndefined("other[0]"); + CHECK(CompileRun("other[0]").IsEmpty()); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); // Set property with failed access check. - v8::Handle<v8::Value> result = CompileRun("other.x = new Object()"); - CHECK(result->IsObject()); + CHECK(CompileRun("other.x = new Object()").IsEmpty()); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); // Set element with failed access check. - result = CompileRun("other[0] = new Object()"); - CHECK(result->IsObject()); + CHECK(CompileRun("other[0] = new Object()").IsEmpty()); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); // Get property attribute with failed access check. - ExpectFalse("\'x\' in other"); + CHECK(CompileRun("\'x\' in other").IsEmpty()); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); // Get property attribute for element with failed access check. - ExpectFalse("0 in other"); + CHECK(CompileRun("0 in other").IsEmpty()); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); // Delete property. - ExpectFalse("delete other.x"); + CHECK(CompileRun("delete other.x").IsEmpty()); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); // Delete element. CHECK_EQ(false, global0->Delete(0)); @@ -16480,15 +16865,25 @@ TEST(GCInFailedAccessCheckCallback) { global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x"))); // Define JavaScript accessor. - ExpectUndefined("Object.prototype.__defineGetter__.call(" - " other, \'x\', function() { return 42; })"); + CHECK(CompileRun( + "Object.prototype.__defineGetter__.call(" + " other, \'x\', function() { return 42; })").IsEmpty()); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); // LookupAccessor. - ExpectUndefined("Object.prototype.__lookupGetter__.call(" - " other, \'x\')"); + CHECK(CompileRun( + "Object.prototype.__lookupGetter__.call(" + " other, \'x\')").IsEmpty()); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); // HasOwnElement. - ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')"); + CHECK(CompileRun( + "Object.prototype.hasOwnProperty.call(" + "other, \'0\')").IsEmpty()); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); CHECK_EQ(false, global0->HasRealIndexedProperty(0)); CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x"))); @@ -17145,7 +17540,7 @@ TEST(RegExp) { v8::Handle<v8::Value> value(CompileRun("re.property")); CHECK_EQ(32, value->Int32Value()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(context->GetIsolate()); re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone); CHECK(re.IsEmpty()); CHECK(try_catch.HasCaught()); @@ -17485,7 +17880,7 @@ void CheckCodeGenerationAllowed() { void CheckCodeGenerationDisallowed() { - TryCatch try_catch; + TryCatch try_catch(CcTest::isolate()); Handle<Value> result = CompileRun("eval('42')"); CHECK(result.IsEmpty()); @@ -17548,7 +17943,7 @@ THREADED_TEST(AllowCodeGenFromStrings) { TEST(SetErrorMessageForCodeGenFromStrings) { LocalContext context; v8::HandleScope scope(context->GetIsolate()); - TryCatch try_catch; + TryCatch try_catch(context->GetIsolate()); Handle<String> message = v8_str("Message") ; Handle<String> expected_message = v8_str("Uncaught EvalError: Message"); @@ -17575,7 +17970,7 @@ THREADED_TEST(CallAPIFunctionOnNonObject) { v8::FunctionTemplate::New(isolate, NonObjectThis); Handle<Function> function = templ->GetFunction(); context->Global()->Set(v8_str("f"), function); - TryCatch try_catch; + TryCatch try_catch(isolate); CompileRun("f.call(2)"); } @@ -18024,7 +18419,7 @@ TEST(RunMicrotasksIgnoresThrownExceptions) { Function::New(isolate, MicrotaskExceptionOne)); isolate->EnqueueMicrotask( Function::New(isolate, MicrotaskExceptionTwo)); - TryCatch try_catch; + TryCatch try_catch(isolate); CompileRun("1+1;"); CHECK(!try_catch.HasCaught()); CHECK_EQ(1, CompileRun("exception1Calls")->Int32Value()); @@ -18345,7 +18740,7 @@ static void CheckInstanceCheckedResult(int getters, int setters, static void CheckInstanceCheckedAccessors(bool expects_callbacks) { instance_checked_getter_count = 0; instance_checked_setter_count = 0; - TryCatch try_catch; + TryCatch try_catch(CcTest::isolate()); // Test path through generic runtime code. CompileRun("obj.foo"); @@ -18493,7 +18888,7 @@ TEST(TryFinallyMessage) { // Test that the original error message is not lost if there is a // recursive call into Javascript is done in the finally block, e.g. to // initialize an IC. (crbug.com/129171) - TryCatch try_catch; + TryCatch try_catch(context->GetIsolate()); const char* trigger_ic = "try { \n" " throw new Error('test'); \n" @@ -18511,7 +18906,7 @@ TEST(TryFinallyMessage) { { // Test that the original exception message is indeed overwritten if // a new error is thrown in the finally block. - TryCatch try_catch; + TryCatch try_catch(context->GetIsolate()); const char* throw_again = "try { \n" " throw new Error('test'); \n" @@ -18681,7 +19076,7 @@ THREADED_TEST(Regress137496) { // Compile a try-finally clause where the finally block causes a GC // while there still is a message pending for external reporting. - TryCatch try_catch; + TryCatch try_catch(context->GetIsolate()); try_catch.SetVerbose(true); CompileRun("try { throw new Error(); } finally { gc(); }"); CHECK(try_catch.HasCaught()); @@ -18859,16 +19254,6 @@ TEST(JSONStringifyAccessCheck) { CHECK(CompileRun("JSON.stringify(other)").IsEmpty()); CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty()); CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty()); - - v8::Handle<v8::Array> array = v8::Array::New(isolate, 2); - array->Set(0, v8_str("a")); - array->Set(1, v8_str("b")); - context1->Global()->Set(v8_str("array"), array); - ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]"); - array->TurnOnAccessCheck(); - CHECK(CompileRun("JSON.stringify(array)").IsEmpty()); - CHECK(CompileRun("JSON.stringify([array])").IsEmpty()); - CHECK(CompileRun("JSON.stringify({'a' : array})").IsEmpty()); } } @@ -18924,6 +19309,7 @@ void CheckCorrectThrow(const char* script) { TEST(AccessCheckThrows) { i::FLAG_allow_natives_syntax = true; + i::FLAG_turbo_try_catch = true; v8::V8::Initialize(); v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows); v8::Isolate* isolate = CcTest::isolate(); @@ -18953,7 +19339,8 @@ TEST(AccessCheckThrows) { context1->Global()->Set(v8_str("has_own_property"), has_own_property_fun->GetFunction()); - { v8::TryCatch try_catch; + { + v8::TryCatch try_catch(isolate); access_check_fail_thrown = false; CompileRun("other.x;"); CHECK(access_check_fail_thrown); @@ -19570,7 +19957,7 @@ class ApiCallOptimizationChecker { "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n" "check(wrap_set());\n", wrap_function.start(), key, key, key, key, key, key); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun(source.start()); DCHECK(!try_catch.HasCaught()); CHECK_EQ(9, count); @@ -19994,7 +20381,7 @@ TEST(ThrowOnJavascriptExecution) { LocalContext context; v8::Isolate* isolate = context->GetIsolate(); v8::HandleScope scope(isolate); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); v8::Isolate::DisallowJavascriptExecutionScope throw_js( isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE); CompileRun("1+1"); @@ -20054,7 +20441,7 @@ TEST(CaptureStackTraceForStackOverflow) { v8::HandleScope scope(isolate); V8::SetCaptureStackTraceForUncaughtExceptions( true, 10, v8::StackTrace::kDetailed); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun("(function f(x) { f(x+1); })(0)"); CHECK(try_catch.HasCaught()); } @@ -20295,7 +20682,7 @@ void RunStreamingTest(const char** chunks, LocalContext env; v8::Isolate* isolate = env->GetIsolate(); v8::HandleScope scope(isolate); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks), encoding); @@ -20568,6 +20955,7 @@ TEST(StreamingWithDebuggingDoesNotProduceParserCache) { CompileRun("function break_here() { }"); i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast( v8::Utils::OpenHandle(*env->Global()->Get(v8_str("break_here")))); + EnableDebugger(); v8::internal::Debug* debug = CcTest::i_isolate()->debug(); int position = 0; debug->SetBreakPoint(func, i::Handle<i::Object>(v8::internal::Smi::FromInt(1), @@ -20588,6 +20976,7 @@ TEST(StreamingWithDebuggingDoesNotProduceParserCache) { // Check that we got no cached data. CHECK(source.GetCachedData() == NULL); + DisableDebugger(); } @@ -20667,7 +21056,7 @@ TEST(StreamingWithHarmonyScopes) { // variable again. const char* chunks[] = {"\"use strict\"; let x = 2;", NULL}; - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); v8::ScriptCompiler::StreamedSource source( new TestSourceStream(chunks), v8::ScriptCompiler::StreamedSource::ONE_BYTE); @@ -20695,6 +21084,58 @@ TEST(StreamingWithHarmonyScopes) { } +TEST(CodeCache) { + v8::Isolate::CreateParams create_params; + create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); + + const char* source = "Math.sqrt(4)"; + const char* origin = "code cache test"; + v8::ScriptCompiler::CachedData* cache; + + v8::Isolate* isolate1 = v8::Isolate::New(create_params); + { + v8::Isolate::Scope iscope(isolate1); + v8::HandleScope scope(isolate1); + v8::Local<v8::Context> context = v8::Context::New(isolate1); + v8::Context::Scope cscope(context); + v8::Local<v8::String> source_string = v8_str(source); + v8::ScriptOrigin script_origin(v8_str(origin)); + v8::ScriptCompiler::Source source(source_string, script_origin); + v8::ScriptCompiler::CompileOptions option = + v8::ScriptCompiler::kProduceCodeCache; + v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked(); + int length = source.GetCachedData()->length; + uint8_t* cache_data = new uint8_t[length]; + memcpy(cache_data, source.GetCachedData()->data, length); + cache = new v8::ScriptCompiler::CachedData( + cache_data, length, v8::ScriptCompiler::CachedData::BufferOwned); + } + isolate1->Dispose(); + + v8::Isolate* isolate2 = v8::Isolate::New(create_params); + { + v8::Isolate::Scope iscope(isolate2); + v8::HandleScope scope(isolate2); + v8::Local<v8::Context> context = v8::Context::New(isolate2); + v8::Context::Scope cscope(context); + v8::Local<v8::String> source_string = v8_str(source); + v8::ScriptOrigin script_origin(v8_str(origin)); + v8::ScriptCompiler::Source source(source_string, script_origin, cache); + v8::ScriptCompiler::CompileOptions option = + v8::ScriptCompiler::kConsumeCodeCache; + v8::Local<v8::Script> script; + { + i::DisallowCompilation no_compile( + reinterpret_cast<i::Isolate*>(isolate2)); + script = v8::ScriptCompiler::Compile(context, &source, option) + .ToLocalChecked(); + } + CHECK_EQ(2, script->Run()->ToInt32(isolate2)->Int32Value()); + } + isolate2->Dispose(); +} + + void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) { const char* garbage = "garbage garbage garbage garbage garbage garbage"; const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage); @@ -20782,7 +21223,7 @@ TEST(StringConcatOverflow) { new RandomLengthOneByteResource(i::String::kMaxLength); v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), r); CHECK(!str.IsEmpty()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(CcTest::isolate()); v8::Local<v8::String> result = v8::String::Concat(str, str); CHECK(result.IsEmpty()); CHECK(!try_catch.HasCaught()); @@ -20843,7 +21284,7 @@ TEST(GetPrototypeAccessControl) { env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance()); { - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun( "function f() { %_GetPrototype(prohibited); }" "%OptimizeFunctionOnNextCall(f);" @@ -20883,7 +21324,6 @@ TEST(GetPrototypeHidden) { TEST(ClassPrototypeCreationContext) { - i::FLAG_harmony_classes = true; v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope handle_scope(isolate); LocalContext env; @@ -20927,21 +21367,21 @@ TEST(NewStringRangeError) { if (buffer == NULL) return; memset(buffer, 'A', buffer_size); { - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); char* data = reinterpret_cast<char*>(buffer); CHECK(v8::String::NewFromUtf8(isolate, data, v8::String::kNormalString, length).IsEmpty()); CHECK(!try_catch.HasCaught()); } { - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); uint8_t* data = reinterpret_cast<uint8_t*>(buffer); CHECK(v8::String::NewFromOneByte(isolate, data, v8::String::kNormalString, length).IsEmpty()); CHECK(!try_catch.HasCaught()); } { - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); uint16_t* data = reinterpret_cast<uint16_t*>(buffer); CHECK(v8::String::NewFromTwoByte(isolate, data, v8::String::kNormalString, length).IsEmpty()); @@ -20983,6 +21423,404 @@ TEST(SealHandleScopeNested) { } +static bool access_was_called = false; + + +static bool AccessAlwaysAllowedWithFlag(Local<v8::Object> global, + Local<Value> name, v8::AccessType type, + Local<Value> data) { + access_was_called = true; + return true; +} + + +static bool AccessAlwaysBlockedWithFlag(Local<v8::Object> global, + Local<Value> name, v8::AccessType type, + Local<Value> data) { + access_was_called = true; + return false; +} + + +TEST(StrongModeAccessCheckAllowed) { + i::FLAG_strong_mode = true; + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle<Value> value; + access_was_called = false; + + v8::Handle<v8::ObjectTemplate> obj_template = + v8::ObjectTemplate::New(isolate); + + obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42)); + obj_template->SetAccessCheckCallbacks(AccessAlwaysAllowedWithFlag, NULL); + + // Create an environment + v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template); + context0->Enter(); + v8::Handle<v8::Object> global0 = context0->Global(); + global0->Set(v8_str("object"), obj_template->NewInstance()); + { + v8::TryCatch try_catch(isolate); + value = CompileRun("'use strong'; object.x"); + CHECK(!try_catch.HasCaught()); + CHECK(!access_was_called); + CHECK_EQ(42, value->Int32Value()); + } + { + v8::TryCatch try_catch(isolate); + value = CompileRun("'use strong'; object.foo"); + CHECK(try_catch.HasCaught()); + CHECK(!access_was_called); + } + { + v8::TryCatch try_catch(isolate); + value = CompileRun("'use strong'; object[10]"); + CHECK(try_catch.HasCaught()); + CHECK(!access_was_called); + } + + // Create an environment + v8::Local<Context> context1 = Context::New(isolate); + context1->Enter(); + v8::Handle<v8::Object> global1 = context1->Global(); + global1->Set(v8_str("object"), obj_template->NewInstance()); + { + v8::TryCatch try_catch(isolate); + value = CompileRun("'use strong'; object.x"); + CHECK(!try_catch.HasCaught()); + CHECK(access_was_called); + CHECK_EQ(42, value->Int32Value()); + } + access_was_called = false; + { + v8::TryCatch try_catch(isolate); + value = CompileRun("'use strong'; object.foo"); + CHECK(try_catch.HasCaught()); + CHECK(access_was_called); + } + access_was_called = false; + { + v8::TryCatch try_catch(isolate); + value = CompileRun("'use strong'; object[10]"); + CHECK(try_catch.HasCaught()); + CHECK(access_was_called); + } + + context1->Exit(); + context0->Exit(); +} + + +TEST(StrongModeAccessCheckBlocked) { + i::FLAG_strong_mode = true; + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope handle_scope(isolate); + v8::Handle<Value> value; + access_was_called = false; + + v8::Handle<v8::ObjectTemplate> obj_template = + v8::ObjectTemplate::New(isolate); + + obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42)); + obj_template->SetAccessCheckCallbacks(AccessAlwaysBlockedWithFlag, NULL); + + // Create an environment + v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template); + context0->Enter(); + v8::Handle<v8::Object> global0 = context0->Global(); + global0->Set(v8_str("object"), obj_template->NewInstance()); + { + v8::TryCatch try_catch(isolate); + value = CompileRun("'use strong'; object.x"); + CHECK(!try_catch.HasCaught()); + CHECK(!access_was_called); + CHECK_EQ(42, value->Int32Value()); + } + { + v8::TryCatch try_catch(isolate); + value = CompileRun("'use strong'; object.foo"); + CHECK(try_catch.HasCaught()); + CHECK(!access_was_called); + } + { + v8::TryCatch try_catch(isolate); + value = CompileRun("'use strong'; object[10]"); + CHECK(try_catch.HasCaught()); + CHECK(!access_was_called); + } + + // Create an environment + v8::Local<Context> context1 = Context::New(isolate); + context1->Enter(); + v8::Handle<v8::Object> global1 = context1->Global(); + global1->Set(v8_str("object"), obj_template->NewInstance()); + { + v8::TryCatch try_catch(isolate); + value = CompileRun("'use strong'; object.x"); + CHECK(try_catch.HasCaught()); + CHECK(access_was_called); + } + access_was_called = false; + { + v8::TryCatch try_catch(isolate); + value = CompileRun("'use strong'; object.foo"); + CHECK(try_catch.HasCaught()); + CHECK(access_was_called); + } + access_was_called = false; + { + v8::TryCatch try_catch(isolate); + value = CompileRun("'use strong'; object[10]"); + CHECK(try_catch.HasCaught()); + CHECK(access_was_called); + } + + context1->Exit(); + context0->Exit(); +} + + +TEST(StrongModeArityCallFromApi) { + i::FLAG_strong_mode = true; + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope scope(isolate); + Local<Function> fun; + { + v8::TryCatch try_catch(isolate); + fun = Local<Function>::Cast(CompileRun( + "function f(x) { 'use strong'; }" + "f")); + + CHECK(!try_catch.HasCaught()); + } + + { + v8::TryCatch try_catch(isolate); + fun->Call(v8::Undefined(isolate), 0, nullptr); + CHECK(try_catch.HasCaught()); + } + + { + v8::TryCatch try_catch(isolate); + v8::Handle<Value> args[] = {v8_num(42)}; + fun->Call(v8::Undefined(isolate), arraysize(args), args); + CHECK(!try_catch.HasCaught()); + } + + { + v8::TryCatch try_catch(isolate); + v8::Handle<Value> args[] = {v8_num(42), v8_num(555)}; + fun->Call(v8::Undefined(isolate), arraysize(args), args); + CHECK(!try_catch.HasCaught()); + } +} + + +TEST(StrongModeArityCallFromApi2) { + i::FLAG_strong_mode = true; + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope scope(isolate); + Local<Function> fun; + { + v8::TryCatch try_catch(isolate); + fun = Local<Function>::Cast(CompileRun( + "'use strong';" + "function f(x) {}" + "f")); + + CHECK(!try_catch.HasCaught()); + } + + { + v8::TryCatch try_catch(isolate); + fun->Call(v8::Undefined(isolate), 0, nullptr); + CHECK(try_catch.HasCaught()); + } + + { + v8::TryCatch try_catch(isolate); + v8::Handle<Value> args[] = {v8_num(42)}; + fun->Call(v8::Undefined(isolate), arraysize(args), args); + CHECK(!try_catch.HasCaught()); + } + + { + v8::TryCatch try_catch(isolate); + v8::Handle<Value> args[] = {v8_num(42), v8_num(555)}; + fun->Call(v8::Undefined(isolate), arraysize(args), args); + CHECK(!try_catch.HasCaught()); + } +} + + +TEST(StrongObjectDelete) { + i::FLAG_strong_mode = true; + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope scope(isolate); + Local<Object> obj; + { + v8::TryCatch try_catch; + obj = Local<Object>::Cast(CompileRun( + "'use strong';" + "({});")); + CHECK(!try_catch.HasCaught()); + } + obj->ForceSet(v8_str("foo"), v8_num(1), v8::None); + obj->ForceSet(v8_str("2"), v8_num(1), v8::None); + CHECK(obj->HasOwnProperty(v8_str("foo"))); + CHECK(obj->HasOwnProperty(v8_str("2"))); + CHECK(!obj->Delete(v8_str("foo"))); + CHECK(!obj->Delete(2)); +} + + +static void ExtrasExportsTestRuntimeFunction( + const v8::FunctionCallbackInfo<v8::Value>& args) { + CHECK_EQ(3, args[0]->Int32Value()); + args.GetReturnValue().Set(v8_num(7)); +} + + +TEST(ExtrasExportsObject) { + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope handle_scope(isolate); + LocalContext env; + + // standalone.gypi ensures we include the test-extra.js file, which should + // export the tested functions. + v8::Local<v8::Object> exports = env->GetExtrasExportsObject(); + + auto func = + exports->Get(v8_str("testExtraShouldReturnFive")).As<v8::Function>(); + auto undefined = v8::Undefined(isolate); + auto result = func->Call(undefined, 0, {}).As<v8::Number>(); + CHECK_EQ(5, result->Int32Value()); + + v8::Handle<v8::FunctionTemplate> runtimeFunction = + v8::FunctionTemplate::New(isolate, ExtrasExportsTestRuntimeFunction); + exports->Set(v8_str("runtime"), runtimeFunction->GetFunction()); + func = + exports->Get(v8_str("testExtraShouldCallToRuntime")).As<v8::Function>(); + result = func->Call(undefined, 0, {}).As<v8::Number>(); + CHECK_EQ(7, result->Int32Value()); +} + + +TEST(Map) { + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope handle_scope(isolate); + LocalContext env; + + v8::Local<v8::Map> map = v8::Map::New(isolate); + CHECK(map->IsObject()); + CHECK(map->IsMap()); + CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype"))); + CHECK_EQ(0U, map->Size()); + + v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])"); + CHECK(val->IsMap()); + map = v8::Local<v8::Map>::Cast(val); + CHECK_EQ(2U, map->Size()); + + v8::Local<v8::Array> contents = map->AsArray(); + CHECK_EQ(4U, contents->Length()); + CHECK_EQ(1, contents->Get(0).As<v8::Int32>()->Value()); + CHECK_EQ(2, contents->Get(1).As<v8::Int32>()->Value()); + CHECK_EQ(3, contents->Get(2).As<v8::Int32>()->Value()); + CHECK_EQ(4, contents->Get(3).As<v8::Int32>()->Value()); + + map = v8::Map::FromArray(env.local(), contents).ToLocalChecked(); + CHECK_EQ(2U, map->Size()); + + CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust()); + CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust()); + + CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust()); + CHECK(!map->Has(env.local(), map).FromJust()); + + CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1)) + .ToLocalChecked() + ->Int32Value()); + CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3)) + .ToLocalChecked() + ->Int32Value()); + + CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42)) + .ToLocalChecked() + ->IsUndefined()); + + CHECK(!map->Set(env.local(), map, map).IsEmpty()); + CHECK_EQ(3U, map->Size()); + CHECK(map->Has(env.local(), map).FromJust()); + + CHECK(map->Delete(env.local(), map).FromJust()); + CHECK_EQ(2U, map->Size()); + CHECK(!map->Has(env.local(), map).FromJust()); + CHECK(!map->Delete(env.local(), map).FromJust()); + + map->Clear(); + CHECK_EQ(0U, map->Size()); +} + + +TEST(MapFromArrayOddLength) { + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope handle_scope(isolate); + LocalContext env; + // Odd lengths result in a null MaybeLocal. + Local<v8::Array> contents = v8::Array::New(isolate, 41); + CHECK(v8::Map::FromArray(env.local(), contents).IsEmpty()); +} + + +TEST(Set) { + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope handle_scope(isolate); + LocalContext env; + + v8::Local<v8::Set> set = v8::Set::New(isolate); + CHECK(set->IsObject()); + CHECK(set->IsSet()); + CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype"))); + CHECK_EQ(0U, set->Size()); + + v8::Local<v8::Value> val = CompileRun("new Set([1, 2])"); + CHECK(val->IsSet()); + set = v8::Local<v8::Set>::Cast(val); + CHECK_EQ(2U, set->Size()); + + v8::Local<v8::Array> keys = set->AsArray(); + CHECK_EQ(2U, keys->Length()); + CHECK_EQ(1, keys->Get(0).As<v8::Int32>()->Value()); + CHECK_EQ(2, keys->Get(1).As<v8::Int32>()->Value()); + + set = v8::Set::FromArray(env.local(), keys).ToLocalChecked(); + CHECK_EQ(2U, set->Size()); + + CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust()); + CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust()); + + CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust()); + CHECK(!set->Has(env.local(), set).FromJust()); + + CHECK(!set->Add(env.local(), set).IsEmpty()); + CHECK_EQ(3U, set->Size()); + CHECK(set->Has(env.local(), set).FromJust()); + + CHECK(set->Delete(env.local(), set).FromJust()); + CHECK_EQ(2U, set->Size()); + CHECK(!set->Has(env.local(), set).FromJust()); + CHECK(!set->Delete(env.local(), set).FromJust()); + + set->Clear(); + CHECK_EQ(0U, set->Size()); +} + + TEST(CompatibleReceiverCheckOnCachedICHandler) { v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope scope(isolate); diff --git a/deps/v8/test/cctest/test-assembler-arm.cc b/deps/v8/test/cctest/test-assembler-arm.cc index 059c04ad40..8f93150fad 100644 --- a/deps/v8/test/cctest/test-assembler-arm.cc +++ b/deps/v8/test/cctest/test-assembler-arm.cc @@ -175,17 +175,17 @@ TEST(3) { __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); __ sub(fp, ip, Operand(4)); __ mov(r4, Operand(r0)); - __ ldr(r0, MemOperand(r4, OFFSET_OF(T, i))); + __ ldr(r0, MemOperand(r4, offsetof(T, i))); __ mov(r2, Operand(r0, ASR, 1)); - __ str(r2, MemOperand(r4, OFFSET_OF(T, i))); - __ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c))); + __ str(r2, MemOperand(r4, offsetof(T, i))); + __ ldrsb(r2, MemOperand(r4, offsetof(T, c))); __ add(r0, r2, Operand(r0)); __ mov(r2, Operand(r2, LSL, 2)); - __ strb(r2, MemOperand(r4, OFFSET_OF(T, c))); - __ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s))); + __ strb(r2, MemOperand(r4, offsetof(T, c))); + __ ldrsh(r2, MemOperand(r4, offsetof(T, s))); __ add(r0, r2, Operand(r0)); __ mov(r2, Operand(r2, ASR, 3)); - __ strh(r2, MemOperand(r4, OFFSET_OF(T, s))); + __ strh(r2, MemOperand(r4, offsetof(T, s))); __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); CodeDesc desc; @@ -247,68 +247,68 @@ TEST(4) { __ sub(fp, ip, Operand(4)); __ mov(r4, Operand(r0)); - __ vldr(d6, r4, OFFSET_OF(T, a)); - __ vldr(d7, r4, OFFSET_OF(T, b)); + __ vldr(d6, r4, offsetof(T, a)); + __ vldr(d7, r4, offsetof(T, b)); __ vadd(d5, d6, d7); - __ vstr(d5, r4, OFFSET_OF(T, c)); + __ vstr(d5, r4, offsetof(T, c)); __ vmla(d5, d6, d7); __ vmls(d5, d5, d6); __ vmov(r2, r3, d5); __ vmov(d4, r2, r3); - __ vstr(d4, r4, OFFSET_OF(T, b)); + __ vstr(d4, r4, offsetof(T, b)); // Load t.x and t.y, switch values, and store back to the struct. - __ vldr(s0, r4, OFFSET_OF(T, x)); - __ vldr(s31, r4, OFFSET_OF(T, y)); + __ vldr(s0, r4, offsetof(T, x)); + __ vldr(s31, r4, offsetof(T, y)); __ vmov(s16, s0); __ vmov(s0, s31); __ vmov(s31, s16); - __ vstr(s0, r4, OFFSET_OF(T, x)); - __ vstr(s31, r4, OFFSET_OF(T, y)); + __ vstr(s0, r4, offsetof(T, x)); + __ vstr(s31, r4, offsetof(T, y)); // Move a literal into a register that can be encoded in the instruction. __ vmov(d4, 1.0); - __ vstr(d4, r4, OFFSET_OF(T, e)); + __ vstr(d4, r4, offsetof(T, e)); // Move a literal into a register that requires 64 bits to encode. // 0x3ff0000010000000 = 1.000000059604644775390625 __ vmov(d4, 1.000000059604644775390625); - __ vstr(d4, r4, OFFSET_OF(T, d)); + __ vstr(d4, r4, offsetof(T, d)); // Convert from floating point to integer. __ vmov(d4, 2.0); __ vcvt_s32_f64(s31, d4); - __ vstr(s31, r4, OFFSET_OF(T, i)); + __ vstr(s31, r4, offsetof(T, i)); // Convert from integer to floating point. __ mov(lr, Operand(42)); __ vmov(s31, lr); __ vcvt_f64_s32(d4, s31); - __ vstr(d4, r4, OFFSET_OF(T, f)); + __ vstr(d4, r4, offsetof(T, f)); // Convert from fixed point to floating point. __ mov(lr, Operand(2468)); __ vmov(s8, lr); __ vcvt_f64_s32(d4, 2); - __ vstr(d4, r4, OFFSET_OF(T, j)); + __ vstr(d4, r4, offsetof(T, j)); // Test vabs. - __ vldr(d1, r4, OFFSET_OF(T, g)); + __ vldr(d1, r4, offsetof(T, g)); __ vabs(d0, d1); - __ vstr(d0, r4, OFFSET_OF(T, g)); - __ vldr(d2, r4, OFFSET_OF(T, h)); + __ vstr(d0, r4, offsetof(T, g)); + __ vldr(d2, r4, offsetof(T, h)); __ vabs(d0, d2); - __ vstr(d0, r4, OFFSET_OF(T, h)); + __ vstr(d0, r4, offsetof(T, h)); // Test vneg. - __ vldr(d1, r4, OFFSET_OF(T, m)); + __ vldr(d1, r4, offsetof(T, m)); __ vneg(d0, d1); - __ vstr(d0, r4, OFFSET_OF(T, m)); - __ vldr(d1, r4, OFFSET_OF(T, n)); + __ vstr(d0, r4, offsetof(T, m)); + __ vldr(d1, r4, offsetof(T, n)); __ vneg(d0, d1); - __ vstr(d0, r4, OFFSET_OF(T, n)); + __ vstr(d0, r4, offsetof(T, n)); __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); @@ -647,19 +647,19 @@ TEST(8) { __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); __ sub(fp, ip, Operand(4)); - __ add(r4, r0, Operand(OFFSET_OF(D, a))); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a)))); __ vldm(ia_w, r4, d0, d3); __ vldm(ia_w, r4, d4, d7); - __ add(r4, r0, Operand(OFFSET_OF(D, a))); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a)))); __ vstm(ia_w, r4, d6, d7); __ vstm(ia_w, r4, d0, d5); - __ add(r4, r1, Operand(OFFSET_OF(F, a))); + __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a)))); __ vldm(ia_w, r4, s0, s3); __ vldm(ia_w, r4, s4, s7); - __ add(r4, r1, Operand(OFFSET_OF(F, a))); + __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a)))); __ vstm(ia_w, r4, s6, s7); __ vstm(ia_w, r4, s0, s5); @@ -753,22 +753,22 @@ TEST(9) { __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); __ sub(fp, ip, Operand(4)); - __ add(r4, r0, Operand(OFFSET_OF(D, a))); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a)))); __ vldm(ia, r4, d0, d3); __ add(r4, r4, Operand(4 * 8)); __ vldm(ia, r4, d4, d7); - __ add(r4, r0, Operand(OFFSET_OF(D, a))); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a)))); __ vstm(ia, r4, d6, d7); __ add(r4, r4, Operand(2 * 8)); __ vstm(ia, r4, d0, d5); - __ add(r4, r1, Operand(OFFSET_OF(F, a))); + __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a)))); __ vldm(ia, r4, s0, s3); __ add(r4, r4, Operand(4 * 4)); __ vldm(ia, r4, s4, s7); - __ add(r4, r1, Operand(OFFSET_OF(F, a))); + __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a)))); __ vstm(ia, r4, s6, s7); __ add(r4, r4, Operand(2 * 4)); __ vstm(ia, r4, s0, s5); @@ -863,19 +863,19 @@ TEST(10) { __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); __ sub(fp, ip, Operand(4)); - __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8)); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, h)) + 8)); __ vldm(db_w, r4, d4, d7); __ vldm(db_w, r4, d0, d3); - __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8)); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, h)) + 8)); __ vstm(db_w, r4, d0, d5); __ vstm(db_w, r4, d6, d7); - __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4)); + __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, h)) + 4)); __ vldm(db_w, r4, s4, s7); __ vldm(db_w, r4, s0, s3); - __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4)); + __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, h)) + 4)); __ vstm(db_w, r4, s0, s5); __ vstm(db_w, r4, s6, s7); @@ -951,28 +951,28 @@ TEST(11) { Assembler assm(isolate, NULL, 0); // Test HeapObject untagging. - __ ldr(r1, MemOperand(r0, OFFSET_OF(I, a))); + __ ldr(r1, MemOperand(r0, offsetof(I, a))); __ mov(r1, Operand(r1, ASR, 1), SetCC); __ adc(r1, r1, Operand(r1), LeaveCC, cs); - __ str(r1, MemOperand(r0, OFFSET_OF(I, a))); + __ str(r1, MemOperand(r0, offsetof(I, a))); - __ ldr(r2, MemOperand(r0, OFFSET_OF(I, b))); + __ ldr(r2, MemOperand(r0, offsetof(I, b))); __ mov(r2, Operand(r2, ASR, 1), SetCC); __ adc(r2, r2, Operand(r2), LeaveCC, cs); - __ str(r2, MemOperand(r0, OFFSET_OF(I, b))); + __ str(r2, MemOperand(r0, offsetof(I, b))); // Test corner cases. __ mov(r1, Operand(0xffffffff)); __ mov(r2, Operand::Zero()); __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry. __ adc(r3, r1, Operand(r2)); - __ str(r3, MemOperand(r0, OFFSET_OF(I, c))); + __ str(r3, MemOperand(r0, offsetof(I, c))); __ mov(r1, Operand(0xffffffff)); __ mov(r2, Operand::Zero()); __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry. __ adc(r3, r1, Operand(r2)); - __ str(r3, MemOperand(r0, OFFSET_OF(I, d))); + __ str(r3, MemOperand(r0, offsetof(I, d))); __ mov(pc, Operand(lr)); @@ -1048,9 +1048,9 @@ TEST(13) { // Load a, b, c into d16, d17, d18. __ mov(r4, Operand(r0)); - __ vldr(d16, r4, OFFSET_OF(T, a)); - __ vldr(d17, r4, OFFSET_OF(T, b)); - __ vldr(d18, r4, OFFSET_OF(T, c)); + __ vldr(d16, r4, offsetof(T, a)); + __ vldr(d17, r4, offsetof(T, b)); + __ vldr(d18, r4, offsetof(T, c)); __ vneg(d25, d16); __ vadd(d25, d25, d17); @@ -1066,12 +1066,12 @@ TEST(13) { // Store d16, d17, d18 into a, b, c. __ mov(r4, Operand(r0)); - __ vstr(d16, r4, OFFSET_OF(T, a)); - __ vstr(d17, r4, OFFSET_OF(T, b)); - __ vstr(d18, r4, OFFSET_OF(T, c)); + __ vstr(d16, r4, offsetof(T, a)); + __ vstr(d17, r4, offsetof(T, b)); + __ vstr(d18, r4, offsetof(T, c)); // Load x, y, z into d29-d31. - __ add(r4, r0, Operand(OFFSET_OF(T, x))); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, x)))); __ vldm(ia_w, r4, d29, d31); // Swap d29 and d30 via r registers. @@ -1084,7 +1084,7 @@ TEST(13) { __ vcvt_f64_u32(d31, s1); // Store d29-d31 into x, y, z. - __ add(r4, r0, Operand(OFFSET_OF(T, x))); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, x)))); __ vstm(ia_w, r4, d29, d31); // Move constants into d20, d21, d22 and store into i, j, k. @@ -1094,13 +1094,13 @@ TEST(13) { __ mov(r2, Operand(1079146608)); __ vmov(d22, VmovIndexLo, r1); __ vmov(d22, VmovIndexHi, r2); - __ add(r4, r0, Operand(OFFSET_OF(T, i))); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i)))); __ vstm(ia_w, r4, d20, d22); // Move d22 into low and high. __ vmov(r4, VmovIndexLo, d22); - __ str(r4, MemOperand(r0, OFFSET_OF(T, low))); + __ str(r4, MemOperand(r0, offsetof(T, low))); __ vmov(r4, VmovIndexHi, d22); - __ str(r4, MemOperand(r0, OFFSET_OF(T, high))); + __ str(r4, MemOperand(r0, offsetof(T, high))); __ ldm(ia_w, sp, r4.bit() | pc.bit()); @@ -1164,16 +1164,16 @@ TEST(14) { __ vmsr(r1); __ bind(&fpscr_done); - __ vldr(d0, r0, OFFSET_OF(T, left)); - __ vldr(d1, r0, OFFSET_OF(T, right)); + __ vldr(d0, r0, offsetof(T, left)); + __ vldr(d1, r0, offsetof(T, right)); __ vadd(d2, d0, d1); - __ vstr(d2, r0, OFFSET_OF(T, add_result)); + __ vstr(d2, r0, offsetof(T, add_result)); __ vsub(d2, d0, d1); - __ vstr(d2, r0, OFFSET_OF(T, sub_result)); + __ vstr(d2, r0, offsetof(T, sub_result)); __ vmul(d2, d0, d1); - __ vstr(d2, r0, OFFSET_OF(T, mul_result)); + __ vstr(d2, r0, offsetof(T, mul_result)); __ vdiv(d2, d0, d1); - __ vstr(d2, r0, OFFSET_OF(T, div_result)); + __ vstr(d2, r0, offsetof(T, div_result)); __ mov(pc, Operand(lr)); @@ -1264,23 +1264,23 @@ TEST(15) { __ stm(db_w, sp, r4.bit() | lr.bit()); // Move 32 bytes with neon. - __ add(r4, r0, Operand(OFFSET_OF(T, src0))); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, src0)))); __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4)); - __ add(r4, r0, Operand(OFFSET_OF(T, dst0))); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dst0)))); __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4)); // Expand 8 bytes into 8 words(16 bits). - __ add(r4, r0, Operand(OFFSET_OF(T, srcA0))); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, srcA0)))); __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(r4)); __ vmovl(NeonU8, q0, d0); - __ add(r4, r0, Operand(OFFSET_OF(T, dstA0))); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dstA0)))); __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(r4)); // The same expansion, but with different source and destination registers. - __ add(r4, r0, Operand(OFFSET_OF(T, srcA0))); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, srcA0)))); __ vld1(Neon8, NeonListOperand(d1), NeonMemOperand(r4)); __ vmovl(NeonU8, q1, d1); - __ add(r4, r0, Operand(OFFSET_OF(T, dstA4))); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dstA4)))); __ vst1(Neon8, NeonListOperand(d2, 2), NeonMemOperand(r4)); __ ldm(ia_w, sp, r4.bit() | pc.bit()); @@ -1367,24 +1367,24 @@ TEST(16) { __ stm(db_w, sp, r4.bit() | lr.bit()); __ mov(r4, Operand(r0)); - __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src0))); - __ ldr(r1, MemOperand(r4, OFFSET_OF(T, src1))); + __ ldr(r0, MemOperand(r4, offsetof(T, src0))); + __ ldr(r1, MemOperand(r4, offsetof(T, src1))); __ pkhbt(r2, r0, Operand(r1, LSL, 8)); - __ str(r2, MemOperand(r4, OFFSET_OF(T, dst0))); + __ str(r2, MemOperand(r4, offsetof(T, dst0))); __ pkhtb(r2, r0, Operand(r1, ASR, 8)); - __ str(r2, MemOperand(r4, OFFSET_OF(T, dst1))); + __ str(r2, MemOperand(r4, offsetof(T, dst1))); __ uxtb16(r2, r0, 8); - __ str(r2, MemOperand(r4, OFFSET_OF(T, dst2))); + __ str(r2, MemOperand(r4, offsetof(T, dst2))); __ uxtb(r2, r0, 8); - __ str(r2, MemOperand(r4, OFFSET_OF(T, dst3))); + __ str(r2, MemOperand(r4, offsetof(T, dst3))); - __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src2))); + __ ldr(r0, MemOperand(r4, offsetof(T, src2))); __ uxtab(r2, r0, r1, 8); - __ str(r2, MemOperand(r4, OFFSET_OF(T, dst4))); + __ str(r2, MemOperand(r4, offsetof(T, dst4))); __ ldm(ia_w, sp, r4.bit() | pc.bit()); @@ -1461,11 +1461,11 @@ TEST(sdiv) { __ mov(r3, Operand(r0)); - __ ldr(r0, MemOperand(r3, OFFSET_OF(T, dividend))); - __ ldr(r1, MemOperand(r3, OFFSET_OF(T, divisor))); + __ ldr(r0, MemOperand(r3, offsetof(T, dividend))); + __ ldr(r1, MemOperand(r3, offsetof(T, divisor))); __ sdiv(r2, r0, r1); - __ str(r2, MemOperand(r3, OFFSET_OF(T, result))); + __ str(r2, MemOperand(r3, offsetof(T, result))); __ bx(lr); @@ -1525,11 +1525,11 @@ TEST(udiv) { __ mov(r3, Operand(r0)); - __ ldr(r0, MemOperand(r3, OFFSET_OF(T, dividend))); - __ ldr(r1, MemOperand(r3, OFFSET_OF(T, divisor))); + __ ldr(r0, MemOperand(r3, offsetof(T, dividend))); + __ ldr(r1, MemOperand(r3, offsetof(T, divisor))); __ sdiv(r2, r0, r1); - __ str(r2, MemOperand(r3, OFFSET_OF(T, result))); + __ str(r2, MemOperand(r3, offsetof(T, result))); __ bx(lr); @@ -1917,29 +1917,29 @@ TEST(ARMv8_vrintX) { __ mov(r4, Operand(r0)); // Test vrinta - __ vldr(d6, r4, OFFSET_OF(T, input)); + __ vldr(d6, r4, offsetof(T, input)); __ vrinta(d5, d6); - __ vstr(d5, r4, OFFSET_OF(T, ar)); + __ vstr(d5, r4, offsetof(T, ar)); // Test vrintn - __ vldr(d6, r4, OFFSET_OF(T, input)); + __ vldr(d6, r4, offsetof(T, input)); __ vrintn(d5, d6); - __ vstr(d5, r4, OFFSET_OF(T, nr)); + __ vstr(d5, r4, offsetof(T, nr)); // Test vrintp - __ vldr(d6, r4, OFFSET_OF(T, input)); + __ vldr(d6, r4, offsetof(T, input)); __ vrintp(d5, d6); - __ vstr(d5, r4, OFFSET_OF(T, pr)); + __ vstr(d5, r4, offsetof(T, pr)); // Test vrintm - __ vldr(d6, r4, OFFSET_OF(T, input)); + __ vldr(d6, r4, offsetof(T, input)); __ vrintm(d5, d6); - __ vstr(d5, r4, OFFSET_OF(T, mr)); + __ vstr(d5, r4, offsetof(T, mr)); // Test vrintz - __ vldr(d6, r4, OFFSET_OF(T, input)); + __ vldr(d6, r4, offsetof(T, input)); __ vrintz(d5, d6); - __ vstr(d5, r4, OFFSET_OF(T, zr)); + __ vstr(d5, r4, offsetof(T, zr)); __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); diff --git a/deps/v8/test/cctest/test-assembler-mips.cc b/deps/v8/test/cctest/test-assembler-mips.cc index 7a8beaa578..13abbbb447 100644 --- a/deps/v8/test/cctest/test-assembler-mips.cc +++ b/deps/v8/test/cctest/test-assembler-mips.cc @@ -278,61 +278,61 @@ TEST(MIPS3) { Label L, C; // Double precision floating point instructions. - __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); - __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); + __ ldc1(f4, MemOperand(a0, offsetof(T, a)) ); + __ ldc1(f6, MemOperand(a0, offsetof(T, b)) ); __ add_d(f8, f4, f6); - __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) ); // c = a + b. + __ sdc1(f8, MemOperand(a0, offsetof(T, c)) ); // c = a + b. __ mov_d(f10, f8); // c __ neg_d(f12, f6); // -b __ sub_d(f10, f10, f12); - __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) ); // d = c - (-b). + __ sdc1(f10, MemOperand(a0, offsetof(T, d)) ); // d = c - (-b). - __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) ); // b = a. + __ sdc1(f4, MemOperand(a0, offsetof(T, b)) ); // b = a. __ li(t0, 120); __ mtc1(t0, f14); __ cvt_d_w(f14, f14); // f14 = 120.0. __ mul_d(f10, f10, f14); - __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) ); // e = d * 120 = 1.8066e16. + __ sdc1(f10, MemOperand(a0, offsetof(T, e)) ); // e = d * 120 = 1.8066e16. __ div_d(f12, f10, f4); - __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) ); // f = e / a = 120.44. + __ sdc1(f12, MemOperand(a0, offsetof(T, f)) ); // f = e / a = 120.44. __ sqrt_d(f14, f12); - __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) ); + __ sdc1(f14, MemOperand(a0, offsetof(T, g)) ); // g = sqrt(f) = 10.97451593465515908537 if (IsMipsArchVariant(kMips32r2)) { - __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, h)) ); - __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, i)) ); + __ ldc1(f4, MemOperand(a0, offsetof(T, h)) ); + __ ldc1(f6, MemOperand(a0, offsetof(T, i)) ); __ madd_d(f14, f6, f4, f6); - __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, h)) ); + __ sdc1(f14, MemOperand(a0, offsetof(T, h)) ); } // Single precision floating point instructions. - __ lwc1(f4, MemOperand(a0, OFFSET_OF(T, fa)) ); - __ lwc1(f6, MemOperand(a0, OFFSET_OF(T, fb)) ); + __ lwc1(f4, MemOperand(a0, offsetof(T, fa)) ); + __ lwc1(f6, MemOperand(a0, offsetof(T, fb)) ); __ add_s(f8, f4, f6); - __ swc1(f8, MemOperand(a0, OFFSET_OF(T, fc)) ); // fc = fa + fb. + __ swc1(f8, MemOperand(a0, offsetof(T, fc)) ); // fc = fa + fb. __ neg_s(f10, f6); // -fb __ sub_s(f10, f8, f10); - __ swc1(f10, MemOperand(a0, OFFSET_OF(T, fd)) ); // fd = fc - (-fb). + __ swc1(f10, MemOperand(a0, offsetof(T, fd)) ); // fd = fc - (-fb). - __ swc1(f4, MemOperand(a0, OFFSET_OF(T, fb)) ); // fb = fa. + __ swc1(f4, MemOperand(a0, offsetof(T, fb)) ); // fb = fa. __ li(t0, 120); __ mtc1(t0, f14); __ cvt_s_w(f14, f14); // f14 = 120.0. __ mul_s(f10, f10, f14); - __ swc1(f10, MemOperand(a0, OFFSET_OF(T, fe)) ); // fe = fd * 120 + __ swc1(f10, MemOperand(a0, offsetof(T, fe)) ); // fe = fd * 120 __ div_s(f12, f10, f4); - __ swc1(f12, MemOperand(a0, OFFSET_OF(T, ff)) ); // ff = fe / fa + __ swc1(f12, MemOperand(a0, offsetof(T, ff)) ); // ff = fe / fa __ sqrt_s(f14, f12); - __ swc1(f14, MemOperand(a0, OFFSET_OF(T, fg)) ); + __ swc1(f14, MemOperand(a0, offsetof(T, fg)) ); __ jr(ra); __ nop(); @@ -398,8 +398,8 @@ TEST(MIPS4) { Assembler assm(isolate, NULL, 0); Label L, C; - __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); - __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); + __ ldc1(f4, MemOperand(a0, offsetof(T, a)) ); + __ ldc1(f6, MemOperand(a0, offsetof(T, b)) ); // Swap f4 and f6, by using four integer registers, t0-t3. if (!IsFp64Mode()) { @@ -425,8 +425,8 @@ TEST(MIPS4) { __ mthc1(t3, f4); } // Store the swapped f4 and f5 back to memory. - __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); - __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) ); + __ sdc1(f4, MemOperand(a0, offsetof(T, a)) ); + __ sdc1(f6, MemOperand(a0, offsetof(T, c)) ); __ jr(ra); __ nop(); @@ -466,30 +466,30 @@ TEST(MIPS5) { Label L, C; // Load all structure elements to registers. - __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); - __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); - __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) ); - __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) ); + __ ldc1(f4, MemOperand(a0, offsetof(T, a)) ); + __ ldc1(f6, MemOperand(a0, offsetof(T, b)) ); + __ lw(t0, MemOperand(a0, offsetof(T, i)) ); + __ lw(t1, MemOperand(a0, offsetof(T, j)) ); // Convert double in f4 to int in element i. __ cvt_w_d(f8, f4); __ mfc1(t2, f8); - __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) ); + __ sw(t2, MemOperand(a0, offsetof(T, i)) ); // Convert double in f6 to int in element j. __ cvt_w_d(f10, f6); __ mfc1(t3, f10); - __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) ); + __ sw(t3, MemOperand(a0, offsetof(T, j)) ); // Convert int in original i (t0) to double in a. __ mtc1(t0, f12); __ cvt_d_w(f0, f12); - __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) ); + __ sdc1(f0, MemOperand(a0, offsetof(T, a)) ); // Convert int in original j (t1) to double in b. __ mtc1(t1, f14); __ cvt_d_w(f2, f14); - __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) ); + __ sdc1(f2, MemOperand(a0, offsetof(T, b)) ); __ jr(ra); __ nop(); @@ -535,31 +535,31 @@ TEST(MIPS6) { Label L, C; // Basic word load/store. - __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) ); - __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) ); + __ lw(t0, MemOperand(a0, offsetof(T, ui)) ); + __ sw(t0, MemOperand(a0, offsetof(T, r1)) ); // lh with positive data. - __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) ); - __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) ); + __ lh(t1, MemOperand(a0, offsetof(T, ui)) ); + __ sw(t1, MemOperand(a0, offsetof(T, r2)) ); // lh with negative data. - __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) ); - __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) ); + __ lh(t2, MemOperand(a0, offsetof(T, si)) ); + __ sw(t2, MemOperand(a0, offsetof(T, r3)) ); // lhu with negative data. - __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) ); - __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) ); + __ lhu(t3, MemOperand(a0, offsetof(T, si)) ); + __ sw(t3, MemOperand(a0, offsetof(T, r4)) ); // lb with negative data. - __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) ); - __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) ); + __ lb(t4, MemOperand(a0, offsetof(T, si)) ); + __ sw(t4, MemOperand(a0, offsetof(T, r5)) ); // sh writes only 1/2 of word. __ lui(t5, 0x3333); __ ori(t5, t5, 0x3333); - __ sw(t5, MemOperand(a0, OFFSET_OF(T, r6)) ); - __ lhu(t5, MemOperand(a0, OFFSET_OF(T, si)) ); - __ sh(t5, MemOperand(a0, OFFSET_OF(T, r6)) ); + __ sw(t5, MemOperand(a0, offsetof(T, r6)) ); + __ lhu(t5, MemOperand(a0, offsetof(T, si)) ); + __ sh(t5, MemOperand(a0, offsetof(T, r6)) ); __ jr(ra); __ nop(); @@ -615,8 +615,8 @@ TEST(MIPS7) { MacroAssembler assm(isolate, NULL, 0); Label neither_is_nan, less_than, outa_here; - __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); - __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); + __ ldc1(f4, MemOperand(a0, offsetof(T, a)) ); + __ ldc1(f6, MemOperand(a0, offsetof(T, b)) ); if (!IsMipsArchVariant(kMips32r6)) { __ c(UN, D, f4, f6); __ bc1f(&neither_is_nan); @@ -625,7 +625,7 @@ TEST(MIPS7) { __ bc1eqz(&neither_is_nan, f2); } __ nop(); - __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); + __ sw(zero_reg, MemOperand(a0, offsetof(T, result)) ); __ Branch(&outa_here); __ bind(&neither_is_nan); @@ -642,12 +642,12 @@ TEST(MIPS7) { } __ nop(); - __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); + __ sw(zero_reg, MemOperand(a0, offsetof(T, result)) ); __ Branch(&outa_here); __ bind(&less_than); __ Addu(t0, zero_reg, Operand(1)); - __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) ); // Set true. + __ sw(t0, MemOperand(a0, offsetof(T, result)) ); // Set true. // This test-case should have additional tests. @@ -706,7 +706,7 @@ TEST(MIPS8) { MacroAssembler assm(isolate, NULL, 0); // Basic word load. - __ lw(t0, MemOperand(a0, OFFSET_OF(T, input)) ); + __ lw(t0, MemOperand(a0, offsetof(T, input)) ); // ROTR instruction (called through the Ror macro). __ Ror(t1, t0, 0x0004); @@ -718,13 +718,13 @@ TEST(MIPS8) { __ Ror(t7, t0, 0x001c); // Basic word store. - __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotr_4)) ); - __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotr_8)) ); - __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotr_12)) ); - __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotr_16)) ); - __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotr_20)) ); - __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotr_24)) ); - __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotr_28)) ); + __ sw(t1, MemOperand(a0, offsetof(T, result_rotr_4)) ); + __ sw(t2, MemOperand(a0, offsetof(T, result_rotr_8)) ); + __ sw(t3, MemOperand(a0, offsetof(T, result_rotr_12)) ); + __ sw(t4, MemOperand(a0, offsetof(T, result_rotr_16)) ); + __ sw(t5, MemOperand(a0, offsetof(T, result_rotr_20)) ); + __ sw(t6, MemOperand(a0, offsetof(T, result_rotr_24)) ); + __ sw(t7, MemOperand(a0, offsetof(T, result_rotr_28)) ); // ROTRV instruction (called through the Ror macro). __ li(t7, 0x0004); @@ -743,13 +743,13 @@ TEST(MIPS8) { __ Ror(t7, t0, t7); // Basic word store. - __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotrv_4)) ); - __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotrv_8)) ); - __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotrv_12)) ); - __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotrv_16)) ); - __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotrv_20)) ); - __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotrv_24)) ); - __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotrv_28)) ); + __ sw(t1, MemOperand(a0, offsetof(T, result_rotrv_4)) ); + __ sw(t2, MemOperand(a0, offsetof(T, result_rotrv_8)) ); + __ sw(t3, MemOperand(a0, offsetof(T, result_rotrv_12)) ); + __ sw(t4, MemOperand(a0, offsetof(T, result_rotrv_16)) ); + __ sw(t5, MemOperand(a0, offsetof(T, result_rotrv_20)) ); + __ sw(t6, MemOperand(a0, offsetof(T, result_rotrv_24)) ); + __ sw(t7, MemOperand(a0, offsetof(T, result_rotrv_28)) ); __ jr(ra); __ nop(); @@ -808,8 +808,9 @@ TEST(MIPS9) { TEST(MIPS10) { - // Test conversions between doubles and long integers. - // Test hos the long ints map to FP regs pairs. + // Test conversions between doubles and words. + // Test maps double to FP reg pairs in fp32 mode + // and into FP reg in fp64 mode. CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); HandleScope scope(isolate); @@ -830,24 +831,32 @@ TEST(MIPS10) { if (!IsMipsArchVariant(kMips32r2)) return; // Load all structure elements to registers. - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a))); - - // Save the raw bits of the double. - __ mfc1(t0, f0); - __ mfc1(t1, f1); - __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant))); - __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp))); + // (f0, f1) = a (fp32), f0 = a (fp64) + __ ldc1(f0, MemOperand(a0, offsetof(T, a))); + + if (IsFp64Mode()) { + __ mfc1(t0, f0); // t0 = f0(31..0) + __ mfhc1(t1, f0); // t1 = sign_extend(f0(63..32)) + __ sw(t0, MemOperand(a0, offsetof(T, dbl_mant))); // dbl_mant = t0 + __ sw(t1, MemOperand(a0, offsetof(T, dbl_exp))); // dbl_exp = t1 + } else { + // Save the raw bits of the double. + __ mfc1(t0, f0); // t0 = a1 + __ mfc1(t1, f1); // t1 = a2 + __ sw(t0, MemOperand(a0, offsetof(T, dbl_mant))); // dbl_mant = t0 + __ sw(t1, MemOperand(a0, offsetof(T, dbl_exp))); // dbl_exp = t1 + } - // Convert double in f0 to long, save hi/lo parts. - __ cvt_w_d(f0, f0); - __ mfc1(t0, f0); // f0 has a 32-bits word. - __ sw(t0, MemOperand(a0, OFFSET_OF(T, word))); + // Convert double in f0 to word, save hi/lo parts. + __ cvt_w_d(f0, f0); // a_word = (word)a + __ mfc1(t0, f0); // f0 has a 32-bits word. t0 = a_word + __ sw(t0, MemOperand(a0, offsetof(T, word))); // word = a_word - // Convert the b long integers to double b. - __ lw(t0, MemOperand(a0, OFFSET_OF(T, b_word))); + // Convert the b word to double b. + __ lw(t0, MemOperand(a0, offsetof(T, b_word))); __ mtc1(t0, f8); // f8 has a 32-bits word. __ cvt_d_w(f10, f8); - __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b))); + __ sdc1(f10, MemOperand(a0, offsetof(T, b))); __ jr(ra); __ nop(); @@ -861,7 +870,6 @@ TEST(MIPS10) { t.b_word = 0x0ff00ff0; // 0x0FF00FF0 -> 0x as double. Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); USE(dummy); - CHECK_EQ(static_cast<int32_t>(0x41DFFFFF), t.dbl_exp); CHECK_EQ(static_cast<int32_t>(0xFF800000), t.dbl_mant); CHECK_EQ(static_cast<int32_t>(0x7FFFFFFE), t.word); @@ -903,80 +911,80 @@ TEST(MIPS11) { Assembler assm(isolate, NULL, 0); // Test all combinations of LWL and vAddr. - __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ lwl(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) ); - __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwl_0)) ); + __ lw(t0, MemOperand(a0, offsetof(T, reg_init)) ); + __ lwl(t0, MemOperand(a0, offsetof(T, mem_init)) ); + __ sw(t0, MemOperand(a0, offsetof(T, lwl_0)) ); - __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ lwl(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) ); - __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwl_1)) ); + __ lw(t1, MemOperand(a0, offsetof(T, reg_init)) ); + __ lwl(t1, MemOperand(a0, offsetof(T, mem_init) + 1) ); + __ sw(t1, MemOperand(a0, offsetof(T, lwl_1)) ); - __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ lwl(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) ); - __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwl_2)) ); + __ lw(t2, MemOperand(a0, offsetof(T, reg_init)) ); + __ lwl(t2, MemOperand(a0, offsetof(T, mem_init) + 2) ); + __ sw(t2, MemOperand(a0, offsetof(T, lwl_2)) ); - __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ lwl(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) ); - __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwl_3)) ); + __ lw(t3, MemOperand(a0, offsetof(T, reg_init)) ); + __ lwl(t3, MemOperand(a0, offsetof(T, mem_init) + 3) ); + __ sw(t3, MemOperand(a0, offsetof(T, lwl_3)) ); // Test all combinations of LWR and vAddr. - __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ lwr(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) ); - __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwr_0)) ); + __ lw(t0, MemOperand(a0, offsetof(T, reg_init)) ); + __ lwr(t0, MemOperand(a0, offsetof(T, mem_init)) ); + __ sw(t0, MemOperand(a0, offsetof(T, lwr_0)) ); - __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ lwr(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) ); - __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwr_1)) ); + __ lw(t1, MemOperand(a0, offsetof(T, reg_init)) ); + __ lwr(t1, MemOperand(a0, offsetof(T, mem_init) + 1) ); + __ sw(t1, MemOperand(a0, offsetof(T, lwr_1)) ); - __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ lwr(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) ); - __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwr_2)) ); + __ lw(t2, MemOperand(a0, offsetof(T, reg_init)) ); + __ lwr(t2, MemOperand(a0, offsetof(T, mem_init) + 2) ); + __ sw(t2, MemOperand(a0, offsetof(T, lwr_2)) ); - __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ lwr(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) ); - __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwr_3)) ); + __ lw(t3, MemOperand(a0, offsetof(T, reg_init)) ); + __ lwr(t3, MemOperand(a0, offsetof(T, mem_init) + 3) ); + __ sw(t3, MemOperand(a0, offsetof(T, lwr_3)) ); // Test all combinations of SWL and vAddr. - __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) ); - __ sw(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) ); - __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ swl(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) ); - - __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) ); - __ sw(t1, MemOperand(a0, OFFSET_OF(T, swl_1)) ); - __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ swl(t1, MemOperand(a0, OFFSET_OF(T, swl_1) + 1) ); - - __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) ); - __ sw(t2, MemOperand(a0, OFFSET_OF(T, swl_2)) ); - __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ swl(t2, MemOperand(a0, OFFSET_OF(T, swl_2) + 2) ); - - __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) ); - __ sw(t3, MemOperand(a0, OFFSET_OF(T, swl_3)) ); - __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ swl(t3, MemOperand(a0, OFFSET_OF(T, swl_3) + 3) ); + __ lw(t0, MemOperand(a0, offsetof(T, mem_init)) ); + __ sw(t0, MemOperand(a0, offsetof(T, swl_0)) ); + __ lw(t0, MemOperand(a0, offsetof(T, reg_init)) ); + __ swl(t0, MemOperand(a0, offsetof(T, swl_0)) ); + + __ lw(t1, MemOperand(a0, offsetof(T, mem_init)) ); + __ sw(t1, MemOperand(a0, offsetof(T, swl_1)) ); + __ lw(t1, MemOperand(a0, offsetof(T, reg_init)) ); + __ swl(t1, MemOperand(a0, offsetof(T, swl_1) + 1) ); + + __ lw(t2, MemOperand(a0, offsetof(T, mem_init)) ); + __ sw(t2, MemOperand(a0, offsetof(T, swl_2)) ); + __ lw(t2, MemOperand(a0, offsetof(T, reg_init)) ); + __ swl(t2, MemOperand(a0, offsetof(T, swl_2) + 2) ); + + __ lw(t3, MemOperand(a0, offsetof(T, mem_init)) ); + __ sw(t3, MemOperand(a0, offsetof(T, swl_3)) ); + __ lw(t3, MemOperand(a0, offsetof(T, reg_init)) ); + __ swl(t3, MemOperand(a0, offsetof(T, swl_3) + 3) ); // Test all combinations of SWR and vAddr. - __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) ); - __ sw(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) ); - __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ swr(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) ); - - __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) ); - __ sw(t1, MemOperand(a0, OFFSET_OF(T, swr_1)) ); - __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ swr(t1, MemOperand(a0, OFFSET_OF(T, swr_1) + 1) ); - - __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) ); - __ sw(t2, MemOperand(a0, OFFSET_OF(T, swr_2)) ); - __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ swr(t2, MemOperand(a0, OFFSET_OF(T, swr_2) + 2) ); - - __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) ); - __ sw(t3, MemOperand(a0, OFFSET_OF(T, swr_3)) ); - __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) ); - __ swr(t3, MemOperand(a0, OFFSET_OF(T, swr_3) + 3) ); + __ lw(t0, MemOperand(a0, offsetof(T, mem_init)) ); + __ sw(t0, MemOperand(a0, offsetof(T, swr_0)) ); + __ lw(t0, MemOperand(a0, offsetof(T, reg_init)) ); + __ swr(t0, MemOperand(a0, offsetof(T, swr_0)) ); + + __ lw(t1, MemOperand(a0, offsetof(T, mem_init)) ); + __ sw(t1, MemOperand(a0, offsetof(T, swr_1)) ); + __ lw(t1, MemOperand(a0, offsetof(T, reg_init)) ); + __ swr(t1, MemOperand(a0, offsetof(T, swr_1) + 1) ); + + __ lw(t2, MemOperand(a0, offsetof(T, mem_init)) ); + __ sw(t2, MemOperand(a0, offsetof(T, swr_2)) ); + __ lw(t2, MemOperand(a0, offsetof(T, reg_init)) ); + __ swr(t2, MemOperand(a0, offsetof(T, swr_2) + 2) ); + + __ lw(t3, MemOperand(a0, offsetof(T, mem_init)) ); + __ sw(t3, MemOperand(a0, offsetof(T, swr_3)) ); + __ lw(t3, MemOperand(a0, offsetof(T, reg_init)) ); + __ swr(t3, MemOperand(a0, offsetof(T, swr_3) + 3) ); __ jr(ra); __ nop(); @@ -1013,7 +1021,7 @@ TEST(MIPS11) { CHECK_EQ(static_cast<int32_t>(0xccdd3344), t.swr_2); CHECK_EQ(static_cast<int32_t>(0xdd223344), t.swr_3); #elif __BYTE_ORDER == __BIG_ENDIAN - 11223344, t.lwl_0); + CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwl_0); CHECK_EQ(static_cast<int32_t>(0x223344dd), t.lwl_1); CHECK_EQ(static_cast<int32_t>(0x3344ccdd), t.lwl_2); CHECK_EQ(static_cast<int32_t>(0x44bbccdd), t.lwl_3); @@ -1057,8 +1065,8 @@ TEST(MIPS12) { __ mov(t6, fp); // Save frame pointer. __ mov(fp, a0); // Access struct T by fp. - __ lw(t0, MemOperand(a0, OFFSET_OF(T, y)) ); - __ lw(t3, MemOperand(a0, OFFSET_OF(T, y4)) ); + __ lw(t0, MemOperand(a0, offsetof(T, y)) ); + __ lw(t3, MemOperand(a0, offsetof(T, y4)) ); __ addu(t1, t0, t3); __ subu(t4, t0, t3); @@ -1076,30 +1084,30 @@ TEST(MIPS12) { __ push(t3); __ pop(t4); __ nop(); - __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) ); - __ lw(t0, MemOperand(fp, OFFSET_OF(T, y)) ); + __ sw(t0, MemOperand(fp, offsetof(T, y)) ); + __ lw(t0, MemOperand(fp, offsetof(T, y)) ); __ nop(); - __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) ); - __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) ); + __ sw(t0, MemOperand(fp, offsetof(T, y)) ); + __ lw(t1, MemOperand(fp, offsetof(T, y)) ); __ nop(); __ push(t1); - __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) ); + __ lw(t1, MemOperand(fp, offsetof(T, y)) ); __ pop(t1); __ nop(); __ push(t1); - __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); + __ lw(t2, MemOperand(fp, offsetof(T, y)) ); __ pop(t1); __ nop(); __ push(t1); - __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); + __ lw(t2, MemOperand(fp, offsetof(T, y)) ); __ pop(t2); __ nop(); __ push(t2); - __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); + __ lw(t2, MemOperand(fp, offsetof(T, y)) ); __ pop(t1); __ nop(); __ push(t1); - __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); + __ lw(t2, MemOperand(fp, offsetof(T, y)) ); __ pop(t3); __ nop(); @@ -1144,19 +1152,19 @@ TEST(MIPS13) { MacroAssembler assm(isolate, NULL, 0); - __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in))); + __ sw(t0, MemOperand(a0, offsetof(T, cvt_small_in))); __ Cvt_d_uw(f10, t0, f22); - __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out))); + __ sdc1(f10, MemOperand(a0, offsetof(T, cvt_small_out))); __ Trunc_uw_d(f10, f10, f22); - __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out))); + __ swc1(f10, MemOperand(a0, offsetof(T, trunc_small_out))); - __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in))); + __ sw(t0, MemOperand(a0, offsetof(T, cvt_big_in))); __ Cvt_d_uw(f8, t0, f22); - __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out))); + __ sdc1(f8, MemOperand(a0, offsetof(T, cvt_big_out))); __ Trunc_uw_d(f8, f8, f22); - __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out))); + __ swc1(f8, MemOperand(a0, offsetof(T, trunc_big_out))); __ jr(ra); __ nop(); @@ -1226,46 +1234,46 @@ TEST(MIPS14) { // Disable FPU exceptions. __ ctc1(zero_reg, FCSR); #define RUN_ROUND_TEST(x) \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, round_up_in))); \ __ x##_w_d(f0, f0); \ - __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \ + __ swc1(f0, MemOperand(a0, offsetof(T, x##_up_out))); \ \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, round_down_in))); \ __ x##_w_d(f0, f0); \ - __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \ + __ swc1(f0, MemOperand(a0, offsetof(T, x##_down_out))); \ \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, neg_round_up_in))); \ __ x##_w_d(f0, f0); \ - __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \ + __ swc1(f0, MemOperand(a0, offsetof(T, neg_##x##_up_out))); \ \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, neg_round_down_in))); \ __ x##_w_d(f0, f0); \ - __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \ + __ swc1(f0, MemOperand(a0, offsetof(T, neg_##x##_down_out))); \ \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, err1_in))); \ __ ctc1(zero_reg, FCSR); \ __ x##_w_d(f0, f0); \ __ cfc1(a2, FCSR); \ - __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \ + __ sw(a2, MemOperand(a0, offsetof(T, x##_err1_out))); \ \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, err2_in))); \ __ ctc1(zero_reg, FCSR); \ __ x##_w_d(f0, f0); \ __ cfc1(a2, FCSR); \ - __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \ + __ sw(a2, MemOperand(a0, offsetof(T, x##_err2_out))); \ \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, err3_in))); \ __ ctc1(zero_reg, FCSR); \ __ x##_w_d(f0, f0); \ __ cfc1(a2, FCSR); \ - __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \ + __ sw(a2, MemOperand(a0, offsetof(T, x##_err3_out))); \ \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, err4_in))); \ __ ctc1(zero_reg, FCSR); \ __ x##_w_d(f0, f0); \ __ cfc1(a2, FCSR); \ - __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \ - __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result))); + __ sw(a2, MemOperand(a0, offsetof(T, x##_err4_out))); \ + __ swc1(f0, MemOperand(a0, offsetof(T, x##_invalid_result))); RUN_ROUND_TEST(round) RUN_ROUND_TEST(floor) @@ -1329,7 +1337,8 @@ TEST(MIPS15) { } -TEST(MIPS16) { +// ----------------------mips32r6 specific tests---------------------- +TEST(seleqz_selnez) { if (IsMipsArchVariant(kMips32r6)) { CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); @@ -1345,26 +1354,36 @@ TEST(MIPS16) { double f; double g; double h; + float i; + float j; + float k; + float l; } Test; Test test; // Integer part of test. __ addiu(t1, zero_reg, 1); // t1 = 1 __ seleqz(t3, t1, zero_reg); // t3 = 1 - __ sw(t3, MemOperand(a0, OFFSET_OF(Test, a))); // a = 1 + __ sw(t3, MemOperand(a0, offsetof(Test, a))); // a = 1 __ seleqz(t2, t1, t1); // t2 = 0 - __ sw(t2, MemOperand(a0, OFFSET_OF(Test, b))); // b = 0 + __ sw(t2, MemOperand(a0, offsetof(Test, b))); // b = 0 __ selnez(t3, t1, zero_reg); // t3 = 1; - __ sw(t3, MemOperand(a0, OFFSET_OF(Test, c))); // c = 0 + __ sw(t3, MemOperand(a0, offsetof(Test, c))); // c = 0 __ selnez(t3, t1, t1); // t3 = 1 - __ sw(t3, MemOperand(a0, OFFSET_OF(Test, d))); // d = 1 + __ sw(t3, MemOperand(a0, offsetof(Test, d))); // d = 1 // Floating point part of test. - __ ldc1(f0, MemOperand(a0, OFFSET_OF(Test, e)) ); // src - __ ldc1(f2, MemOperand(a0, OFFSET_OF(Test, f)) ); // test - __ seleqz(D, f4, f0, f2); - __ selnez(D, f6, f0, f2); - __ sdc1(f4, MemOperand(a0, OFFSET_OF(Test, g)) ); // src - __ sdc1(f6, MemOperand(a0, OFFSET_OF(Test, h)) ); // src + __ ldc1(f0, MemOperand(a0, offsetof(Test, e)) ); // src + __ ldc1(f2, MemOperand(a0, offsetof(Test, f)) ); // test + __ lwc1(f8, MemOperand(a0, offsetof(Test, i)) ); // src + __ lwc1(f10, MemOperand(a0, offsetof(Test, j)) ); // test + __ seleqz_d(f4, f0, f2); + __ selnez_d(f6, f0, f2); + __ seleqz_s(f12, f8, f10); + __ selnez_s(f14, f8, f10); + __ sdc1(f4, MemOperand(a0, offsetof(Test, g)) ); // src + __ sdc1(f6, MemOperand(a0, offsetof(Test, h)) ); // src + __ swc1(f12, MemOperand(a0, offsetof(Test, k)) ); // src + __ swc1(f14, MemOperand(a0, offsetof(Test, l)) ); // src __ jr(ra); __ nop(); CodeDesc desc; @@ -1383,31 +1402,44 @@ TEST(MIPS16) { const int test_size = 3; const int input_size = 5; - double inputs[input_size] = {0.0, 65.2, -70.32, + double inputs_D[input_size] = {0.0, 65.2, -70.32, 18446744073709551621.0, -18446744073709551621.0}; - double outputs[input_size] = {0.0, 65.2, -70.32, + double outputs_D[input_size] = {0.0, 65.2, -70.32, 18446744073709551621.0, -18446744073709551621.0}; - double tests[test_size*2] = {2.8, 2.9, -2.8, -2.9, + double tests_D[test_size*2] = {2.8, 2.9, -2.8, -2.9, 18446744073709551616.0, 18446744073709555712.0}; + float inputs_S[input_size] = {0.0, 65.2, -70.32, + 18446744073709551621.0, -18446744073709551621.0}; + float outputs_S[input_size] = {0.0, 65.2, -70.32, + 18446744073709551621.0, -18446744073709551621.0}; + float tests_S[test_size*2] = {2.9, 2.8, -2.9, -2.8, + 18446744073709551616.0, 18446746272732807168.0}; for (int j=0; j < test_size; j+=2) { for (int i=0; i < input_size; i++) { - test.e = inputs[i]; - test.f = tests[j]; + test.e = inputs_D[i]; + test.f = tests_D[j]; + test.i = inputs_S[i]; + test.j = tests_S[j]; (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - CHECK_EQ(test.g, outputs[i]); + CHECK_EQ(test.g, outputs_D[i]); CHECK_EQ(test.h, 0); + CHECK_EQ(test.k, outputs_S[i]); + CHECK_EQ(test.l, 0); - test.f = tests[j+1]; + test.f = tests_D[j+1]; + test.j = tests_S[j+1]; (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); CHECK_EQ(test.g, 0); - CHECK_EQ(test.h, outputs[i]); + CHECK_EQ(test.h, outputs_D[i]); + CHECK_EQ(test.k, 0); + CHECK_EQ(test.l, outputs_S[i]); } } } } -TEST(MIPS17) { +TEST(min_max) { if (IsMipsArchVariant(kMips32r6)) { CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); @@ -1419,16 +1451,38 @@ TEST(MIPS17) { double b; double c; double d; + float e; + float f; + float g; + float h; } TestFloat; TestFloat test; - - __ ldc1(f4, MemOperand(a0, OFFSET_OF(TestFloat, a))); - __ ldc1(f8, MemOperand(a0, OFFSET_OF(TestFloat, b))); + const double dblNaN = std::numeric_limits<double>::quiet_NaN(); + const float fltNaN = std::numeric_limits<float>::quiet_NaN(); + const int tableLength = 5; + double inputsa[tableLength] = {2.0, 3.0, dblNaN, 3.0, dblNaN}; + double inputsb[tableLength] = {3.0, 2.0, 3.0, dblNaN, dblNaN}; + double outputsdmin[tableLength] = {2.0, 2.0, 3.0, 3.0, dblNaN}; + double outputsdmax[tableLength] = {3.0, 3.0, 3.0, 3.0, dblNaN}; + + float inputse[tableLength] = {2.0, 3.0, fltNaN, 3.0, fltNaN}; + float inputsf[tableLength] = {3.0, 2.0, 3.0, fltNaN, fltNaN}; + float outputsfmin[tableLength] = {2.0, 2.0, 3.0, 3.0, fltNaN}; + float outputsfmax[tableLength] = {3.0, 3.0, 3.0, 3.0, fltNaN}; + + __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); + __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b))); + __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, e))); + __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, f))); __ min_d(f10, f4, f8); __ max_d(f12, f4, f8); - __ sdc1(f10, MemOperand(a0, OFFSET_OF(TestFloat, c))); - __ sdc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, d))); + __ min_s(f14, f2, f6); + __ max_s(f16, f2, f6); + __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c))); + __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, d))); + __ swc1(f14, MemOperand(a0, offsetof(TestFloat, g))); + __ swc1(f16, MemOperand(a0, offsetof(TestFloat, h))); __ jr(ra); __ nop(); @@ -1437,40 +1491,31 @@ TEST(MIPS17) { Handle<Code> code = isolate->factory()->NewCode( desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); F3 f = FUNCTION_CAST<F3>(code->entry()); - test.a = 2.0; // a goes to fs - test.b = 3.0; // b goes to ft - (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - CHECK_EQ(test.c, 2.0); - CHECK_EQ(test.d, 3.0); - - test.a = 3.0; // a goes to fs - test.b = 2.0; // b goes to ft - (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - CHECK_EQ(test.c, 2.0); - CHECK_EQ(test.d, 3.0); - - test.a = std::numeric_limits<double>::quiet_NaN(); - test.b = 3.0; // b goes to ft - (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - CHECK_EQ(test.c, 3.0); - CHECK_EQ(test.d, 3.0); + for (int i = 0; i < tableLength; i++) { + test.a = inputsa[i]; + test.b = inputsb[i]; + test.e = inputse[i]; + test.f = inputsf[i]; - test.b = std::numeric_limits<double>::quiet_NaN(); - test.a = 3.0; // b goes to ft - (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - CHECK_EQ(test.c, 3.0); - CHECK_EQ(test.d, 3.0); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - test.a = std::numeric_limits<double>::quiet_NaN(); - test.b = std::numeric_limits<double>::quiet_NaN(); - (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - DCHECK(std::isnan(test.c)); - DCHECK(std::isnan(test.d)); + if (i < tableLength - 1) { + CHECK_EQ(test.c, outputsdmin[i]); + CHECK_EQ(test.d, outputsdmax[i]); + CHECK_EQ(test.g, outputsfmin[i]); + CHECK_EQ(test.h, outputsfmax[i]); + } else { + DCHECK(std::isnan(test.c)); + DCHECK(std::isnan(test.d)); + DCHECK(std::isnan(test.g)); + DCHECK(std::isnan(test.h)); + } + } } } -TEST(MIPS18) { +TEST(rint_d) { if (IsMipsArchVariant(kMips32r6)) { const int tableLength = 30; CcTest::InitializeVM(); @@ -1548,12 +1593,191 @@ TEST(MIPS18) { int fcsr_inputs[4] = {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf}; double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM}; - __ ldc1(f4, MemOperand(a0, OFFSET_OF(TestFloat, a)) ); - __ lw(t0, MemOperand(a0, OFFSET_OF(TestFloat, fcsr)) ); + __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)) ); + __ lw(t0, MemOperand(a0, offsetof(TestFloat, fcsr)) ); __ cfc1(t1, FCSR); __ ctc1(t0, FCSR); __ rint_d(f8, f4); - __ sdc1(f8, MemOperand(a0, OFFSET_OF(TestFloat, b)) ); + __ sdc1(f8, MemOperand(a0, offsetof(TestFloat, b)) ); + __ ctc1(t1, FCSR); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + + for (int j = 0; j < 4; j++) { + test.fcsr = fcsr_inputs[j]; + for (int i = 0; i < tableLength; i++) { + test.a = inputs[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.b, outputs[j][i]); + } + } + } +} + + +TEST(sel) { + if (IsMipsArchVariant(kMips32r6)) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test { + double dd; + double ds; + double dt; + float fd; + float fs; + float ft; + } Test; + + Test test; + __ ldc1(f0, MemOperand(a0, offsetof(Test, dd)) ); // test + __ ldc1(f2, MemOperand(a0, offsetof(Test, ds)) ); // src1 + __ ldc1(f4, MemOperand(a0, offsetof(Test, dt)) ); // src2 + __ lwc1(f6, MemOperand(a0, offsetof(Test, fd)) ); // test + __ lwc1(f8, MemOperand(a0, offsetof(Test, fs)) ); // src1 + __ lwc1(f10, MemOperand(a0, offsetof(Test, ft)) ); // src2 + __ sel_d(f0, f2, f4); + __ sel_s(f6, f8, f10); + __ sdc1(f0, MemOperand(a0, offsetof(Test, dd)) ); + __ swc1(f6, MemOperand(a0, offsetof(Test, fd)) ); + __ jr(ra); + __ nop(); + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + + const int test_size = 3; + const int input_size = 5; + + double inputs_dt[input_size] = {0.0, 65.2, -70.32, + 18446744073709551621.0, -18446744073709551621.0}; + double inputs_ds[input_size] = {0.1, 69.88, -91.325, + 18446744073709551625.0, -18446744073709551625.0}; + float inputs_ft[input_size] = {0.0, 65.2, -70.32, + 18446744073709551621.0, -18446744073709551621.0}; + float inputs_fs[input_size] = {0.1, 69.88, -91.325, + 18446744073709551625.0, -18446744073709551625.0}; + double tests_D[test_size*2] = {2.8, 2.9, -2.8, -2.9, + 18446744073709551616.0, 18446744073709555712.0}; + float tests_S[test_size*2] = {2.9, 2.8, -2.9, -2.8, + 18446744073709551616.0, 18446746272732807168.0}; + for (int j=0; j < test_size; j+=2) { + for (int i=0; i < input_size; i++) { + test.dt = inputs_dt[i]; + test.dd = tests_D[j]; + test.ds = inputs_ds[i]; + test.ft = inputs_ft[i]; + test.fd = tests_S[j]; + test.fs = inputs_fs[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dd, inputs_ds[i]); + CHECK_EQ(test.fd, inputs_fs[i]); + + test.dd = tests_D[j+1]; + test.fd = tests_S[j+1]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dd, inputs_dt[i]); + CHECK_EQ(test.fd, inputs_ft[i]); + } + } + } +} + + +TEST(rint_s) { + if (IsMipsArchVariant(kMips32r6)) { + const int tableLength = 30; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + float a; + float b; + int fcsr; + }TestFloat; + + TestFloat test; + float inputs[tableLength] = {18446744073709551617.0, + 4503599627370496.0, -4503599627370496.0, + 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, + 1.7976931348623157E+38, 6.27463370218383111104242366943E-37, + 309485009821345068724781056.89, + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 37778931862957161709568.0, 37778931862957161709569.0, + 37778931862957161709580.0, 37778931862957161709581.0, + 37778931862957161709582.0, 37778931862957161709583.0, + 37778931862957161709584.0, 37778931862957161709585.0, + 37778931862957161709586.0, 37778931862957161709587.0}; + float outputs_RN[tableLength] = {18446744073709551617.0, + 4503599627370496.0, -4503599627370496.0, + 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, + 1.7976931348623157E38, 0, + 309485009821345068724781057.0, + 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, + -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, + 37778931862957161709568.0, 37778931862957161709569.0, + 37778931862957161709580.0, 37778931862957161709581.0, + 37778931862957161709582.0, 37778931862957161709583.0, + 37778931862957161709584.0, 37778931862957161709585.0, + 37778931862957161709586.0, 37778931862957161709587.0}; + float outputs_RZ[tableLength] = {18446744073709551617.0, + 4503599627370496.0, -4503599627370496.0, + 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, + 1.7976931348623157E38, 0, + 309485009821345068724781057.0, + 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, + -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, + 37778931862957161709568.0, 37778931862957161709569.0, + 37778931862957161709580.0, 37778931862957161709581.0, + 37778931862957161709582.0, 37778931862957161709583.0, + 37778931862957161709584.0, 37778931862957161709585.0, + 37778931862957161709586.0, 37778931862957161709587.0}; + float outputs_RP[tableLength] = {18446744073709551617.0, + 4503599627370496.0, -4503599627370496.0, + 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, + 1.7976931348623157E38, 1, + 309485009821345068724781057.0, + 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, + -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, + 37778931862957161709568.0, 37778931862957161709569.0, + 37778931862957161709580.0, 37778931862957161709581.0, + 37778931862957161709582.0, 37778931862957161709583.0, + 37778931862957161709584.0, 37778931862957161709585.0, + 37778931862957161709586.0, 37778931862957161709587.0}; + float outputs_RM[tableLength] = {18446744073709551617.0, + 4503599627370496.0, -4503599627370496.0, + 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, + 1.7976931348623157E38, 0, + 309485009821345068724781057.0, + 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, + -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, + 37778931862957161709568.0, 37778931862957161709569.0, + 37778931862957161709580.0, 37778931862957161709581.0, + 37778931862957161709582.0, 37778931862957161709583.0, + 37778931862957161709584.0, 37778931862957161709585.0, + 37778931862957161709586.0, 37778931862957161709587.0}; + int fcsr_inputs[4] = + {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf}; + float* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM}; + __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, a)) ); + __ lw(t0, MemOperand(a0, offsetof(TestFloat, fcsr)) ); + __ cfc1(t1, FCSR); + __ ctc1(t0, FCSR); + __ rint_s(f8, f4); + __ swc1(f8, MemOperand(a0, offsetof(TestFloat, b)) ); __ ctc1(t1, FCSR); __ jr(ra); __ nop(); @@ -1568,7 +1792,6 @@ TEST(MIPS18) { test.fcsr = fcsr_inputs[j]; for (int i = 0; i < tableLength; i++) { test.a = inputs[i]; - std::cout << j << " " << i << "\n"; (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); CHECK_EQ(test.b, outputs[j][i]); } @@ -1577,7 +1800,356 @@ TEST(MIPS18) { } -TEST(MIPS19) { +TEST(mina_maxa) { + if (IsMipsArchVariant(kMips32r6)) { + const int tableLength = 12; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double a; + double b; + double resd; + double resd1; + float c; + float d; + float resf; + float resf1; + }TestFloat; + + TestFloat test; + double inputsa[tableLength] = { + 5.3, 4.8, 6.1, + 9.8, 9.8, 9.8, + -10.0, -8.9, -9.8, + -10.0, -8.9, -9.8 + }; + double inputsb[tableLength] = { + 4.8, 5.3, 6.1, + -10.0, -8.9, -9.8, + 9.8, 9.8, 9.8, + -9.8, -11.2, -9.8 + }; + double resd[tableLength] = { + 4.8, 4.8, 6.1, + 9.8, -8.9, 9.8, + 9.8, -8.9, 9.8, + -9.8, -8.9, -9.8 + }; + double resd1[tableLength] = { + 5.3, 5.3, 6.1, + -10.0, 9.8, 9.8, + -10.0, 9.8, 9.8, + -10.0, -11.2, -9.8 + }; + float inputsc[tableLength] = { + 5.3, 4.8, 6.1, + 9.8, 9.8, 9.8, + -10.0, -8.9, -9.8, + -10.0, -8.9, -9.8 + }; + float inputsd[tableLength] = { + 4.8, 5.3, 6.1, + -10.0, -8.9, -9.8, + 9.8, 9.8, 9.8, + -9.8, -11.2, -9.8 + }; + float resf[tableLength] = { + 4.8, 4.8, 6.1, + 9.8, -8.9, 9.8, + 9.8, -8.9, 9.8, + -9.8, -8.9, -9.8 + }; + float resf1[tableLength] = { + 5.3, 5.3, 6.1, + -10.0, 9.8, 9.8, + -10.0, 9.8, 9.8, + -10.0, -11.2, -9.8 + }; + + __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); + __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, b)) ); + __ lwc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); + __ lwc1(f10, MemOperand(a0, offsetof(TestFloat, d)) ); + __ mina_d(f6, f2, f4); + __ mina_s(f12, f8, f10); + __ maxa_d(f14, f2, f4); + __ maxa_s(f16, f8, f10); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, resf)) ); + __ sdc1(f6, MemOperand(a0, offsetof(TestFloat, resd)) ); + __ swc1(f16, MemOperand(a0, offsetof(TestFloat, resf1)) ); + __ sdc1(f14, MemOperand(a0, offsetof(TestFloat, resd1)) ); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputsa[i]; + test.b = inputsb[i]; + test.c = inputsc[i]; + test.d = inputsd[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.resd, resd[i]); + CHECK_EQ(test.resf, resf[i]); + CHECK_EQ(test.resd1, resd1[i]); + CHECK_EQ(test.resf1, resf1[i]); + } + } +} + + +// ----------------------mips32r2 specific tests---------------------- +TEST(trunc_l) { + if (IsMipsArchVariant(kMips32r2) && IsFp64Mode()) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); + typedef struct test_float { + double a; + float b; + int64_t c; // a trunc result + int64_t d; // b trunc result + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, + -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, + 2147483648.0, dFPU64InvalidResult, + dFPU64InvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ trunc_l_d(f8, f4); + __ trunc_l_s(f10, f6); + __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); + } + } +} + + +TEST(movz_movn) { + if (IsMipsArchVariant(kMips32r2)) { + const int tableLength = 4; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + int64_t rt; + double a; + double b; + double bold; + double b1; + double bold1; + float c; + float d; + float dold; + float d1; + float dold1; + }TestFloat; + + TestFloat test; + double inputs_D[tableLength] = { + 5.3, -5.3, 5.3, -2.9 + }; + double inputs_S[tableLength] = { + 4.8, 4.8, -4.8, -0.29 + }; + + float outputs_S[tableLength] = { + 4.8, 4.8, -4.8, -0.29 + }; + double outputs_D[tableLength] = { + 5.3, -5.3, 5.3, -2.9 + }; + + __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) ); + __ lw(t0, MemOperand(a0, offsetof(TestFloat, rt)) ); + __ li(t1, 0x0); + __ mtc1(t1, f12); + __ mtc1(t1, f10); + __ mtc1(t1, f16); + __ mtc1(t1, f14); + __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, bold)) ); + __ swc1(f10, MemOperand(a0, offsetof(TestFloat, dold)) ); + __ sdc1(f16, MemOperand(a0, offsetof(TestFloat, bold1)) ); + __ swc1(f14, MemOperand(a0, offsetof(TestFloat, dold1)) ); + __ movz_s(f10, f6, t0); + __ movz_d(f12, f2, t0); + __ movn_s(f14, f6, t0); + __ movn_d(f16, f2, t0); + __ swc1(f10, MemOperand(a0, offsetof(TestFloat, d)) ); + __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, b)) ); + __ swc1(f14, MemOperand(a0, offsetof(TestFloat, d1)) ); + __ sdc1(f16, MemOperand(a0, offsetof(TestFloat, b1)) ); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.c = inputs_S[i]; + + test.rt = 1; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.b, test.bold); + CHECK_EQ(test.d, test.dold); + CHECK_EQ(test.b1, outputs_D[i]); + CHECK_EQ(test.d1, outputs_S[i]); + + test.rt = 0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.b, outputs_D[i]); + CHECK_EQ(test.d, outputs_S[i]); + CHECK_EQ(test.b1, test.bold1); + CHECK_EQ(test.d1, test.dold1); + } + } +} + + +TEST(movt_movd) { + if (IsMipsArchVariant(kMips32r2)) { + const int tableLength = 4; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + + typedef struct test_float { + double srcd; + double dstd; + double dstdold; + double dstd1; + double dstdold1; + float srcf; + float dstf; + float dstfold; + float dstf1; + float dstfold1; + int32_t cc; + int32_t fcsr; + }TestFloat; + + TestFloat test; + double inputs_D[tableLength] = { + 5.3, -5.3, 20.8, -2.9 + }; + double inputs_S[tableLength] = { + 4.88, 4.8, -4.8, -0.29 + }; + + float outputs_S[tableLength] = { + 4.88, 4.8, -4.8, -0.29 + }; + double outputs_D[tableLength] = { + 5.3, -5.3, 20.8, -2.9 + }; + int condition_flags[8] = {0, 1, 2, 3, 4, 5, 6, 7}; + + for (int i = 0; i < tableLength; i++) { + test.srcd = inputs_D[i]; + test.srcf = inputs_S[i]; + + for (int j = 0; j< 8; j++) { + test.cc = condition_flags[j]; + if (test.cc == 0) { + test.fcsr = 1 << 23; + } else { + test.fcsr = 1 << (24+condition_flags[j]); + } + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, srcd)) ); + __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, srcf)) ); + __ lw(t1, MemOperand(a0, offsetof(TestFloat, fcsr)) ); + __ cfc1(t0, FCSR); + __ ctc1(t1, FCSR); + __ li(t2, 0x0); + __ mtc1(t2, f12); + __ mtc1(t2, f10); + __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstdold)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstfold)) ); + __ movt_s(f12, f4, test.cc); + __ movt_d(f10, f2, test.cc); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstf)) ); + __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstd)) ); + __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstdold1)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstfold1)) ); + __ movf_s(f12, f4, test.cc); + __ movf_d(f10, f2, test.cc); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstf1)) ); + __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstd1)) ); + __ ctc1(t0, FCSR); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dstf, outputs_S[i]); + CHECK_EQ(test.dstd, outputs_D[i]); + CHECK_EQ(test.dstf1, test.dstfold1); + CHECK_EQ(test.dstd1, test.dstdold1); + test.fcsr = 0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dstf, test.dstfold); + CHECK_EQ(test.dstd, test.dstdold); + CHECK_EQ(test.dstf1, outputs_S[i]); + CHECK_EQ(test.dstd1, outputs_D[i]); + } + } + } +} + + +// ----------------------tests for all archs-------------------------- +TEST(cvt_w_d) { CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); HandleScope scope(isolate); @@ -1628,12 +2200,12 @@ TEST(MIPS19) { int fcsr_inputs[4] = {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf}; double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM}; - __ ldc1(f4, MemOperand(a0, OFFSET_OF(Test, a)) ); - __ lw(t0, MemOperand(a0, OFFSET_OF(Test, fcsr)) ); + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lw(t0, MemOperand(a0, offsetof(Test, fcsr)) ); __ cfc1(t1, FCSR); __ ctc1(t0, FCSR); __ cvt_w_d(f8, f4); - __ swc1(f8, MemOperand(a0, OFFSET_OF(Test, b)) ); + __ swc1(f8, MemOperand(a0, offsetof(Test, b)) ); __ ctc1(t1, FCSR); __ jr(ra); __ nop(); @@ -1647,7 +2219,6 @@ TEST(MIPS19) { test.fcsr = fcsr_inputs[j]; for (int i = 0; i < tableLength; i++) { test.a = inputs[i]; - std::cout << i << " " << j << "\n"; (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); CHECK_EQ(test.b, outputs[j][i]); } @@ -1655,6 +2226,750 @@ TEST(MIPS19) { } +TEST(trunc_w) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double a; + float b; + int32_t c; // a trunc result + int32_t d; // b trunc result + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, + -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, + kFPUInvalidResult, kFPUInvalidResult, + kFPUInvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ trunc_w_d(f8, f4); + __ trunc_w_s(f10, f6); + __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); + } +} + + +TEST(round_w) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double a; + float b; + int32_t c; // a trunc result + int32_t d; // b trunc result + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, + -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, + kFPUInvalidResult, kFPUInvalidResult, + kFPUInvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ round_w_d(f8, f4); + __ round_w_s(f10, f6); + __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); + } +} + + +TEST(round_l) { + if (IsFp64Mode()) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); + typedef struct test_float { + double a; + float b; + int64_t c; + int64_t d; + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, + -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, + 2147483648.0, dFPU64InvalidResult, + dFPU64InvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ round_l_d(f8, f4); + __ round_l_s(f10, f6); + __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); + } + } +} + + +TEST(sub) { + const int tableLength = 12; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + float a; + float b; + float resultS; + double c; + double d; + double resultD; + }TestFloat; + + TestFloat test; + double inputfs_D[tableLength] = { + 5.3, 4.8, 2.9, -5.3, -4.8, -2.9, + 5.3, 4.8, 2.9, -5.3, -4.8, -2.9 + }; + double inputft_D[tableLength] = { + 4.8, 5.3, 2.9, 4.8, 5.3, 2.9, + -4.8, -5.3, -2.9, -4.8, -5.3, -2.9 + }; + double outputs_D[tableLength] = { + 0.5, -0.5, 0.0, -10.1, -10.1, -5.8, + 10.1, 10.1, 5.8, -0.5, 0.5, 0.0 + }; + float inputfs_S[tableLength] = { + 5.3, 4.8, 2.9, -5.3, -4.8, -2.9, + 5.3, 4.8, 2.9, -5.3, -4.8, -2.9 + }; + float inputft_S[tableLength] = { + 4.8, 5.3, 2.9, 4.8, 5.3, 2.9, + -4.8, -5.3, -2.9, -4.8, -5.3, -2.9 + }; + float outputs_S[tableLength] = { + 0.5, -0.5, 0.0, -10.1, -10.1, -5.8, + 10.1, 10.1, 5.8, -0.5, 0.5, 0.0 + }; + __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); + __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)) ); + __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); + __ ldc1(f10, MemOperand(a0, offsetof(TestFloat, d)) ); + __ sub_s(f6, f2, f4); + __ sub_d(f12, f8, f10); + __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) ); + __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputfs_S[i]; + test.b = inputft_S[i]; + test.c = inputfs_D[i]; + test.d = inputft_D[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.resultS, outputs_S[i]); + CHECK_EQ(test.resultD, outputs_D[i]); + } +} + + +TEST(sqrt_rsqrt_recip) { + const int tableLength = 4; + const double deltaDouble = 2E-15; + const float deltaFloat = 2E-7; + const float sqrt2_s = sqrt(2); + const double sqrt2_d = sqrt(2); + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + float a; + float resultS; + float resultS1; + float resultS2; + double c; + double resultD; + double resultD1; + double resultD2; + }TestFloat; + TestFloat test; + + double inputs_D[tableLength] = { + 0.0L, 4.0L, 2.0L, 4e-28L + }; + + double outputs_D[tableLength] = { + 0.0L, 2.0L, sqrt2_d, 2e-14L + }; + float inputs_S[tableLength] = { + 0.0, 4.0, 2.0, 4e-28 + }; + + float outputs_S[tableLength] = { + 0.0, 2.0, sqrt2_s, 2e-14 + }; + + + __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); + __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); + __ sqrt_s(f6, f2); + __ sqrt_d(f12, f8); + + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + __ rsqrt_d(f14, f8); + __ rsqrt_s(f16, f2); + __ recip_d(f18, f8); + __ recip_s(f20, f2); + } + __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) ); + __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); + + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + __ swc1(f16, MemOperand(a0, offsetof(TestFloat, resultS1)) ); + __ sdc1(f14, MemOperand(a0, offsetof(TestFloat, resultD1)) ); + __ swc1(f20, MemOperand(a0, offsetof(TestFloat, resultS2)) ); + __ sdc1(f18, MemOperand(a0, offsetof(TestFloat, resultD2)) ); + } + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + + for (int i = 0; i < tableLength; i++) { + float f1; + double d1; + test.a = inputs_S[i]; + test.c = inputs_D[i]; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + + CHECK_EQ(test.resultS, outputs_S[i]); + CHECK_EQ(test.resultD, outputs_D[i]); + + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + if (i != 0) { + f1 = test.resultS1 - 1.0F/outputs_S[i]; + f1 = (f1 < 0) ? f1 : -f1; + CHECK(f1 <= deltaFloat); + d1 = test.resultD1 - 1.0L/outputs_D[i]; + d1 = (d1 < 0) ? d1 : -d1; + CHECK(d1 <= deltaDouble); + f1 = test.resultS2 - 1.0F/inputs_S[i]; + f1 = (f1 < 0) ? f1 : -f1; + CHECK(f1 <= deltaFloat); + d1 = test.resultD2 - 1.0L/inputs_D[i]; + d1 = (d1 < 0) ? d1 : -d1; + CHECK(d1 <= deltaDouble); + } else { + CHECK_EQ(test.resultS1, 1.0F/outputs_S[i]); + CHECK_EQ(test.resultD1, 1.0L/outputs_D[i]); + CHECK_EQ(test.resultS2, 1.0F/inputs_S[i]); + CHECK_EQ(test.resultD2, 1.0L/inputs_D[i]); + } + } + } +} + + +TEST(neg) { + const int tableLength = 3; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + float a; + float resultS; + double c; + double resultD; + }TestFloat; + + TestFloat test; + double inputs_D[tableLength] = { + 0.0, 4.0, -2.0 + }; + + double outputs_D[tableLength] = { + 0.0, -4.0, 2.0 + }; + float inputs_S[tableLength] = { + 0.0, 4.0, -2.0 + }; + + float outputs_S[tableLength] = { + 0.0, -4.0, 2.0 + }; + __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); + __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); + __ neg_s(f6, f2); + __ neg_d(f12, f8); + __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) ); + __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_S[i]; + test.c = inputs_D[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.resultS, outputs_S[i]); + CHECK_EQ(test.resultD, outputs_D[i]); + } +} + + +TEST(mul) { + const int tableLength = 4; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + float a; + float b; + float resultS; + double c; + double d; + double resultD; + }TestFloat; + + TestFloat test; + double inputfs_D[tableLength] = { + 5.3, -5.3, 5.3, -2.9 + }; + double inputft_D[tableLength] = { + 4.8, 4.8, -4.8, -0.29 + }; + + float inputfs_S[tableLength] = { + 5.3, -5.3, 5.3, -2.9 + }; + float inputft_S[tableLength] = { + 4.8, 4.8, -4.8, -0.29 + }; + + __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); + __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)) ); + __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, c)) ); + __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, d)) ); + __ mul_s(f10, f2, f4); + __ mul_d(f12, f6, f8); + __ swc1(f10, MemOperand(a0, offsetof(TestFloat, resultS)) ); + __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputfs_S[i]; + test.b = inputft_S[i]; + test.c = inputfs_D[i]; + test.d = inputft_D[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.resultS, inputfs_S[i]*inputft_S[i]); + CHECK_EQ(test.resultD, inputfs_D[i]*inputft_D[i]); + } +} + + +TEST(mov) { + const int tableLength = 4; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double a; + double b; + float c; + float d; + }TestFloat; + + TestFloat test; + double inputs_D[tableLength] = { + 5.3, -5.3, 5.3, -2.9 + }; + double inputs_S[tableLength] = { + 4.8, 4.8, -4.8, -0.29 + }; + + float outputs_S[tableLength] = { + 4.8, 4.8, -4.8, -0.29 + }; + double outputs_D[tableLength] = { + 5.3, -5.3, 5.3, -2.9 + }; + + __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) ); + __ mov_s(f18, f6); + __ mov_d(f20, f2); + __ swc1(f18, MemOperand(a0, offsetof(TestFloat, d)) ); + __ sdc1(f20, MemOperand(a0, offsetof(TestFloat, b)) ); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.c = inputs_S[i]; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.b, outputs_D[i]); + CHECK_EQ(test.d, outputs_S[i]); + } +} + + +TEST(floor_w) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double a; + float b; + int32_t c; // a floor result + int32_t d; // b floor result + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, + -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, + kFPUInvalidResult, kFPUInvalidResult, + kFPUInvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ floor_w_d(f8, f4); + __ floor_w_s(f10, f6); + __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); + } +} + + +TEST(floor_l) { + if (IsFp64Mode()) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); + typedef struct test_float { + double a; + float b; + int64_t c; + int64_t d; + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, + -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, + 2147483648.0, dFPU64InvalidResult, + dFPU64InvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ floor_l_d(f8, f4); + __ floor_l_s(f10, f6); + __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); + } + } +} + + +TEST(ceil_w) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double a; + float b; + int32_t c; // a floor result + int32_t d; // b floor result + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, + -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, + kFPUInvalidResult, kFPUInvalidResult, + kFPUInvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ ceil_w_d(f8, f4); + __ ceil_w_s(f10, f6); + __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); + } +} + + +TEST(ceil_l) { + if (IsFp64Mode()) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); + typedef struct test_float { + double a; + float b; + int64_t c; + int64_t d; + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, + -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, + 2147483648.0, dFPU64InvalidResult, + dFPU64InvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ ceil_l_d(f8, f4); + __ ceil_l_s(f10, f6); + __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); + } + } +} + + TEST(jump_tables1) { // Test jump tables with forward jumps. CcTest::InitializeVM(); @@ -1869,4 +3184,1879 @@ TEST(jump_tables3) { } +TEST(BITSWAP) { + // Test BITSWAP + if (IsMipsArchVariant(kMips32r6)) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + typedef struct { + int32_t r1; + int32_t r2; + int32_t r3; + int32_t r4; + } T; + T t; + + Assembler assm(isolate, NULL, 0); + + __ lw(a2, MemOperand(a0, offsetof(T, r1))); + __ nop(); + __ bitswap(a1, a2); + __ sw(a1, MemOperand(a0, offsetof(T, r1))); + + __ lw(a2, MemOperand(a0, offsetof(T, r2))); + __ nop(); + __ bitswap(a1, a2); + __ sw(a1, MemOperand(a0, offsetof(T, r2))); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + t.r1 = 0x781A15C3; + t.r2 = 0x8B71FCDE; + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); + USE(dummy); + + CHECK_EQ(static_cast<int32_t>(0x1E58A8C3), t.r1); + CHECK_EQ(static_cast<int32_t>(0xD18E3F7B), t.r2); + } +} + + +TEST(class_fmt) { + if (IsMipsArchVariant(kMips32r6)) { + // Test CLASS.fmt instruction. + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + typedef struct { + double dSignalingNan; + double dQuietNan; + double dNegInf; + double dNegNorm; + double dNegSubnorm; + double dNegZero; + double dPosInf; + double dPosNorm; + double dPosSubnorm; + double dPosZero; + float fSignalingNan; + float fQuietNan; + float fNegInf; + float fNegNorm; + float fNegSubnorm; + float fNegZero; + float fPosInf; + float fPosNorm; + float fPosSubnorm; + float fPosZero; } T; + T t; + + // Create a function that accepts &t, and loads, manipulates, and stores + // the doubles t.a ... t.f. + MacroAssembler assm(isolate, NULL, 0); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dSignalingNan))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dSignalingNan))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dQuietNan))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dQuietNan))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dNegInf))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dNegInf))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dNegNorm))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dNegNorm))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dNegSubnorm))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dNegSubnorm))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dNegZero))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dNegZero))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dPosInf))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dPosInf))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dPosNorm))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dPosNorm))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dPosSubnorm))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dPosSubnorm))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dPosZero))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dPosZero))); + + // Testing instruction CLASS.S + __ lwc1(f4, MemOperand(a0, offsetof(T, fSignalingNan))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fSignalingNan))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fQuietNan))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fQuietNan))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fNegInf))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fNegInf))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fNegNorm))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fNegNorm))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fNegSubnorm))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fNegSubnorm))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fNegZero))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fNegZero))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fPosInf))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fPosInf))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fPosNorm))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fPosNorm))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fPosSubnorm))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fPosSubnorm))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fPosZero))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fPosZero))); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + + t.dSignalingNan = std::numeric_limits<double>::signaling_NaN(); + t.dQuietNan = std::numeric_limits<double>::quiet_NaN(); + t.dNegInf = -1.0 / 0.0; + t.dNegNorm = -5.0; + t.dNegSubnorm = -DBL_MIN / 2.0; + t.dNegZero = -0.0; + t.dPosInf = 2.0 / 0.0; + t.dPosNorm = 275.35; + t.dPosSubnorm = DBL_MIN / 2.0; + t.dPosZero = +0.0; + // Float test values + + t.fSignalingNan = std::numeric_limits<float>::signaling_NaN(); + t.fQuietNan = std::numeric_limits<float>::quiet_NaN(); + t.fNegInf = -0.5/0.0; + t.fNegNorm = -FLT_MIN; + t.fNegSubnorm = -FLT_MIN / 1.5; + t.fNegZero = -0.0; + t.fPosInf = 100000.0 / 0.0; + t.fPosNorm = FLT_MAX; + t.fPosSubnorm = FLT_MIN / 20.0; + t.fPosZero = +0.0; + + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); + USE(dummy); + // Expected double results. + CHECK_EQ(bit_cast<int64_t>(t.dSignalingNan), 0x001); + CHECK_EQ(bit_cast<int64_t>(t.dQuietNan), 0x002); + CHECK_EQ(bit_cast<int64_t>(t.dNegInf), 0x004); + CHECK_EQ(bit_cast<int64_t>(t.dNegNorm), 0x008); + CHECK_EQ(bit_cast<int64_t>(t.dNegSubnorm), 0x010); + CHECK_EQ(bit_cast<int64_t>(t.dNegZero), 0x020); + CHECK_EQ(bit_cast<int64_t>(t.dPosInf), 0x040); + CHECK_EQ(bit_cast<int64_t>(t.dPosNorm), 0x080); + CHECK_EQ(bit_cast<int64_t>(t.dPosSubnorm), 0x100); + CHECK_EQ(bit_cast<int64_t>(t.dPosZero), 0x200); + + // Expected float results. + CHECK_EQ(bit_cast<int32_t>(t.fSignalingNan), 0x001); + CHECK_EQ(bit_cast<int32_t>(t.fQuietNan), 0x002); + CHECK_EQ(bit_cast<int32_t>(t.fNegInf), 0x004); + CHECK_EQ(bit_cast<int32_t>(t.fNegNorm), 0x008); + CHECK_EQ(bit_cast<int32_t>(t.fNegSubnorm), 0x010); + CHECK_EQ(bit_cast<int32_t>(t.fNegZero), 0x020); + CHECK_EQ(bit_cast<int32_t>(t.fPosInf), 0x040); + CHECK_EQ(bit_cast<int32_t>(t.fPosNorm), 0x080); + CHECK_EQ(bit_cast<int32_t>(t.fPosSubnorm), 0x100); + CHECK_EQ(bit_cast<int32_t>(t.fPosZero), 0x200); + } +} + + +TEST(ABS) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + int64_t fir; + double a; + float b; + double fcsr; + } TestFloat; + + TestFloat test; + + // Save FIR. + __ cfc1(a1, FCSR); + // Disable FPU exceptions. + __ ctc1(zero_reg, FCSR); + + __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); + __ abs_d(f10, f4); + __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, a))); + + __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b))); + __ abs_s(f10, f4); + __ swc1(f10, MemOperand(a0, offsetof(TestFloat, b))); + + // Restore FCSR. + __ ctc1(a1, FCSR); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + test.a = -2.0; + test.b = -2.0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.a, 2.0); + CHECK_EQ(test.b, 2.0); + + test.a = 2.0; + test.b = 2.0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.a, 2.0); + CHECK_EQ(test.b, 2.0); + + // Testing biggest positive number + test.a = std::numeric_limits<double>::max(); + test.b = std::numeric_limits<float>::max(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.a, std::numeric_limits<double>::max()); + CHECK_EQ(test.b, std::numeric_limits<float>::max()); + + // Testing smallest negative number + test.a = -std::numeric_limits<double>::max(); // lowest() + test.b = -std::numeric_limits<float>::max(); // lowest() + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.a, std::numeric_limits<double>::max()); + CHECK_EQ(test.b, std::numeric_limits<float>::max()); + + // Testing smallest positive number + test.a = -std::numeric_limits<double>::min(); + test.b = -std::numeric_limits<float>::min(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.a, std::numeric_limits<double>::min()); + CHECK_EQ(test.b, std::numeric_limits<float>::min()); + + // Testing infinity + test.a = -std::numeric_limits<double>::max() + / std::numeric_limits<double>::min(); + test.b = -std::numeric_limits<float>::max() + / std::numeric_limits<float>::min(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.a, std::numeric_limits<double>::max() + / std::numeric_limits<double>::min()); + CHECK_EQ(test.b, std::numeric_limits<float>::max() + / std::numeric_limits<float>::min()); + + test.a = std::numeric_limits<double>::quiet_NaN(); + test.b = std::numeric_limits<float>::quiet_NaN(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(std::isnan(test.a), true); + CHECK_EQ(std::isnan(test.b), true); + + test.a = std::numeric_limits<double>::signaling_NaN(); + test.b = std::numeric_limits<float>::signaling_NaN(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(std::isnan(test.a), true); + CHECK_EQ(std::isnan(test.b), true); +} + + +TEST(ADD_FMT) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double a; + double b; + double c; + float fa; + float fb; + float fc; + } TestFloat; + + TestFloat test; + + __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); + __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b))); + __ add_d(f10, f8, f4); + __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c))); + + __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, fa))); + __ lwc1(f8, MemOperand(a0, offsetof(TestFloat, fb))); + __ add_s(f10, f8, f4); + __ swc1(f10, MemOperand(a0, offsetof(TestFloat, fc))); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + test.a = 2.0; + test.b = 3.0; + test.fa = 2.0; + test.fb = 3.0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, 5.0); + CHECK_EQ(test.fc, 5.0); + + test.a = std::numeric_limits<double>::max(); + test.b = -std::numeric_limits<double>::max(); // lowest() + test.fa = std::numeric_limits<float>::max(); + test.fb = -std::numeric_limits<float>::max(); // lowest() + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, 0.0); + CHECK_EQ(test.fc, 0.0); + + test.a = std::numeric_limits<double>::max(); + test.b = std::numeric_limits<double>::max(); + test.fa = std::numeric_limits<float>::max(); + test.fb = std::numeric_limits<float>::max(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(std::isfinite(test.c), false); + CHECK_EQ(std::isfinite(test.fc), false); + + test.a = 5.0; + test.b = std::numeric_limits<double>::signaling_NaN(); + test.fa = 5.0; + test.fb = std::numeric_limits<float>::signaling_NaN(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(std::isnan(test.c), true); + CHECK_EQ(std::isnan(test.fc), true); +} + + +TEST(C_COND_FMT) { + if ((IsMipsArchVariant(kMips32r1)) || (IsMipsArchVariant(kMips32r2))) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double dOp1; + double dOp2; + uint32_t dF; + uint32_t dUn; + uint32_t dEq; + uint32_t dUeq; + uint32_t dOlt; + uint32_t dUlt; + uint32_t dOle; + uint32_t dUle; + float fOp1; + float fOp2; + uint32_t fF; + uint32_t fUn; + uint32_t fEq; + uint32_t fUeq; + uint32_t fOlt; + uint32_t fUlt; + uint32_t fOle; + uint32_t fUle; + } TestFloat; + + TestFloat test; + + __ li(t1, 1); + + __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, dOp1))); + __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, dOp2))); + + __ lwc1(f14, MemOperand(a0, offsetof(TestFloat, fOp1))); + __ lwc1(f16, MemOperand(a0, offsetof(TestFloat, fOp2))); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(F, f4, f6, 0); + __ c_s(F, f14, f16, 2); + __ movt(t2, t1, 0); + __ movt(t3, t1, 2); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dF)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fF)) ); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(UN, f4, f6, 2); + __ c_s(UN, f14, f16, 4); + __ movt(t2, t1, 2); + __ movt(t3, t1, 4); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUn)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUn)) ); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(EQ, f4, f6, 4); + __ c_s(EQ, f14, f16, 6); + __ movt(t2, t1, 4); + __ movt(t3, t1, 6); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dEq)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fEq)) ); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(UEQ, f4, f6, 6); + __ c_s(UEQ, f14, f16, 0); + __ movt(t2, t1, 6); + __ movt(t3, t1, 0); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUeq)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUeq)) ); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(OLT, f4, f6, 0); + __ c_s(OLT, f14, f16, 2); + __ movt(t2, t1, 0); + __ movt(t3, t1, 2); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dOlt)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fOlt)) ); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(ULT, f4, f6, 2); + __ c_s(ULT, f14, f16, 4); + __ movt(t2, t1, 2); + __ movt(t3, t1, 4); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUlt)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUlt)) ); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(OLE, f4, f6, 4); + __ c_s(OLE, f14, f16, 6); + __ movt(t2, t1, 4); + __ movt(t3, t1, 6); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dOle)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fOle)) ); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(ULE, f4, f6, 6); + __ c_s(ULE, f14, f16, 0); + __ movt(t2, t1, 6); + __ movt(t3, t1, 0); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUle)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUle)) ); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + test.dOp1 = 2.0; + test.dOp2 = 3.0; + test.fOp1 = 2.0; + test.fOp2 = 3.0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dF, 0U); + CHECK_EQ(test.dUn, 0U); + CHECK_EQ(test.dEq, 0U); + CHECK_EQ(test.dUeq, 0U); + CHECK_EQ(test.dOlt, 1U); + CHECK_EQ(test.dUlt, 1U); + CHECK_EQ(test.dOle, 1U); + CHECK_EQ(test.dUle, 1U); + CHECK_EQ(test.fF, 0U); + CHECK_EQ(test.fUn, 0U); + CHECK_EQ(test.fEq, 0U); + CHECK_EQ(test.fUeq, 0U); + CHECK_EQ(test.fOlt, 1U); + CHECK_EQ(test.fUlt, 1U); + CHECK_EQ(test.fOle, 1U); + CHECK_EQ(test.fUle, 1U); + + test.dOp1 = std::numeric_limits<double>::max(); + test.dOp2 = std::numeric_limits<double>::min(); + test.fOp1 = std::numeric_limits<float>::min(); + test.fOp2 = -std::numeric_limits<float>::max(); // lowest() + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dF, 0U); + CHECK_EQ(test.dUn, 0U); + CHECK_EQ(test.dEq, 0U); + CHECK_EQ(test.dUeq, 0U); + CHECK_EQ(test.dOlt, 0U); + CHECK_EQ(test.dUlt, 0U); + CHECK_EQ(test.dOle, 0U); + CHECK_EQ(test.dUle, 0U); + CHECK_EQ(test.fF, 0U); + CHECK_EQ(test.fUn, 0U); + CHECK_EQ(test.fEq, 0U); + CHECK_EQ(test.fUeq, 0U); + CHECK_EQ(test.fOlt, 0U); + CHECK_EQ(test.fUlt, 0U); + CHECK_EQ(test.fOle, 0U); + CHECK_EQ(test.fUle, 0U); + + test.dOp1 = -std::numeric_limits<double>::max(); // lowest() + test.dOp2 = -std::numeric_limits<double>::max(); // lowest() + test.fOp1 = std::numeric_limits<float>::max(); + test.fOp2 = std::numeric_limits<float>::max(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dF, 0U); + CHECK_EQ(test.dUn, 0U); + CHECK_EQ(test.dEq, 1U); + CHECK_EQ(test.dUeq, 1U); + CHECK_EQ(test.dOlt, 0U); + CHECK_EQ(test.dUlt, 0U); + CHECK_EQ(test.dOle, 1U); + CHECK_EQ(test.dUle, 1U); + CHECK_EQ(test.fF, 0U); + CHECK_EQ(test.fUn, 0U); + CHECK_EQ(test.fEq, 1U); + CHECK_EQ(test.fUeq, 1U); + CHECK_EQ(test.fOlt, 0U); + CHECK_EQ(test.fUlt, 0U); + CHECK_EQ(test.fOle, 1U); + CHECK_EQ(test.fUle, 1U); + + test.dOp1 = std::numeric_limits<double>::quiet_NaN(); + test.dOp2 = 0.0; + test.fOp1 = std::numeric_limits<float>::quiet_NaN(); + test.fOp2 = 0.0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dF, 0U); + CHECK_EQ(test.dUn, 1U); + CHECK_EQ(test.dEq, 0U); + CHECK_EQ(test.dUeq, 1U); + CHECK_EQ(test.dOlt, 0U); + CHECK_EQ(test.dUlt, 1U); + CHECK_EQ(test.dOle, 0U); + CHECK_EQ(test.dUle, 1U); + CHECK_EQ(test.fF, 0U); + CHECK_EQ(test.fUn, 1U); + CHECK_EQ(test.fEq, 0U); + CHECK_EQ(test.fUeq, 1U); + CHECK_EQ(test.fOlt, 0U); + CHECK_EQ(test.fUlt, 1U); + CHECK_EQ(test.fOle, 0U); + CHECK_EQ(test.fUle, 1U); + } +} + + +TEST(CMP_COND_FMT) { + if (IsMipsArchVariant(kMips32r6)) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double dOp1; + double dOp2; + double dF; + double dUn; + double dEq; + double dUeq; + double dOlt; + double dUlt; + double dOle; + double dUle; + double dOr; + double dUne; + double dNe; + float fOp1; + float fOp2; + float fF; + float fUn; + float fEq; + float fUeq; + float fOlt; + float fUlt; + float fOle; + float fUle; + float fOr; + float fUne; + float fNe; + } TestFloat; + + TestFloat test; + + __ li(t1, 1); + + __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, dOp1))); + __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, dOp2))); + + __ lwc1(f14, MemOperand(a0, offsetof(TestFloat, fOp1))); + __ lwc1(f16, MemOperand(a0, offsetof(TestFloat, fOp2))); + + __ cmp_d(F, f2, f4, f6); + __ cmp_s(F, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dF)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fF)) ); + + __ cmp_d(UN, f2, f4, f6); + __ cmp_s(UN, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUn)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUn)) ); + + __ cmp_d(EQ, f2, f4, f6); + __ cmp_s(EQ, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dEq)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fEq)) ); + + __ cmp_d(UEQ, f2, f4, f6); + __ cmp_s(UEQ, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUeq)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUeq)) ); + + __ cmp_d(LT, f2, f4, f6); + __ cmp_s(LT, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOlt)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOlt)) ); + + __ cmp_d(ULT, f2, f4, f6); + __ cmp_s(ULT, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUlt)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUlt)) ); + + __ cmp_d(LE, f2, f4, f6); + __ cmp_s(LE, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOle)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOle)) ); + + __ cmp_d(ULE, f2, f4, f6); + __ cmp_s(ULE, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUle)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUle)) ); + + __ cmp_d(ORD, f2, f4, f6); + __ cmp_s(ORD, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOr)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOr)) ); + + __ cmp_d(UNE, f2, f4, f6); + __ cmp_s(UNE, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUne)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUne)) ); + + __ cmp_d(NE, f2, f4, f6); + __ cmp_s(NE, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dNe)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fNe)) ); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + uint64_t dTrue = 0xFFFFFFFFFFFFFFFF; + uint64_t dFalse = 0x0000000000000000; + uint32_t fTrue = 0xFFFFFFFF; + uint32_t fFalse = 0x00000000; + + test.dOp1 = 2.0; + test.dOp2 = 3.0; + test.fOp1 = 2.0; + test.fOp2 = 3.0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue); + + test.dOp1 = std::numeric_limits<double>::max(); + test.dOp2 = std::numeric_limits<double>::min(); + test.fOp1 = std::numeric_limits<float>::min(); + test.fOp2 = -std::numeric_limits<float>::max(); // lowest() + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUle), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUle), fFalse); + + test.dOp1 = -std::numeric_limits<double>::max(); // lowest() + test.dOp2 = -std::numeric_limits<double>::max(); // lowest() + test.fOp1 = std::numeric_limits<float>::max(); + test.fOp2 = std::numeric_limits<float>::max(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dEq), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dUne), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fEq), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue); + + test.dOp1 = std::numeric_limits<double>::quiet_NaN(); + test.dOp2 = 0.0; + test.fOp1 = std::numeric_limits<float>::quiet_NaN(); + test.fOp2 = 0.0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUn), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dOr), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUn), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue); + } +} + + +TEST(CVT) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + float cvt_d_s_in; + double cvt_d_s_out; + int32_t cvt_d_w_in; + double cvt_d_w_out; + int64_t cvt_d_l_in; + double cvt_d_l_out; + + float cvt_l_s_in; + int64_t cvt_l_s_out; + double cvt_l_d_in; + int64_t cvt_l_d_out; + + double cvt_s_d_in; + float cvt_s_d_out; + int32_t cvt_s_w_in; + float cvt_s_w_out; + int64_t cvt_s_l_in; + float cvt_s_l_out; + + float cvt_w_s_in; + int32_t cvt_w_s_out; + double cvt_w_d_in; + int32_t cvt_w_d_out; + } TestFloat; + + TestFloat test; + + // Save FCSR. + __ cfc1(a1, FCSR); + // Disable FPU exceptions. + __ ctc1(zero_reg, FCSR); + +#define GENERATE_CVT_TEST(x, y, z) \ + __ y##c1(f0, MemOperand(a0, offsetof(TestFloat, x##_in))); \ + __ x(f0, f0); \ + __ nop(); \ + __ z##c1(f0, MemOperand(a0, offsetof(TestFloat, x##_out))); + + GENERATE_CVT_TEST(cvt_d_s, lw, sd) + GENERATE_CVT_TEST(cvt_d_w, lw, sd) + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + GENERATE_CVT_TEST(cvt_d_l, ld, sd) + } + + if (IsFp64Mode()) { + GENERATE_CVT_TEST(cvt_l_s, lw, sd) + GENERATE_CVT_TEST(cvt_l_d, ld, sd) + } + + GENERATE_CVT_TEST(cvt_s_d, ld, sw) + GENERATE_CVT_TEST(cvt_s_w, lw, sw) + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + GENERATE_CVT_TEST(cvt_s_l, ld, sw) + } + + GENERATE_CVT_TEST(cvt_w_s, lw, sw) + GENERATE_CVT_TEST(cvt_w_d, ld, sw) + + // Restore FCSR. + __ ctc1(a1, FCSR); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + + test.cvt_d_s_in = -0.51; + test.cvt_d_w_in = -1; + test.cvt_d_l_in = -1; + test.cvt_l_s_in = -0.51; + test.cvt_l_d_in = -0.51; + test.cvt_s_d_in = -0.51; + test.cvt_s_w_in = -1; + test.cvt_s_l_in = -1; + test.cvt_w_s_in = -0.51; + test.cvt_w_d_in = -0.51; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); + } + if (IsFp64Mode()) { + CHECK_EQ(test.cvt_l_s_out, -1); + CHECK_EQ(test.cvt_l_d_out, -1); + } + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); + } + CHECK_EQ(test.cvt_w_s_out, -1); + CHECK_EQ(test.cvt_w_d_out, -1); + + + test.cvt_d_s_in = 0.49; + test.cvt_d_w_in = 1; + test.cvt_d_l_in = 1; + test.cvt_l_s_in = 0.49; + test.cvt_l_d_in = 0.49; + test.cvt_s_d_in = 0.49; + test.cvt_s_w_in = 1; + test.cvt_s_l_in = 1; + test.cvt_w_s_in = 0.49; + test.cvt_w_d_in = 0.49; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); + } + if (IsFp64Mode()) { + CHECK_EQ(test.cvt_l_s_out, 0); + CHECK_EQ(test.cvt_l_d_out, 0); + } + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); + } + CHECK_EQ(test.cvt_w_s_out, 0); + CHECK_EQ(test.cvt_w_d_out, 0); + + test.cvt_d_s_in = std::numeric_limits<float>::max(); + test.cvt_d_w_in = std::numeric_limits<int32_t>::max(); + test.cvt_d_l_in = std::numeric_limits<int64_t>::max(); + test.cvt_l_s_in = std::numeric_limits<float>::max(); + test.cvt_l_d_in = std::numeric_limits<double>::max(); + test.cvt_s_d_in = std::numeric_limits<double>::max(); + test.cvt_s_w_in = std::numeric_limits<int32_t>::max(); + test.cvt_s_l_in = std::numeric_limits<int64_t>::max(); + test.cvt_w_s_in = std::numeric_limits<float>::max(); + test.cvt_w_d_in = std::numeric_limits<double>::max(); + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); + } + if (IsFp64Mode()) { + CHECK_EQ(test.cvt_l_s_out, std::numeric_limits<int64_t>::max()); + CHECK_EQ(test.cvt_l_d_out, std::numeric_limits<int64_t>::max()); + } + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); + } + CHECK_EQ(test.cvt_w_s_out, std::numeric_limits<int32_t>::max()); + CHECK_EQ(test.cvt_w_d_out, std::numeric_limits<int32_t>::max()); + + + test.cvt_d_s_in = -std::numeric_limits<float>::max(); // lowest() + test.cvt_d_w_in = std::numeric_limits<int32_t>::min(); // lowest() + test.cvt_d_l_in = std::numeric_limits<int64_t>::min(); // lowest() + test.cvt_l_s_in = -std::numeric_limits<float>::max(); // lowest() + test.cvt_l_d_in = -std::numeric_limits<double>::max(); // lowest() + test.cvt_s_d_in = -std::numeric_limits<double>::max(); // lowest() + test.cvt_s_w_in = std::numeric_limits<int32_t>::min(); // lowest() + test.cvt_s_l_in = std::numeric_limits<int64_t>::min(); // lowest() + test.cvt_w_s_in = -std::numeric_limits<float>::max(); // lowest() + test.cvt_w_d_in = -std::numeric_limits<double>::max(); // lowest() + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); + } + // The returned value when converting from fixed-point to float-point + // is not consistent between board, simulator and specification + // in this test case, therefore modifying the test + if (IsFp64Mode()) { + CHECK(test.cvt_l_s_out == std::numeric_limits<int64_t>::min() || + test.cvt_l_s_out == std::numeric_limits<int64_t>::max()); + CHECK(test.cvt_l_d_out == std::numeric_limits<int64_t>::min() || + test.cvt_l_d_out == std::numeric_limits<int64_t>::max()); + } + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); + } + CHECK(test.cvt_w_s_out == std::numeric_limits<int32_t>::min() || + test.cvt_w_s_out == std::numeric_limits<int32_t>::max()); + CHECK(test.cvt_w_d_out == std::numeric_limits<int32_t>::min() || + test.cvt_w_d_out == std::numeric_limits<int32_t>::max()); + + + test.cvt_d_s_in = std::numeric_limits<float>::min(); + test.cvt_d_w_in = std::numeric_limits<int32_t>::min(); + test.cvt_d_l_in = std::numeric_limits<int64_t>::min(); + test.cvt_l_s_in = std::numeric_limits<float>::min(); + test.cvt_l_d_in = std::numeric_limits<double>::min(); + test.cvt_s_d_in = std::numeric_limits<double>::min(); + test.cvt_s_w_in = std::numeric_limits<int32_t>::min(); + test.cvt_s_l_in = std::numeric_limits<int64_t>::min(); + test.cvt_w_s_in = std::numeric_limits<float>::min(); + test.cvt_w_d_in = std::numeric_limits<double>::min(); + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); + } + if (IsFp64Mode()) { + CHECK_EQ(test.cvt_l_s_out, 0); + CHECK_EQ(test.cvt_l_d_out, 0); + } + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); + } + CHECK_EQ(test.cvt_w_s_out, 0); + CHECK_EQ(test.cvt_w_d_out, 0); +} + + +TEST(DIV_FMT) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test { + double dOp1; + double dOp2; + double dRes; + float fOp1; + float fOp2; + float fRes; + } Test; + + Test test; + + // Save FCSR. + __ cfc1(a1, FCSR); + // Disable FPU exceptions. + __ ctc1(zero_reg, FCSR); + + __ ldc1(f4, MemOperand(a0, offsetof(Test, dOp1)) ); + __ ldc1(f2, MemOperand(a0, offsetof(Test, dOp2)) ); + __ nop(); + __ div_d(f6, f4, f2); + __ sdc1(f6, MemOperand(a0, offsetof(Test, dRes)) ); + + __ lwc1(f4, MemOperand(a0, offsetof(Test, fOp1)) ); + __ lwc1(f2, MemOperand(a0, offsetof(Test, fOp2)) ); + __ nop(); + __ div_s(f6, f4, f2); + __ swc1(f6, MemOperand(a0, offsetof(Test, fRes)) ); + + // Restore FCSR. + __ ctc1(a1, FCSR); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F3 f = FUNCTION_CAST<F3>(code->entry()); + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + + const int test_size = 3; + + double dOp1[test_size] = { + 5.0, + DBL_MAX, + DBL_MAX, + }; + double dOp2[test_size] = { + 2.0, + 2.0, + -DBL_MAX, + }; + double dRes[test_size] = { + 2.5, + DBL_MAX / 2.0, + -1.0, + }; + float fOp1[test_size] = { + 5.0, + FLT_MAX, + FLT_MAX, + }; + float fOp2[test_size] = { + 2.0, + 2.0, + -FLT_MAX, + }; + float fRes[test_size] = { + 2.5, + FLT_MAX / 2.0, + -1.0, + }; + + for (int i = 0; i < test_size; i++) { + test.dOp1 = dOp1[i]; + test.dOp2 = dOp2[i]; + test.fOp1 = fOp1[i]; + test.fOp2 = fOp2[i]; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dRes, dRes[i]); + CHECK_EQ(test.fRes, fRes[i]); + } + + test.dOp1 = DBL_MAX; + test.dOp2 = -0.0; + test.fOp1 = FLT_MAX; + test.fOp2 = -0.0; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(false, std::isfinite(test.dRes)); + CHECK_EQ(false, std::isfinite(test.fRes)); + + test.dOp1 = 0.0; + test.dOp2 = -0.0; + test.fOp1 = 0.0; + test.fOp2 = -0.0; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(true, std::isnan(test.dRes)); + CHECK_EQ(true, std::isnan(test.fRes)); + + test.dOp1 = std::numeric_limits<double>::quiet_NaN(); + test.dOp2 = -5.0; + test.fOp1 = std::numeric_limits<float>::quiet_NaN(); + test.fOp2 = -5.0; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(true, std::isnan(test.dRes)); + CHECK_EQ(true, std::isnan(test.fRes)); +} + + +uint32_t run_align(uint32_t rs_value, uint32_t rt_value, uint8_t bp) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + __ align(v0, a0, a1, bp); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + uint32_t res = + reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(f, rs_value, + rt_value, + 0, 0, 0)); + + return res; +} + + +TEST(r6_align) { + if (IsMipsArchVariant(kMips32r6)) { + CcTest::InitializeVM(); + + struct TestCaseAlign { + uint32_t rs_value; + uint32_t rt_value; + uint8_t bp; + uint32_t expected_res; + }; + + struct TestCaseAlign tc[] = { + // rs_value, rt_value, bp, expected_res + { 0x11223344, 0xaabbccdd, 0, 0xaabbccdd }, + { 0x11223344, 0xaabbccdd, 1, 0xbbccdd11 }, + { 0x11223344, 0xaabbccdd, 2, 0xccdd1122 }, + { 0x11223344, 0xaabbccdd, 3, 0xdd112233 }, + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAlign); + for (size_t i = 0; i < nr_test_cases; ++i) { + CHECK_EQ(tc[i].expected_res, run_align(tc[i].rs_value, + tc[i].rt_value, tc[i].bp)); + } + } +} + +uint32_t PC; // The program counter. + +uint32_t run_aluipc(int16_t offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + __ aluipc(v0, offset); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + PC = (uint32_t) f; // Set the program counter. + + uint32_t res = + reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_aluipc) { + if (IsMipsArchVariant(kMips32r6)) { + CcTest::InitializeVM(); + + struct TestCaseAluipc { + int16_t offset; + }; + + struct TestCaseAluipc tc[] = { + // offset + { -32768 }, // 0x8000 + { -1 }, // 0xFFFF + { 0 }, + { 1 }, + { 32767 }, // 0x7FFF + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAluipc); + for (size_t i = 0; i < nr_test_cases; ++i) { + PC = 0; + uint32_t res = run_aluipc(tc[i].offset); + // Now, the program_counter (PC) is set. + uint32_t expected_res = ~0x0FFFF & (PC + (tc[i].offset << 16)); + CHECK_EQ(expected_res, res); + } + } +} + + +uint32_t run_auipc(int16_t offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + __ auipc(v0, offset); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + PC = (uint32_t) f; // Set the program counter. + + uint32_t res = + reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_auipc) { + if (IsMipsArchVariant(kMips32r6)) { + CcTest::InitializeVM(); + + struct TestCaseAuipc { + int16_t offset; + }; + + struct TestCaseAuipc tc[] = { + // offset + { -32768 }, // 0x8000 + { -1 }, // 0xFFFF + { 0 }, + { 1 }, + { 32767 }, // 0x7FFF + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAuipc); + for (size_t i = 0; i < nr_test_cases; ++i) { + PC = 0; + uint32_t res = run_auipc(tc[i].offset); + // Now, the program_counter (PC) is set. + uint32_t expected_res = PC + (tc[i].offset << 16); + CHECK_EQ(expected_res, res); + } + } +} + + +uint32_t run_lwpc(int offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + // 256k instructions; 2^8k + // addiu t7, t0, 0xffff; (0x250fffff) + // ... + // addiu t4, t0, 0x0000; (0x250c0000) + uint32_t addiu_start_1 = 0x25000000; + for (int32_t i = 0xfffff; i >= 0xc0000; --i) { + uint32_t addiu_new = addiu_start_1 + i; + __ dd(addiu_new); + } + + __ lwpc(t8, offset); // offset 0; 0xef080000 (t8 register) + __ mov(v0, t8); + + // 256k instructions; 2^8k + // addiu t0, t0, 0x0000; (0x25080000) + // ... + // addiu t3, t0, 0xffff; (0x250bffff) + uint32_t addiu_start_2 = 0x25000000; + for (int32_t i = 0x80000; i <= 0xbffff; ++i) { + uint32_t addiu_new = addiu_start_2 + i; + __ dd(addiu_new); + } + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + uint32_t res = + reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_lwpc) { + if (IsMipsArchVariant(kMips32r6)) { + CcTest::InitializeVM(); + + struct TestCaseLwpc { + int offset; + uint32_t expected_res; + }; + + struct TestCaseLwpc tc[] = { + // offset, expected_res + { -262144, 0x250fffff }, // offset 0x40000 + { -4, 0x250c0003 }, + { -1, 0x250c0000 }, + { 0, 0xef080000 }, + { 1, 0x03001025 }, // mov(v0, t8) + { 2, 0x25080000 }, + { 4, 0x25080002 }, + { 262143, 0x250bfffd }, // offset 0x3ffff + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLwpc); + for (size_t i = 0; i < nr_test_cases; ++i) { + uint32_t res = run_lwpc(tc[i].offset); + CHECK_EQ(tc[i].expected_res, res); + } + } +} + + +uint32_t run_jic(int16_t offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + Label get_program_counter, stop_execution; + __ push(ra); + __ li(v0, 0); + __ li(t1, 0x66); + + __ addiu(v0, v0, 0x1); // <-- offset = -32 + __ addiu(v0, v0, 0x2); + __ addiu(v0, v0, 0x10); + __ addiu(v0, v0, 0x20); + __ beq(v0, t1, &stop_execution); + __ nop(); + + __ bal(&get_program_counter); // t0 <- program counter + __ nop(); + __ jic(t0, offset); + + __ addiu(v0, v0, 0x100); + __ addiu(v0, v0, 0x200); + __ addiu(v0, v0, 0x1000); + __ addiu(v0, v0, 0x2000); // <--- offset = 16 + __ pop(ra); + __ jr(ra); + __ nop(); + + __ bind(&get_program_counter); + __ mov(t0, ra); + __ jr(ra); + __ nop(); + + __ bind(&stop_execution); + __ pop(ra); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + uint32_t res = + reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_jic) { + if (IsMipsArchVariant(kMips32r6)) { + CcTest::InitializeVM(); + + struct TestCaseJic { + // As rt will be used t0 register which will have value of + // the program counter for the jic instruction. + int16_t offset; + uint32_t expected_res; + }; + + struct TestCaseJic tc[] = { + // offset, expected_result + { 16, 0x2033 }, + { 4, 0x3333 }, + { -32, 0x66 }, + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJic); + for (size_t i = 0; i < nr_test_cases; ++i) { + uint32_t res = run_jic(tc[i].offset); + CHECK_EQ(tc[i].expected_res, res); + } + } +} + + +uint64_t run_beqzc(int32_t value, int32_t offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + Label stop_execution; + __ li(v0, 0); + __ li(t1, 0x66); + __ push(ra); + + __ addiu(v0, v0, 0x1); // <-- offset = -32 + __ addiu(v0, v0, 0x2); + __ addiu(v0, v0, 0x10); + __ addiu(v0, v0, 0x20); + __ beq(v0, t1, &stop_execution); + __ nop(); + + __ beqzc(a0, offset); // BEQZC rs, offset + + __ addiu(v0, v0, 0x1); + __ addiu(v0, v0, 0x100); + __ addiu(v0, v0, 0x200); + __ addiu(v0, v0, 0x1000); + __ addiu(v0, v0, 0x2000); // <--- offset = 16 + __ jr(ra); + __ nop(); + + __ bind(&stop_execution); + __ pop(ra); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + uint32_t res = + reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(f, value, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_beqzc) { + if (IsMipsArchVariant(kMips32r6)) { + CcTest::InitializeVM(); + + struct TestCaseBeqzc { + uint32_t value; + int32_t offset; + uint32_t expected_res; + }; + + struct TestCaseBeqzc tc[] = { + // value, offset, expected_res + { 0x0, -8, 0x66 }, + { 0x0, 0, 0x3334 }, + { 0x0, 1, 0x3333 }, + { 0xabc, 1, 0x3334 }, + { 0x0, 4, 0x2033 }, + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBeqzc); + for (size_t i = 0; i < nr_test_cases; ++i) { + uint32_t res = run_beqzc(tc[i].value, tc[i].offset); + CHECK_EQ(tc[i].expected_res, res); + } + } +} + + +uint32_t run_jialc(int16_t offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + Label main_block, get_program_counter; + __ push(ra); + __ li(v0, 0); + __ beq(v0, v0, &main_block); + __ nop(); + + // Block 1 + __ addiu(v0, v0, 0x1); // <-- offset = -40 + __ addiu(v0, v0, 0x2); + __ jr(ra); + __ nop(); + + // Block 2 + __ addiu(v0, v0, 0x10); // <-- offset = -24 + __ addiu(v0, v0, 0x20); + __ jr(ra); + __ nop(); + + // Block 3 (Main) + __ bind(&main_block); + __ bal(&get_program_counter); // t0 <- program counter + __ nop(); + __ jialc(t0, offset); + __ addiu(v0, v0, 0x4); + __ pop(ra); + __ jr(ra); + __ nop(); + + // Block 4 + __ addiu(v0, v0, 0x100); // <-- offset = 20 + __ addiu(v0, v0, 0x200); + __ jr(ra); + __ nop(); + + // Block 5 + __ addiu(v0, v0, 0x1000); // <--- offset = 36 + __ addiu(v0, v0, 0x2000); + __ jr(ra); + __ nop(); + + __ bind(&get_program_counter); + __ mov(t0, ra); + __ jr(ra); + __ nop(); + + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + uint32_t res = + reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_jialc) { + if (IsMipsArchVariant(kMips32r6)) { + CcTest::InitializeVM(); + + struct TestCaseJialc { + int16_t offset; + uint32_t expected_res; + }; + + struct TestCaseJialc tc[] = { + // offset, expected_res + { -40, 0x7 }, + { -24, 0x34 }, + { 20, 0x304 }, + { 36, 0x3004 } + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJialc); + for (size_t i = 0; i < nr_test_cases; ++i) { + uint32_t res = run_jialc(tc[i].offset); + CHECK_EQ(tc[i].expected_res, res); + } + } +} + + +uint64_t run_addiupc(int32_t imm19) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + __ addiupc(v0, imm19); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + PC = (uint32_t) f; // Set the program counter. + + uint32_t rs = + reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(f, imm19, 0, 0, 0, 0)); + + return rs; +} + + +TEST(r6_addiupc) { + if (IsMipsArchVariant(kMips32r6)) { + CcTest::InitializeVM(); + + struct TestCaseAddiupc { + int32_t imm19; + }; + + struct TestCaseAddiupc tc[] = { + // imm19 + { -262144 }, // 0x40000 + { -1 }, // 0x7FFFF + { 0 }, + { 1 }, // 0x00001 + { 262143 } // 0x3FFFF + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAddiupc); + for (size_t i = 0; i < nr_test_cases; ++i) { + PC = 0; + uint32_t res = run_addiupc(tc[i].imm19); + // Now, the program_counter (PC) is set. + uint32_t expected_res = PC + (tc[i].imm19 << 2); + CHECK_EQ(expected_res, res); + } + } +} + + +int32_t run_bc(int32_t offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + Label continue_1, stop_execution; + __ push(ra); + __ li(v0, 0); + __ li(t8, 0); + __ li(t9, 2); // A condition for stopping execution. + + uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1 + for (int32_t i = -100; i <= -11; ++i) { + __ dd(instruction_addiu); + } + + __ addiu(t8, t8, 1); // -10 + + __ beq(t8, t9, &stop_execution); // -9 + __ nop(); // -8 + __ beq(t8, t8, &continue_1); // -7 + __ nop(); // -6 + + __ bind(&stop_execution); + __ pop(ra); // -5, -4 + __ jr(ra); // -3 + __ nop(); // -2 + + __ bind(&continue_1); + __ bc(offset); // -1 + + for (int32_t i = 0; i <= 99; ++i) { + __ dd(instruction_addiu); + } + + __ pop(ra); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + int32_t res = + reinterpret_cast<int32_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_bc) { + if (IsMipsArchVariant(kMips32r6)) { + CcTest::InitializeVM(); + + struct TestCaseBc { + int32_t offset; + int32_t expected_res; + }; + + struct TestCaseBc tc[] = { + // offset, expected_result + { -100, (abs(-100) - 10) * 2 }, + { -11, (abs(-100) - 10 + 1) }, + { 0, (abs(-100) - 10 + 1 + 99) }, + { 1, (abs(-100) - 10 + 99) }, + { 99, (abs(-100) - 10 + 1) }, + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBc); + for (size_t i = 0; i < nr_test_cases; ++i) { + int32_t res = run_bc(tc[i].offset); + CHECK_EQ(tc[i].expected_res, res); + } + } +} + + +int32_t run_balc(int32_t offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + Label continue_1, stop_execution; + __ push(ra); + __ li(v0, 0); + __ li(t8, 0); + __ li(t9, 2); // A condition for stopping execution. + + __ beq(t8, t8, &continue_1); + __ nop(); + + uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1 + for (int32_t i = -117; i <= -57; ++i) { + __ dd(instruction_addiu); + } + __ jr(ra); // -56 + __ nop(); // -55 + + for (int32_t i = -54; i <= -4; ++i) { + __ dd(instruction_addiu); + } + __ jr(ra); // -3 + __ nop(); // -2 + + __ bind(&continue_1); + __ balc(offset); // -1 + + __ pop(ra); // 0, 1 + __ jr(ra); // 2 + __ nop(); // 3 + + for (int32_t i = 4; i <= 44; ++i) { + __ dd(instruction_addiu); + } + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + int32_t res = + reinterpret_cast<int32_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_balc) { + if (IsMipsArchVariant(kMips32r6)) { + CcTest::InitializeVM(); + + struct TestCaseBalc { + int32_t offset; + int32_t expected_res; + }; + + struct TestCaseBalc tc[] = { + // offset, expected_result + { -117, 61 }, + { -54, 51 }, + { 0, 0 }, + { 4, 41 }, + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBalc); + for (size_t i = 0; i < nr_test_cases; ++i) { + int32_t res = run_balc(tc[i].offset); + CHECK_EQ(tc[i].expected_res, res); + } + } +} + + #undef __ diff --git a/deps/v8/test/cctest/test-assembler-mips64.cc b/deps/v8/test/cctest/test-assembler-mips64.cc index 3b422a2716..bb7b05ca76 100644 --- a/deps/v8/test/cctest/test-assembler-mips64.cc +++ b/deps/v8/test/cctest/test-assembler-mips64.cc @@ -45,6 +45,7 @@ using namespace v8::internal; typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); +typedef Object* (*F4)(int64_t x, int64_t y, int64_t p2, int64_t p3, int64_t p4); // clang-format off @@ -289,61 +290,61 @@ TEST(MIPS3) { Label L, C; // Double precision floating point instructions. - __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); - __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); + __ ldc1(f4, MemOperand(a0, offsetof(T, a)) ); + __ ldc1(f6, MemOperand(a0, offsetof(T, b)) ); __ add_d(f8, f4, f6); - __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) ); // c = a + b. + __ sdc1(f8, MemOperand(a0, offsetof(T, c)) ); // c = a + b. __ mov_d(f10, f8); // c __ neg_d(f12, f6); // -b __ sub_d(f10, f10, f12); - __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) ); // d = c - (-b). + __ sdc1(f10, MemOperand(a0, offsetof(T, d)) ); // d = c - (-b). - __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) ); // b = a. + __ sdc1(f4, MemOperand(a0, offsetof(T, b)) ); // b = a. __ li(a4, 120); __ mtc1(a4, f14); __ cvt_d_w(f14, f14); // f14 = 120.0. __ mul_d(f10, f10, f14); - __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) ); // e = d * 120 = 1.8066e16. + __ sdc1(f10, MemOperand(a0, offsetof(T, e)) ); // e = d * 120 = 1.8066e16. __ div_d(f12, f10, f4); - __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) ); // f = e / a = 120.44. + __ sdc1(f12, MemOperand(a0, offsetof(T, f)) ); // f = e / a = 120.44. __ sqrt_d(f14, f12); - __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) ); + __ sdc1(f14, MemOperand(a0, offsetof(T, g)) ); // g = sqrt(f) = 10.97451593465515908537 if (kArchVariant == kMips64r2) { - __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, h)) ); - __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, i)) ); + __ ldc1(f4, MemOperand(a0, offsetof(T, h)) ); + __ ldc1(f6, MemOperand(a0, offsetof(T, i)) ); __ madd_d(f14, f6, f4, f6); - __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, h)) ); + __ sdc1(f14, MemOperand(a0, offsetof(T, h)) ); } // Single precision floating point instructions. - __ lwc1(f4, MemOperand(a0, OFFSET_OF(T, fa)) ); - __ lwc1(f6, MemOperand(a0, OFFSET_OF(T, fb)) ); + __ lwc1(f4, MemOperand(a0, offsetof(T, fa)) ); + __ lwc1(f6, MemOperand(a0, offsetof(T, fb)) ); __ add_s(f8, f4, f6); - __ swc1(f8, MemOperand(a0, OFFSET_OF(T, fc)) ); // fc = fa + fb. + __ swc1(f8, MemOperand(a0, offsetof(T, fc)) ); // fc = fa + fb. __ neg_s(f10, f6); // -fb __ sub_s(f10, f8, f10); - __ swc1(f10, MemOperand(a0, OFFSET_OF(T, fd)) ); // fd = fc - (-fb). + __ swc1(f10, MemOperand(a0, offsetof(T, fd)) ); // fd = fc - (-fb). - __ swc1(f4, MemOperand(a0, OFFSET_OF(T, fb)) ); // fb = fa. + __ swc1(f4, MemOperand(a0, offsetof(T, fb)) ); // fb = fa. __ li(t0, 120); __ mtc1(t0, f14); __ cvt_s_w(f14, f14); // f14 = 120.0. __ mul_s(f10, f10, f14); - __ swc1(f10, MemOperand(a0, OFFSET_OF(T, fe)) ); // fe = fd * 120 + __ swc1(f10, MemOperand(a0, offsetof(T, fe)) ); // fe = fd * 120 __ div_s(f12, f10, f4); - __ swc1(f12, MemOperand(a0, OFFSET_OF(T, ff)) ); // ff = fe / fa + __ swc1(f12, MemOperand(a0, offsetof(T, ff)) ); // ff = fe / fa __ sqrt_s(f14, f12); - __ swc1(f14, MemOperand(a0, OFFSET_OF(T, fg)) ); + __ swc1(f14, MemOperand(a0, offsetof(T, fg)) ); __ jr(ra); __ nop(); @@ -412,8 +413,8 @@ TEST(MIPS4) { Assembler assm(isolate, NULL, 0); Label L, C; - __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a))); - __ ldc1(f5, MemOperand(a0, OFFSET_OF(T, b))); + __ ldc1(f4, MemOperand(a0, offsetof(T, a))); + __ ldc1(f5, MemOperand(a0, offsetof(T, b))); // Swap f4 and f5, by using 3 integer registers, a4-a6, // both two 32-bit chunks, and one 64-bit chunk. @@ -428,16 +429,16 @@ TEST(MIPS4) { __ dmtc1(a6, f4); // Store the swapped f4 and f5 back to memory. - __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a))); - __ sdc1(f5, MemOperand(a0, OFFSET_OF(T, c))); + __ sdc1(f4, MemOperand(a0, offsetof(T, a))); + __ sdc1(f5, MemOperand(a0, offsetof(T, c))); // Test sign extension of move operations from coprocessor. - __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, d))); + __ ldc1(f4, MemOperand(a0, offsetof(T, d))); __ mfhc1(a4, f4); __ mfc1(a5, f4); - __ sd(a4, MemOperand(a0, OFFSET_OF(T, high))); - __ sd(a5, MemOperand(a0, OFFSET_OF(T, low))); + __ sd(a4, MemOperand(a0, offsetof(T, high))); + __ sd(a5, MemOperand(a0, offsetof(T, low))); __ jr(ra); __ nop(); @@ -480,30 +481,30 @@ TEST(MIPS5) { Label L, C; // Load all structure elements to registers. - __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); - __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); - __ lw(a4, MemOperand(a0, OFFSET_OF(T, i)) ); - __ lw(a5, MemOperand(a0, OFFSET_OF(T, j)) ); + __ ldc1(f4, MemOperand(a0, offsetof(T, a)) ); + __ ldc1(f6, MemOperand(a0, offsetof(T, b)) ); + __ lw(a4, MemOperand(a0, offsetof(T, i)) ); + __ lw(a5, MemOperand(a0, offsetof(T, j)) ); // Convert double in f4 to int in element i. __ cvt_w_d(f8, f4); __ mfc1(a6, f8); - __ sw(a6, MemOperand(a0, OFFSET_OF(T, i)) ); + __ sw(a6, MemOperand(a0, offsetof(T, i)) ); // Convert double in f6 to int in element j. __ cvt_w_d(f10, f6); __ mfc1(a7, f10); - __ sw(a7, MemOperand(a0, OFFSET_OF(T, j)) ); + __ sw(a7, MemOperand(a0, offsetof(T, j)) ); // Convert int in original i (a4) to double in a. __ mtc1(a4, f12); __ cvt_d_w(f0, f12); - __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) ); + __ sdc1(f0, MemOperand(a0, offsetof(T, a)) ); // Convert int in original j (a5) to double in b. __ mtc1(a5, f14); __ cvt_d_w(f2, f14); - __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) ); + __ sdc1(f2, MemOperand(a0, offsetof(T, b)) ); __ jr(ra); __ nop(); @@ -549,31 +550,31 @@ TEST(MIPS6) { Label L, C; // Basic word load/store. - __ lw(a4, MemOperand(a0, OFFSET_OF(T, ui)) ); - __ sw(a4, MemOperand(a0, OFFSET_OF(T, r1)) ); + __ lw(a4, MemOperand(a0, offsetof(T, ui)) ); + __ sw(a4, MemOperand(a0, offsetof(T, r1)) ); // lh with positive data. - __ lh(a5, MemOperand(a0, OFFSET_OF(T, ui)) ); - __ sw(a5, MemOperand(a0, OFFSET_OF(T, r2)) ); + __ lh(a5, MemOperand(a0, offsetof(T, ui)) ); + __ sw(a5, MemOperand(a0, offsetof(T, r2)) ); // lh with negative data. - __ lh(a6, MemOperand(a0, OFFSET_OF(T, si)) ); - __ sw(a6, MemOperand(a0, OFFSET_OF(T, r3)) ); + __ lh(a6, MemOperand(a0, offsetof(T, si)) ); + __ sw(a6, MemOperand(a0, offsetof(T, r3)) ); // lhu with negative data. - __ lhu(a7, MemOperand(a0, OFFSET_OF(T, si)) ); - __ sw(a7, MemOperand(a0, OFFSET_OF(T, r4)) ); + __ lhu(a7, MemOperand(a0, offsetof(T, si)) ); + __ sw(a7, MemOperand(a0, offsetof(T, r4)) ); // lb with negative data. - __ lb(t0, MemOperand(a0, OFFSET_OF(T, si)) ); - __ sw(t0, MemOperand(a0, OFFSET_OF(T, r5)) ); + __ lb(t0, MemOperand(a0, offsetof(T, si)) ); + __ sw(t0, MemOperand(a0, offsetof(T, r5)) ); // sh writes only 1/2 of word. __ lui(t1, 0x3333); __ ori(t1, t1, 0x3333); - __ sw(t1, MemOperand(a0, OFFSET_OF(T, r6)) ); - __ lhu(t1, MemOperand(a0, OFFSET_OF(T, si)) ); - __ sh(t1, MemOperand(a0, OFFSET_OF(T, r6)) ); + __ sw(t1, MemOperand(a0, offsetof(T, r6)) ); + __ lhu(t1, MemOperand(a0, offsetof(T, si)) ); + __ sh(t1, MemOperand(a0, offsetof(T, r6)) ); __ jr(ra); __ nop(); @@ -619,8 +620,8 @@ TEST(MIPS7) { MacroAssembler assm(isolate, NULL, 0); Label neither_is_nan, less_than, outa_here; - __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); - __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); + __ ldc1(f4, MemOperand(a0, offsetof(T, a)) ); + __ ldc1(f6, MemOperand(a0, offsetof(T, b)) ); if (kArchVariant != kMips64r6) { __ c(UN, D, f4, f6); __ bc1f(&neither_is_nan); @@ -629,7 +630,7 @@ TEST(MIPS7) { __ bc1eqz(&neither_is_nan, f2); } __ nop(); - __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); + __ sw(zero_reg, MemOperand(a0, offsetof(T, result)) ); __ Branch(&outa_here); __ bind(&neither_is_nan); @@ -643,12 +644,12 @@ TEST(MIPS7) { } __ nop(); - __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); + __ sw(zero_reg, MemOperand(a0, offsetof(T, result)) ); __ Branch(&outa_here); __ bind(&less_than); __ Addu(a4, zero_reg, Operand(1)); - __ sw(a4, MemOperand(a0, OFFSET_OF(T, result)) ); // Set true. + __ sw(a4, MemOperand(a0, offsetof(T, result)) ); // Set true. // This test-case should have additional tests. @@ -707,7 +708,7 @@ TEST(MIPS8) { MacroAssembler assm(isolate, NULL, 0); // Basic word load. - __ lw(a4, MemOperand(a0, OFFSET_OF(T, input)) ); + __ lw(a4, MemOperand(a0, offsetof(T, input)) ); // ROTR instruction (called through the Ror macro). __ Ror(a5, a4, 0x0004); @@ -719,13 +720,13 @@ TEST(MIPS8) { __ Ror(t3, a4, 0x001c); // Basic word store. - __ sw(a5, MemOperand(a0, OFFSET_OF(T, result_rotr_4)) ); - __ sw(a6, MemOperand(a0, OFFSET_OF(T, result_rotr_8)) ); - __ sw(a7, MemOperand(a0, OFFSET_OF(T, result_rotr_12)) ); - __ sw(t0, MemOperand(a0, OFFSET_OF(T, result_rotr_16)) ); - __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotr_20)) ); - __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotr_24)) ); - __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotr_28)) ); + __ sw(a5, MemOperand(a0, offsetof(T, result_rotr_4)) ); + __ sw(a6, MemOperand(a0, offsetof(T, result_rotr_8)) ); + __ sw(a7, MemOperand(a0, offsetof(T, result_rotr_12)) ); + __ sw(t0, MemOperand(a0, offsetof(T, result_rotr_16)) ); + __ sw(t1, MemOperand(a0, offsetof(T, result_rotr_20)) ); + __ sw(t2, MemOperand(a0, offsetof(T, result_rotr_24)) ); + __ sw(t3, MemOperand(a0, offsetof(T, result_rotr_28)) ); // ROTRV instruction (called through the Ror macro). __ li(t3, 0x0004); @@ -744,13 +745,13 @@ TEST(MIPS8) { __ Ror(t3, a4, t3); // Basic word store. - __ sw(a5, MemOperand(a0, OFFSET_OF(T, result_rotrv_4)) ); - __ sw(a6, MemOperand(a0, OFFSET_OF(T, result_rotrv_8)) ); - __ sw(a7, MemOperand(a0, OFFSET_OF(T, result_rotrv_12)) ); - __ sw(t0, MemOperand(a0, OFFSET_OF(T, result_rotrv_16)) ); - __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotrv_20)) ); - __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotrv_24)) ); - __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotrv_28)) ); + __ sw(a5, MemOperand(a0, offsetof(T, result_rotrv_4)) ); + __ sw(a6, MemOperand(a0, offsetof(T, result_rotrv_8)) ); + __ sw(a7, MemOperand(a0, offsetof(T, result_rotrv_12)) ); + __ sw(t0, MemOperand(a0, offsetof(T, result_rotrv_16)) ); + __ sw(t1, MemOperand(a0, offsetof(T, result_rotrv_20)) ); + __ sw(t2, MemOperand(a0, offsetof(T, result_rotrv_24)) ); + __ sw(t3, MemOperand(a0, offsetof(T, result_rotrv_28)) ); __ jr(ra); __ nop(); @@ -838,42 +839,42 @@ TEST(MIPS10) { // - 32 FP regs of 64-bits each, no odd/even pairs. // - Note that cvt_l_d/cvt_d_l ARE legal in FR=1 mode. // Load all structure elements to registers. - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a))); + __ ldc1(f0, MemOperand(a0, offsetof(T, a))); // Save the raw bits of the double. __ mfc1(a4, f0); __ mfhc1(a5, f0); - __ sw(a4, MemOperand(a0, OFFSET_OF(T, dbl_mant))); - __ sw(a5, MemOperand(a0, OFFSET_OF(T, dbl_exp))); + __ sw(a4, MemOperand(a0, offsetof(T, dbl_mant))); + __ sw(a5, MemOperand(a0, offsetof(T, dbl_exp))); // Convert double in f0 to long, save hi/lo parts. __ cvt_l_d(f0, f0); __ mfc1(a4, f0); // f0 LS 32 bits of long. __ mfhc1(a5, f0); // f0 MS 32 bits of long. - __ sw(a4, MemOperand(a0, OFFSET_OF(T, long_lo))); - __ sw(a5, MemOperand(a0, OFFSET_OF(T, long_hi))); + __ sw(a4, MemOperand(a0, offsetof(T, long_lo))); + __ sw(a5, MemOperand(a0, offsetof(T, long_hi))); // Combine the high/low ints, convert back to double. __ dsll32(a6, a5, 0); // Move a5 to high bits of a6. __ or_(a6, a6, a4); __ dmtc1(a6, f1); __ cvt_d_l(f1, f1); - __ sdc1(f1, MemOperand(a0, OFFSET_OF(T, a_converted))); + __ sdc1(f1, MemOperand(a0, offsetof(T, a_converted))); // Convert the b long integers to double b. - __ lw(a4, MemOperand(a0, OFFSET_OF(T, b_long_lo))); - __ lw(a5, MemOperand(a0, OFFSET_OF(T, b_long_hi))); + __ lw(a4, MemOperand(a0, offsetof(T, b_long_lo))); + __ lw(a5, MemOperand(a0, offsetof(T, b_long_hi))); __ mtc1(a4, f8); // f8 LS 32-bits. __ mthc1(a5, f8); // f8 MS 32-bits. __ cvt_d_l(f10, f8); - __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b))); + __ sdc1(f10, MemOperand(a0, offsetof(T, b))); // Convert double b back to long-int. - __ ldc1(f31, MemOperand(a0, OFFSET_OF(T, b))); + __ ldc1(f31, MemOperand(a0, offsetof(T, b))); __ cvt_l_d(f31, f31); __ dmfc1(a7, f31); - __ sd(a7, MemOperand(a0, OFFSET_OF(T, b_long_as_int64))); + __ sd(a7, MemOperand(a0, offsetof(T, b_long_as_int64))); __ jr(ra); @@ -936,80 +937,80 @@ TEST(MIPS11) { Assembler assm(isolate, NULL, 0); // Test all combinations of LWL and vAddr. - __ lw(a4, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ lwl(a4, MemOperand(a0, OFFSET_OF(T, mem_init))); - __ sw(a4, MemOperand(a0, OFFSET_OF(T, lwl_0))); + __ lw(a4, MemOperand(a0, offsetof(T, reg_init))); + __ lwl(a4, MemOperand(a0, offsetof(T, mem_init))); + __ sw(a4, MemOperand(a0, offsetof(T, lwl_0))); - __ lw(a5, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ lwl(a5, MemOperand(a0, OFFSET_OF(T, mem_init) + 1)); - __ sw(a5, MemOperand(a0, OFFSET_OF(T, lwl_1))); + __ lw(a5, MemOperand(a0, offsetof(T, reg_init))); + __ lwl(a5, MemOperand(a0, offsetof(T, mem_init) + 1)); + __ sw(a5, MemOperand(a0, offsetof(T, lwl_1))); - __ lw(a6, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ lwl(a6, MemOperand(a0, OFFSET_OF(T, mem_init) + 2)); - __ sw(a6, MemOperand(a0, OFFSET_OF(T, lwl_2))); + __ lw(a6, MemOperand(a0, offsetof(T, reg_init))); + __ lwl(a6, MemOperand(a0, offsetof(T, mem_init) + 2)); + __ sw(a6, MemOperand(a0, offsetof(T, lwl_2))); - __ lw(a7, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ lwl(a7, MemOperand(a0, OFFSET_OF(T, mem_init) + 3)); - __ sw(a7, MemOperand(a0, OFFSET_OF(T, lwl_3))); + __ lw(a7, MemOperand(a0, offsetof(T, reg_init))); + __ lwl(a7, MemOperand(a0, offsetof(T, mem_init) + 3)); + __ sw(a7, MemOperand(a0, offsetof(T, lwl_3))); // Test all combinations of LWR and vAddr. - __ lw(a4, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ lwr(a4, MemOperand(a0, OFFSET_OF(T, mem_init))); - __ sw(a4, MemOperand(a0, OFFSET_OF(T, lwr_0))); + __ lw(a4, MemOperand(a0, offsetof(T, reg_init))); + __ lwr(a4, MemOperand(a0, offsetof(T, mem_init))); + __ sw(a4, MemOperand(a0, offsetof(T, lwr_0))); - __ lw(a5, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ lwr(a5, MemOperand(a0, OFFSET_OF(T, mem_init) + 1)); - __ sw(a5, MemOperand(a0, OFFSET_OF(T, lwr_1))); + __ lw(a5, MemOperand(a0, offsetof(T, reg_init))); + __ lwr(a5, MemOperand(a0, offsetof(T, mem_init) + 1)); + __ sw(a5, MemOperand(a0, offsetof(T, lwr_1))); - __ lw(a6, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ lwr(a6, MemOperand(a0, OFFSET_OF(T, mem_init) + 2)); - __ sw(a6, MemOperand(a0, OFFSET_OF(T, lwr_2)) ); + __ lw(a6, MemOperand(a0, offsetof(T, reg_init))); + __ lwr(a6, MemOperand(a0, offsetof(T, mem_init) + 2)); + __ sw(a6, MemOperand(a0, offsetof(T, lwr_2)) ); - __ lw(a7, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ lwr(a7, MemOperand(a0, OFFSET_OF(T, mem_init) + 3)); - __ sw(a7, MemOperand(a0, OFFSET_OF(T, lwr_3)) ); + __ lw(a7, MemOperand(a0, offsetof(T, reg_init))); + __ lwr(a7, MemOperand(a0, offsetof(T, mem_init) + 3)); + __ sw(a7, MemOperand(a0, offsetof(T, lwr_3)) ); // Test all combinations of SWL and vAddr. - __ lw(a4, MemOperand(a0, OFFSET_OF(T, mem_init))); - __ sw(a4, MemOperand(a0, OFFSET_OF(T, swl_0))); - __ lw(a4, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ swl(a4, MemOperand(a0, OFFSET_OF(T, swl_0))); - - __ lw(a5, MemOperand(a0, OFFSET_OF(T, mem_init))); - __ sw(a5, MemOperand(a0, OFFSET_OF(T, swl_1))); - __ lw(a5, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ swl(a5, MemOperand(a0, OFFSET_OF(T, swl_1) + 1)); - - __ lw(a6, MemOperand(a0, OFFSET_OF(T, mem_init))); - __ sw(a6, MemOperand(a0, OFFSET_OF(T, swl_2))); - __ lw(a6, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ swl(a6, MemOperand(a0, OFFSET_OF(T, swl_2) + 2)); - - __ lw(a7, MemOperand(a0, OFFSET_OF(T, mem_init))); - __ sw(a7, MemOperand(a0, OFFSET_OF(T, swl_3))); - __ lw(a7, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ swl(a7, MemOperand(a0, OFFSET_OF(T, swl_3) + 3)); + __ lw(a4, MemOperand(a0, offsetof(T, mem_init))); + __ sw(a4, MemOperand(a0, offsetof(T, swl_0))); + __ lw(a4, MemOperand(a0, offsetof(T, reg_init))); + __ swl(a4, MemOperand(a0, offsetof(T, swl_0))); + + __ lw(a5, MemOperand(a0, offsetof(T, mem_init))); + __ sw(a5, MemOperand(a0, offsetof(T, swl_1))); + __ lw(a5, MemOperand(a0, offsetof(T, reg_init))); + __ swl(a5, MemOperand(a0, offsetof(T, swl_1) + 1)); + + __ lw(a6, MemOperand(a0, offsetof(T, mem_init))); + __ sw(a6, MemOperand(a0, offsetof(T, swl_2))); + __ lw(a6, MemOperand(a0, offsetof(T, reg_init))); + __ swl(a6, MemOperand(a0, offsetof(T, swl_2) + 2)); + + __ lw(a7, MemOperand(a0, offsetof(T, mem_init))); + __ sw(a7, MemOperand(a0, offsetof(T, swl_3))); + __ lw(a7, MemOperand(a0, offsetof(T, reg_init))); + __ swl(a7, MemOperand(a0, offsetof(T, swl_3) + 3)); // Test all combinations of SWR and vAddr. - __ lw(a4, MemOperand(a0, OFFSET_OF(T, mem_init))); - __ sw(a4, MemOperand(a0, OFFSET_OF(T, swr_0))); - __ lw(a4, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ swr(a4, MemOperand(a0, OFFSET_OF(T, swr_0))); - - __ lw(a5, MemOperand(a0, OFFSET_OF(T, mem_init))); - __ sw(a5, MemOperand(a0, OFFSET_OF(T, swr_1))); - __ lw(a5, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ swr(a5, MemOperand(a0, OFFSET_OF(T, swr_1) + 1)); - - __ lw(a6, MemOperand(a0, OFFSET_OF(T, mem_init))); - __ sw(a6, MemOperand(a0, OFFSET_OF(T, swr_2))); - __ lw(a6, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ swr(a6, MemOperand(a0, OFFSET_OF(T, swr_2) + 2)); - - __ lw(a7, MemOperand(a0, OFFSET_OF(T, mem_init))); - __ sw(a7, MemOperand(a0, OFFSET_OF(T, swr_3))); - __ lw(a7, MemOperand(a0, OFFSET_OF(T, reg_init))); - __ swr(a7, MemOperand(a0, OFFSET_OF(T, swr_3) + 3)); + __ lw(a4, MemOperand(a0, offsetof(T, mem_init))); + __ sw(a4, MemOperand(a0, offsetof(T, swr_0))); + __ lw(a4, MemOperand(a0, offsetof(T, reg_init))); + __ swr(a4, MemOperand(a0, offsetof(T, swr_0))); + + __ lw(a5, MemOperand(a0, offsetof(T, mem_init))); + __ sw(a5, MemOperand(a0, offsetof(T, swr_1))); + __ lw(a5, MemOperand(a0, offsetof(T, reg_init))); + __ swr(a5, MemOperand(a0, offsetof(T, swr_1) + 1)); + + __ lw(a6, MemOperand(a0, offsetof(T, mem_init))); + __ sw(a6, MemOperand(a0, offsetof(T, swr_2))); + __ lw(a6, MemOperand(a0, offsetof(T, reg_init))); + __ swr(a6, MemOperand(a0, offsetof(T, swr_2) + 2)); + + __ lw(a7, MemOperand(a0, offsetof(T, mem_init))); + __ sw(a7, MemOperand(a0, offsetof(T, swr_3))); + __ lw(a7, MemOperand(a0, offsetof(T, reg_init))); + __ swr(a7, MemOperand(a0, offsetof(T, swr_3) + 3)); __ jr(ra); __ nop(); @@ -1067,8 +1068,8 @@ TEST(MIPS12) { __ mov(t2, fp); // Save frame pointer. __ mov(fp, a0); // Access struct T by fp. - __ lw(a4, MemOperand(a0, OFFSET_OF(T, y))); - __ lw(a7, MemOperand(a0, OFFSET_OF(T, y4))); + __ lw(a4, MemOperand(a0, offsetof(T, y))); + __ lw(a7, MemOperand(a0, offsetof(T, y4))); __ addu(a5, a4, a7); __ subu(t0, a4, a7); @@ -1086,30 +1087,30 @@ TEST(MIPS12) { __ push(a7); __ pop(t0); __ nop(); - __ sw(a4, MemOperand(fp, OFFSET_OF(T, y))); - __ lw(a4, MemOperand(fp, OFFSET_OF(T, y))); + __ sw(a4, MemOperand(fp, offsetof(T, y))); + __ lw(a4, MemOperand(fp, offsetof(T, y))); __ nop(); - __ sw(a4, MemOperand(fp, OFFSET_OF(T, y))); - __ lw(a5, MemOperand(fp, OFFSET_OF(T, y))); + __ sw(a4, MemOperand(fp, offsetof(T, y))); + __ lw(a5, MemOperand(fp, offsetof(T, y))); __ nop(); __ push(a5); - __ lw(a5, MemOperand(fp, OFFSET_OF(T, y))); + __ lw(a5, MemOperand(fp, offsetof(T, y))); __ pop(a5); __ nop(); __ push(a5); - __ lw(a6, MemOperand(fp, OFFSET_OF(T, y))); + __ lw(a6, MemOperand(fp, offsetof(T, y))); __ pop(a5); __ nop(); __ push(a5); - __ lw(a6, MemOperand(fp, OFFSET_OF(T, y))); + __ lw(a6, MemOperand(fp, offsetof(T, y))); __ pop(a6); __ nop(); __ push(a6); - __ lw(a6, MemOperand(fp, OFFSET_OF(T, y))); + __ lw(a6, MemOperand(fp, offsetof(T, y))); __ pop(a5); __ nop(); __ push(a5); - __ lw(a6, MemOperand(fp, OFFSET_OF(T, y))); + __ lw(a6, MemOperand(fp, offsetof(T, y))); __ pop(a7); __ nop(); @@ -1154,19 +1155,19 @@ TEST(MIPS13) { MacroAssembler assm(isolate, NULL, 0); - __ sw(a4, MemOperand(a0, OFFSET_OF(T, cvt_small_in))); + __ sw(a4, MemOperand(a0, offsetof(T, cvt_small_in))); __ Cvt_d_uw(f10, a4, f22); - __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out))); + __ sdc1(f10, MemOperand(a0, offsetof(T, cvt_small_out))); __ Trunc_uw_d(f10, f10, f22); - __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out))); + __ swc1(f10, MemOperand(a0, offsetof(T, trunc_small_out))); - __ sw(a4, MemOperand(a0, OFFSET_OF(T, cvt_big_in))); + __ sw(a4, MemOperand(a0, offsetof(T, cvt_big_in))); __ Cvt_d_uw(f8, a4, f22); - __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out))); + __ sdc1(f8, MemOperand(a0, offsetof(T, cvt_big_out))); __ Trunc_uw_d(f8, f8, f22); - __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out))); + __ swc1(f8, MemOperand(a0, offsetof(T, trunc_big_out))); __ jr(ra); __ nop(); @@ -1236,46 +1237,46 @@ TEST(MIPS14) { // Disable FPU exceptions. __ ctc1(zero_reg, FCSR); #define RUN_ROUND_TEST(x) \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, round_up_in))); \ __ x##_w_d(f0, f0); \ - __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \ + __ swc1(f0, MemOperand(a0, offsetof(T, x##_up_out))); \ \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, round_down_in))); \ __ x##_w_d(f0, f0); \ - __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \ + __ swc1(f0, MemOperand(a0, offsetof(T, x##_down_out))); \ \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, neg_round_up_in))); \ __ x##_w_d(f0, f0); \ - __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \ + __ swc1(f0, MemOperand(a0, offsetof(T, neg_##x##_up_out))); \ \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, neg_round_down_in))); \ __ x##_w_d(f0, f0); \ - __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \ + __ swc1(f0, MemOperand(a0, offsetof(T, neg_##x##_down_out))); \ \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, err1_in))); \ __ ctc1(zero_reg, FCSR); \ __ x##_w_d(f0, f0); \ __ cfc1(a2, FCSR); \ - __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \ + __ sw(a2, MemOperand(a0, offsetof(T, x##_err1_out))); \ \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, err2_in))); \ __ ctc1(zero_reg, FCSR); \ __ x##_w_d(f0, f0); \ __ cfc1(a2, FCSR); \ - __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \ + __ sw(a2, MemOperand(a0, offsetof(T, x##_err2_out))); \ \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, err3_in))); \ __ ctc1(zero_reg, FCSR); \ __ x##_w_d(f0, f0); \ __ cfc1(a2, FCSR); \ - __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \ + __ sw(a2, MemOperand(a0, offsetof(T, x##_err3_out))); \ \ - __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \ + __ ldc1(f0, MemOperand(a0, offsetof(T, err4_in))); \ __ ctc1(zero_reg, FCSR); \ __ x##_w_d(f0, f0); \ __ cfc1(a2, FCSR); \ - __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \ - __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result))); + __ sw(a2, MemOperand(a0, offsetof(T, x##_err4_out))); \ + __ swc1(f0, MemOperand(a0, offsetof(T, x##_invalid_result))); RUN_ROUND_TEST(round) RUN_ROUND_TEST(floor) @@ -1363,48 +1364,48 @@ TEST(MIPS16) { Label L, C; // Basic 32-bit word load/store, with un-signed data. - __ lw(a4, MemOperand(a0, OFFSET_OF(T, ui))); - __ sw(a4, MemOperand(a0, OFFSET_OF(T, r1))); + __ lw(a4, MemOperand(a0, offsetof(T, ui))); + __ sw(a4, MemOperand(a0, offsetof(T, r1))); // Check that the data got zero-extended into 64-bit a4. - __ sd(a4, MemOperand(a0, OFFSET_OF(T, r2))); + __ sd(a4, MemOperand(a0, offsetof(T, r2))); // Basic 32-bit word load/store, with SIGNED data. - __ lw(a5, MemOperand(a0, OFFSET_OF(T, si))); - __ sw(a5, MemOperand(a0, OFFSET_OF(T, r3))); + __ lw(a5, MemOperand(a0, offsetof(T, si))); + __ sw(a5, MemOperand(a0, offsetof(T, r3))); // Check that the data got sign-extended into 64-bit a4. - __ sd(a5, MemOperand(a0, OFFSET_OF(T, r4))); + __ sd(a5, MemOperand(a0, offsetof(T, r4))); // 32-bit UNSIGNED word load/store, with SIGNED data. - __ lwu(a6, MemOperand(a0, OFFSET_OF(T, si))); - __ sw(a6, MemOperand(a0, OFFSET_OF(T, r5))); + __ lwu(a6, MemOperand(a0, offsetof(T, si))); + __ sw(a6, MemOperand(a0, offsetof(T, r5))); // Check that the data got zero-extended into 64-bit a4. - __ sd(a6, MemOperand(a0, OFFSET_OF(T, r6))); + __ sd(a6, MemOperand(a0, offsetof(T, r6))); // lh with positive data. - __ lh(a5, MemOperand(a0, OFFSET_OF(T, ui))); - __ sw(a5, MemOperand(a0, OFFSET_OF(T, r2))); + __ lh(a5, MemOperand(a0, offsetof(T, ui))); + __ sw(a5, MemOperand(a0, offsetof(T, r2))); // lh with negative data. - __ lh(a6, MemOperand(a0, OFFSET_OF(T, si))); - __ sw(a6, MemOperand(a0, OFFSET_OF(T, r3))); + __ lh(a6, MemOperand(a0, offsetof(T, si))); + __ sw(a6, MemOperand(a0, offsetof(T, r3))); // lhu with negative data. - __ lhu(a7, MemOperand(a0, OFFSET_OF(T, si))); - __ sw(a7, MemOperand(a0, OFFSET_OF(T, r4))); + __ lhu(a7, MemOperand(a0, offsetof(T, si))); + __ sw(a7, MemOperand(a0, offsetof(T, r4))); // lb with negative data. - __ lb(t0, MemOperand(a0, OFFSET_OF(T, si))); - __ sw(t0, MemOperand(a0, OFFSET_OF(T, r5))); + __ lb(t0, MemOperand(a0, offsetof(T, si))); + __ sw(t0, MemOperand(a0, offsetof(T, r5))); // // sh writes only 1/2 of word. __ lui(t1, 0x3333); __ ori(t1, t1, 0x3333); - __ sw(t1, MemOperand(a0, OFFSET_OF(T, r6))); - __ lhu(t1, MemOperand(a0, OFFSET_OF(T, si))); - __ sh(t1, MemOperand(a0, OFFSET_OF(T, r6))); + __ sw(t1, MemOperand(a0, offsetof(T, r6))); + __ lhu(t1, MemOperand(a0, offsetof(T, si))); + __ sh(t1, MemOperand(a0, offsetof(T, r6))); __ jr(ra); __ nop(); @@ -1439,7 +1440,8 @@ TEST(MIPS16) { } -TEST(MIPS17) { +// ----------------------mips32r6 specific tests---------------------- +TEST(seleqz_selnez) { if (kArchVariant == kMips64r6) { CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); @@ -1455,26 +1457,36 @@ TEST(MIPS17) { double f; double g; double h; + float i; + float j; + float k; + float l; } Test; Test test; // Integer part of test. __ addiu(t1, zero_reg, 1); // t1 = 1 __ seleqz(t3, t1, zero_reg); // t3 = 1 - __ sw(t3, MemOperand(a0, OFFSET_OF(Test, a))); // a = 1 + __ sw(t3, MemOperand(a0, offsetof(Test, a))); // a = 1 __ seleqz(t2, t1, t1); // t2 = 0 - __ sw(t2, MemOperand(a0, OFFSET_OF(Test, b))); // b = 0 + __ sw(t2, MemOperand(a0, offsetof(Test, b))); // b = 0 __ selnez(t3, t1, zero_reg); // t3 = 1; - __ sw(t3, MemOperand(a0, OFFSET_OF(Test, c))); // c = 0 + __ sw(t3, MemOperand(a0, offsetof(Test, c))); // c = 0 __ selnez(t3, t1, t1); // t3 = 1 - __ sw(t3, MemOperand(a0, OFFSET_OF(Test, d))); // d = 1 + __ sw(t3, MemOperand(a0, offsetof(Test, d))); // d = 1 // Floating point part of test. - __ ldc1(f0, MemOperand(a0, OFFSET_OF(Test, e)) ); // src - __ ldc1(f2, MemOperand(a0, OFFSET_OF(Test, f)) ); // test - __ seleqz(D, f4, f0, f2); - __ selnez(D, f6, f0, f2); - __ sdc1(f4, MemOperand(a0, OFFSET_OF(Test, g)) ); // src - __ sdc1(f6, MemOperand(a0, OFFSET_OF(Test, h)) ); // src + __ ldc1(f0, MemOperand(a0, offsetof(Test, e)) ); // src + __ ldc1(f2, MemOperand(a0, offsetof(Test, f)) ); // test + __ lwc1(f8, MemOperand(a0, offsetof(Test, i)) ); // src + __ lwc1(f10, MemOperand(a0, offsetof(Test, j)) ); // test + __ seleqz_d(f4, f0, f2); + __ selnez_d(f6, f0, f2); + __ seleqz_s(f12, f8, f10); + __ selnez_s(f14, f8, f10); + __ sdc1(f4, MemOperand(a0, offsetof(Test, g)) ); // src + __ sdc1(f6, MemOperand(a0, offsetof(Test, h)) ); // src + __ swc1(f12, MemOperand(a0, offsetof(Test, k)) ); // src + __ swc1(f14, MemOperand(a0, offsetof(Test, l)) ); // src __ jr(ra); __ nop(); CodeDesc desc; @@ -1493,31 +1505,45 @@ TEST(MIPS17) { const int test_size = 3; const int input_size = 5; - double inputs[input_size] = {0.0, 65.2, -70.32, + double inputs_D[input_size] = {0.0, 65.2, -70.32, 18446744073709551621.0, -18446744073709551621.0}; - double outputs[input_size] = {0.0, 65.2, -70.32, + double outputs_D[input_size] = {0.0, 65.2, -70.32, 18446744073709551621.0, -18446744073709551621.0}; - double tests[test_size*2] = {2.8, 2.9, -2.8, -2.9, + double tests_D[test_size*2] = {2.8, 2.9, -2.8, -2.9, 18446744073709551616.0, 18446744073709555712.0}; - for (int j=0;j < test_size;j+=2) { - for (int i=0;i < input_size;i++) { - test.e = inputs[i]; - test.f = tests[j]; + float inputs_S[input_size] = {0.0, 65.2, -70.32, + 18446744073709551621.0, -18446744073709551621.0}; + float outputs_S[input_size] = {0.0, 65.2, -70.32, + 18446744073709551621.0, -18446744073709551621.0}; + float tests_S[test_size*2] = {2.9, 2.8, -2.9, -2.8, + 18446744073709551616.0, 18446746272732807168.0}; + for (int j=0; j < test_size; j+=2) { + for (int i=0; i < input_size; i++) { + test.e = inputs_D[i]; + test.f = tests_D[j]; + test.i = inputs_S[i]; + test.j = tests_S[j]; (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - CHECK_EQ(test.g, outputs[i]); + CHECK_EQ(test.g, outputs_D[i]); CHECK_EQ(test.h, 0); + CHECK_EQ(test.k, outputs_S[i]); + CHECK_EQ(test.l, 0); - test.f = tests[j+1]; + test.f = tests_D[j+1]; + test.j = tests_S[j+1]; (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); CHECK_EQ(test.g, 0); - CHECK_EQ(test.h, outputs[i]); + CHECK_EQ(test.h, outputs_D[i]); + CHECK_EQ(test.k, 0); + CHECK_EQ(test.l, outputs_S[i]); } } } } -TEST(MIPS18) { + +TEST(min_max) { if (kArchVariant == kMips64r6) { CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); @@ -1529,16 +1555,38 @@ TEST(MIPS18) { double b; double c; double d; + float e; + float f; + float g; + float h; } TestFloat; TestFloat test; - - __ ldc1(f4, MemOperand(a0, OFFSET_OF(TestFloat, a))); - __ ldc1(f8, MemOperand(a0, OFFSET_OF(TestFloat, b))); + const double dblNaN = std::numeric_limits<double>::quiet_NaN(); + const float fltNaN = std::numeric_limits<float>::quiet_NaN(); + const int tableLength = 5; + double inputsa[tableLength] = {2.0, 3.0, dblNaN, 3.0, dblNaN}; + double inputsb[tableLength] = {3.0, 2.0, 3.0, dblNaN, dblNaN}; + double outputsdmin[tableLength] = {2.0, 2.0, 3.0, 3.0, dblNaN}; + double outputsdmax[tableLength] = {3.0, 3.0, 3.0, 3.0, dblNaN}; + + float inputse[tableLength] = {2.0, 3.0, fltNaN, 3.0, fltNaN}; + float inputsf[tableLength] = {3.0, 2.0, 3.0, fltNaN, fltNaN}; + float outputsfmin[tableLength] = {2.0, 2.0, 3.0, 3.0, fltNaN}; + float outputsfmax[tableLength] = {3.0, 3.0, 3.0, 3.0, fltNaN}; + + __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); + __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b))); + __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, e))); + __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, f))); __ min_d(f10, f4, f8); __ max_d(f12, f4, f8); - __ sdc1(f10, MemOperand(a0, OFFSET_OF(TestFloat, c))); - __ sdc1(f12, MemOperand(a0, OFFSET_OF(TestFloat, d))); + __ min_s(f14, f2, f6); + __ max_s(f16, f2, f6); + __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c))); + __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, d))); + __ swc1(f14, MemOperand(a0, offsetof(TestFloat, g))); + __ swc1(f16, MemOperand(a0, offsetof(TestFloat, h))); __ jr(ra); __ nop(); @@ -1547,40 +1595,31 @@ TEST(MIPS18) { Handle<Code> code = isolate->factory()->NewCode( desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); F3 f = FUNCTION_CAST<F3>(code->entry()); - test.a = 2.0; // a goes to fs - test.b = 3.0; // b goes to ft - (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - CHECK_EQ(test.c, 2.0); - CHECK_EQ(test.d, 3.0); + for (int i = 0; i < tableLength; i++) { + test.a = inputsa[i]; + test.b = inputsb[i]; + test.e = inputse[i]; + test.f = inputsf[i]; - test.a = 3.0; // a goes to fs - test.b = 2.0; // b goes to ft - (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - CHECK_EQ(test.c, 2.0); - CHECK_EQ(test.d, 3.0); - - test.a = std::numeric_limits<double>::quiet_NaN(); - test.b = 3.0; // b goes to ft - (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - CHECK_EQ(test.c, 3.0); - CHECK_EQ(test.d, 3.0); - - test.b = std::numeric_limits<double>::quiet_NaN(); - test.a = 3.0; // b goes to ft - (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - CHECK_EQ(test.c, 3.0); - CHECK_EQ(test.d, 3.0); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - test.a = std::numeric_limits<double>::quiet_NaN(); - test.b = std::numeric_limits<double>::quiet_NaN(); - (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - DCHECK(std::isnan(test.c)); - DCHECK(std::isnan(test.d)); + if (i < tableLength - 1) { + CHECK_EQ(test.c, outputsdmin[i]); + CHECK_EQ(test.d, outputsdmax[i]); + CHECK_EQ(test.g, outputsfmin[i]); + CHECK_EQ(test.h, outputsfmax[i]); + } else { + DCHECK(std::isnan(test.c)); + DCHECK(std::isnan(test.d)); + DCHECK(std::isnan(test.g)); + DCHECK(std::isnan(test.h)); + } + } } } -TEST(MIPS19) { +TEST(rint_d) { if (kArchVariant == kMips64r6) { const int tableLength = 30; CcTest::InitializeVM(); @@ -1658,11 +1697,190 @@ TEST(MIPS19) { int fcsr_inputs[4] = {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf}; double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM}; - __ ldc1(f4, MemOperand(a0, OFFSET_OF(TestFloat, a)) ); - __ lw(t0, MemOperand(a0, OFFSET_OF(TestFloat, fcsr)) ); + __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)) ); + __ lw(t0, MemOperand(a0, offsetof(TestFloat, fcsr)) ); __ ctc1(t0, FCSR); __ rint_d(f8, f4); - __ sdc1(f8, MemOperand(a0, OFFSET_OF(TestFloat, b)) ); + __ sdc1(f8, MemOperand(a0, offsetof(TestFloat, b)) ); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + + for (int j = 0; j < 4; j++) { + test.fcsr = fcsr_inputs[j]; + for (int i = 0; i < tableLength; i++) { + test.a = inputs[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.b, outputs[j][i]); + } + } + } +} + + +TEST(sel) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test { + double dd; + double ds; + double dt; + float fd; + float fs; + float ft; + } Test; + + Test test; + __ ldc1(f0, MemOperand(a0, offsetof(Test, dd)) ); // test + __ ldc1(f2, MemOperand(a0, offsetof(Test, ds)) ); // src1 + __ ldc1(f4, MemOperand(a0, offsetof(Test, dt)) ); // src2 + __ lwc1(f6, MemOperand(a0, offsetof(Test, fd)) ); // test + __ lwc1(f8, MemOperand(a0, offsetof(Test, fs)) ); // src1 + __ lwc1(f10, MemOperand(a0, offsetof(Test, ft)) ); // src2 + __ sel_d(f0, f2, f4); + __ sel_s(f6, f8, f10); + __ sdc1(f0, MemOperand(a0, offsetof(Test, dd)) ); + __ swc1(f6, MemOperand(a0, offsetof(Test, fd)) ); + __ jr(ra); + __ nop(); + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + + const int test_size = 3; + const int input_size = 5; + + double inputs_dt[input_size] = {0.0, 65.2, -70.32, + 18446744073709551621.0, -18446744073709551621.0}; + double inputs_ds[input_size] = {0.1, 69.88, -91.325, + 18446744073709551625.0, -18446744073709551625.0}; + float inputs_ft[input_size] = {0.0, 65.2, -70.32, + 18446744073709551621.0, -18446744073709551621.0}; + float inputs_fs[input_size] = {0.1, 69.88, -91.325, + 18446744073709551625.0, -18446744073709551625.0}; + double tests_D[test_size*2] = {2.8, 2.9, -2.8, -2.9, + 18446744073709551616.0, 18446744073709555712.0}; + float tests_S[test_size*2] = {2.9, 2.8, -2.9, -2.8, + 18446744073709551616.0, 18446746272732807168.0}; + for (int j=0; j < test_size; j+=2) { + for (int i=0; i < input_size; i++) { + test.dt = inputs_dt[i]; + test.dd = tests_D[j]; + test.ds = inputs_ds[i]; + test.ft = inputs_ft[i]; + test.fd = tests_S[j]; + test.fs = inputs_fs[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dd, inputs_ds[i]); + CHECK_EQ(test.fd, inputs_fs[i]); + + test.dd = tests_D[j+1]; + test.fd = tests_S[j+1]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dd, inputs_dt[i]); + CHECK_EQ(test.fd, inputs_ft[i]); + } + } + } +} + + +TEST(rint_s) { + if (kArchVariant == kMips64r6) { + const int tableLength = 30; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + float a; + float b; + int fcsr; + }TestFloat; + + TestFloat test; + float inputs[tableLength] = {18446744073709551617.0, + 4503599627370496.0, -4503599627370496.0, + 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, + 1.7976931348623157E+38, 6.27463370218383111104242366943E-37, + 309485009821345068724781056.89, + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 37778931862957161709568.0, 37778931862957161709569.0, + 37778931862957161709580.0, 37778931862957161709581.0, + 37778931862957161709582.0, 37778931862957161709583.0, + 37778931862957161709584.0, 37778931862957161709585.0, + 37778931862957161709586.0, 37778931862957161709587.0}; + float outputs_RN[tableLength] = {18446744073709551617.0, + 4503599627370496.0, -4503599627370496.0, + 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, + 1.7976931348623157E38, 0, + 309485009821345068724781057.0, + 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, + -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, + 37778931862957161709568.0, 37778931862957161709569.0, + 37778931862957161709580.0, 37778931862957161709581.0, + 37778931862957161709582.0, 37778931862957161709583.0, + 37778931862957161709584.0, 37778931862957161709585.0, + 37778931862957161709586.0, 37778931862957161709587.0}; + float outputs_RZ[tableLength] = {18446744073709551617.0, + 4503599627370496.0, -4503599627370496.0, + 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, + 1.7976931348623157E38, 0, + 309485009821345068724781057.0, + 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, + -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, + 37778931862957161709568.0, 37778931862957161709569.0, + 37778931862957161709580.0, 37778931862957161709581.0, + 37778931862957161709582.0, 37778931862957161709583.0, + 37778931862957161709584.0, 37778931862957161709585.0, + 37778931862957161709586.0, 37778931862957161709587.0}; + float outputs_RP[tableLength] = {18446744073709551617.0, + 4503599627370496.0, -4503599627370496.0, + 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, + 1.7976931348623157E38, 1, + 309485009821345068724781057.0, + 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, + -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, + 37778931862957161709568.0, 37778931862957161709569.0, + 37778931862957161709580.0, 37778931862957161709581.0, + 37778931862957161709582.0, 37778931862957161709583.0, + 37778931862957161709584.0, 37778931862957161709585.0, + 37778931862957161709586.0, 37778931862957161709587.0}; + float outputs_RM[tableLength] = {18446744073709551617.0, + 4503599627370496.0, -4503599627370496.0, + 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, + 1.7976931348623157E38, 0, + 309485009821345068724781057.0, + 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, + -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, + 37778931862957161709568.0, 37778931862957161709569.0, + 37778931862957161709580.0, 37778931862957161709581.0, + 37778931862957161709582.0, 37778931862957161709583.0, + 37778931862957161709584.0, 37778931862957161709585.0, + 37778931862957161709586.0, 37778931862957161709587.0}; + int fcsr_inputs[4] = + {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf}; + float* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM}; + __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, a)) ); + __ lw(t0, MemOperand(a0, offsetof(TestFloat, fcsr)) ); + __ cfc1(t1, FCSR); + __ ctc1(t0, FCSR); + __ rint_s(f8, f4); + __ swc1(f8, MemOperand(a0, offsetof(TestFloat, b)) ); + __ ctc1(t1, FCSR); __ jr(ra); __ nop(); @@ -1672,11 +1890,10 @@ TEST(MIPS19) { desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); F3 f = FUNCTION_CAST<F3>(code->entry()); - for (int j = 0;j < 4;j++) { + for (int j = 0; j < 4; j++) { test.fcsr = fcsr_inputs[j]; - for (int i = 0;i < tableLength;i++) { + for (int i = 0; i < tableLength; i++) { test.a = inputs[i]; - std::cout << j << " " << i << "\n"; (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); CHECK_EQ(test.b, outputs[j][i]); } @@ -1685,7 +1902,358 @@ TEST(MIPS19) { } -TEST(MIPS20) { +TEST(mina_maxa) { + if (kArchVariant == kMips64r6) { + const int tableLength = 12; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double a; + double b; + double resd; + double resd1; + float c; + float d; + float resf; + float resf1; + }TestFloat; + + TestFloat test; + double inputsa[tableLength] = { + 5.3, 4.8, 6.1, + 9.8, 9.8, 9.8, + -10.0, -8.9, -9.8, + -10.0, -8.9, -9.8 + }; + double inputsb[tableLength] = { + 4.8, 5.3, 6.1, + -10.0, -8.9, -9.8, + 9.8, 9.8, 9.8, + -9.8, -11.2, -9.8 + }; + double resd[tableLength] = { + 4.8, 4.8, 6.1, + 9.8, -8.9, 9.8, + 9.8, -8.9, 9.8, + -9.8, -8.9, -9.8 + }; + double resd1[tableLength] = { + 5.3, 5.3, 6.1, + -10.0, 9.8, 9.8, + -10.0, 9.8, 9.8, + -10.0, -11.2, -9.8 + }; + float inputsc[tableLength] = { + 5.3, 4.8, 6.1, + 9.8, 9.8, 9.8, + -10.0, -8.9, -9.8, + -10.0, -8.9, -9.8 + }; + float inputsd[tableLength] = { + 4.8, 5.3, 6.1, + -10.0, -8.9, -9.8, + 9.8, 9.8, 9.8, + -9.8, -11.2, -9.8 + }; + float resf[tableLength] = { + 4.8, 4.8, 6.1, + 9.8, -8.9, 9.8, + 9.8, -8.9, 9.8, + -9.8, -8.9, -9.8 + }; + float resf1[tableLength] = { + 5.3, 5.3, 6.1, + -10.0, 9.8, 9.8, + -10.0, 9.8, 9.8, + -10.0, -11.2, -9.8 + }; + + __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); + __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, b)) ); + __ lwc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); + __ lwc1(f10, MemOperand(a0, offsetof(TestFloat, d)) ); + __ mina_d(f6, f2, f4); + __ mina_s(f12, f8, f10); + __ maxa_d(f14, f2, f4); + __ maxa_s(f16, f8, f10); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, resf)) ); + __ sdc1(f6, MemOperand(a0, offsetof(TestFloat, resd)) ); + __ swc1(f16, MemOperand(a0, offsetof(TestFloat, resf1)) ); + __ sdc1(f14, MemOperand(a0, offsetof(TestFloat, resd1)) ); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputsa[i]; + test.b = inputsb[i]; + test.c = inputsc[i]; + test.d = inputsd[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + + CHECK_EQ(test.resd, resd[i]); + CHECK_EQ(test.resf, resf[i]); + CHECK_EQ(test.resd1, resd1[i]); + CHECK_EQ(test.resf1, resf1[i]); + } + } +} + + + +// ----------------------mips32r2 specific tests---------------------- +TEST(trunc_l) { + if (kArchVariant == kMips64r2) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); + typedef struct test_float { + double a; + float b; + int64_t c; // a trunc result + int64_t d; // b trunc result + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, + -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, + 2147483648.0, dFPU64InvalidResult, + dFPU64InvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ trunc_l_d(f8, f4); + __ trunc_l_s(f10, f6); + __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); + } + } +} + + +TEST(movz_movn) { + if (kArchVariant == kMips64r2) { + const int tableLength = 4; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + int64_t rt; + double a; + double b; + double bold; + double b1; + double bold1; + float c; + float d; + float dold; + float d1; + float dold1; + }TestFloat; + + TestFloat test; + double inputs_D[tableLength] = { + 5.3, -5.3, 5.3, -2.9 + }; + double inputs_S[tableLength] = { + 4.8, 4.8, -4.8, -0.29 + }; + + float outputs_S[tableLength] = { + 4.8, 4.8, -4.8, -0.29 + }; + double outputs_D[tableLength] = { + 5.3, -5.3, 5.3, -2.9 + }; + + __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) ); + __ lw(t0, MemOperand(a0, offsetof(TestFloat, rt)) ); + __ li(t1, 0x0); + __ mtc1(t1, f12); + __ mtc1(t1, f10); + __ mtc1(t1, f16); + __ mtc1(t1, f14); + __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, bold)) ); + __ swc1(f10, MemOperand(a0, offsetof(TestFloat, dold)) ); + __ sdc1(f16, MemOperand(a0, offsetof(TestFloat, bold1)) ); + __ swc1(f14, MemOperand(a0, offsetof(TestFloat, dold1)) ); + __ movz_s(f10, f6, t0); + __ movz_d(f12, f2, t0); + __ movn_s(f14, f6, t0); + __ movn_d(f16, f2, t0); + __ swc1(f10, MemOperand(a0, offsetof(TestFloat, d)) ); + __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, b)) ); + __ swc1(f14, MemOperand(a0, offsetof(TestFloat, d1)) ); + __ sdc1(f16, MemOperand(a0, offsetof(TestFloat, b1)) ); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.c = inputs_S[i]; + + test.rt = 1; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.b, test.bold); + CHECK_EQ(test.d, test.dold); + CHECK_EQ(test.b1, outputs_D[i]); + CHECK_EQ(test.d1, outputs_S[i]); + + test.rt = 0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.b, outputs_D[i]); + CHECK_EQ(test.d, outputs_S[i]); + CHECK_EQ(test.b1, test.bold1); + CHECK_EQ(test.d1, test.dold1); + } + } +} + + +TEST(movt_movd) { + if (kArchVariant == kMips64r2) { + const int tableLength = 4; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + typedef struct test_float { + double srcd; + double dstd; + double dstdold; + double dstd1; + double dstdold1; + float srcf; + float dstf; + float dstfold; + float dstf1; + float dstfold1; + int32_t cc; + int32_t fcsr; + }TestFloat; + + TestFloat test; + double inputs_D[tableLength] = { + 5.3, -5.3, 20.8, -2.9 + }; + double inputs_S[tableLength] = { + 4.88, 4.8, -4.8, -0.29 + }; + + float outputs_S[tableLength] = { + 4.88, 4.8, -4.8, -0.29 + }; + double outputs_D[tableLength] = { + 5.3, -5.3, 20.8, -2.9 + }; + int condition_flags[8] = {0, 1, 2, 3, 4, 5, 6, 7}; + + for (int i = 0; i < tableLength; i++) { + test.srcd = inputs_D[i]; + test.srcf = inputs_S[i]; + + for (int j = 0; j< 8; j++) { + test.cc = condition_flags[j]; + if (test.cc == 0) { + test.fcsr = 1 << 23; + } else { + test.fcsr = 1 << (24+condition_flags[j]); + } + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, srcd)) ); + __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, srcf)) ); + __ lw(t1, MemOperand(a0, offsetof(TestFloat, fcsr)) ); + __ cfc1(t0, FCSR); + __ ctc1(t1, FCSR); + __ li(t2, 0x0); + __ mtc1(t2, f12); + __ mtc1(t2, f10); + __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstdold)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstfold)) ); + __ movt_s(f12, f4, test.cc); + __ movt_d(f10, f2, test.cc); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstf)) ); + __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstd)) ); + __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstdold1)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstfold1)) ); + __ movf_s(f12, f4, test.cc); + __ movf_d(f10, f2, test.cc); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstf1)) ); + __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstd1)) ); + __ ctc1(t0, FCSR); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dstf, outputs_S[i]); + CHECK_EQ(test.dstd, outputs_D[i]); + CHECK_EQ(test.dstf1, test.dstfold1); + CHECK_EQ(test.dstd1, test.dstdold1); + test.fcsr = 0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dstf, test.dstfold); + CHECK_EQ(test.dstd, test.dstdold); + CHECK_EQ(test.dstf1, outputs_S[i]); + CHECK_EQ(test.dstd1, outputs_D[i]); + } + } + } +} + + + +// ----------------------tests for all archs-------------------------- +TEST(cvt_w_d) { CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); HandleScope scope(isolate); @@ -1736,12 +2304,12 @@ TEST(MIPS20) { int fcsr_inputs[4] = {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf}; double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM}; - __ ldc1(f4, MemOperand(a0, OFFSET_OF(Test, a)) ); - __ lw(t0, MemOperand(a0, OFFSET_OF(Test, fcsr)) ); + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lw(t0, MemOperand(a0, offsetof(Test, fcsr)) ); __ cfc1(t1, FCSR); __ ctc1(t0, FCSR); __ cvt_w_d(f8, f4); - __ swc1(f8, MemOperand(a0, OFFSET_OF(Test, b)) ); + __ swc1(f8, MemOperand(a0, offsetof(Test, b)) ); __ ctc1(t1, FCSR); __ jr(ra); __ nop(); @@ -1751,9 +2319,9 @@ TEST(MIPS20) { Handle<Code> code = isolate->factory()->NewCode( desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); F3 f = FUNCTION_CAST<F3>(code->entry()); - for (int j = 0;j < 4;j++) { + for (int j = 0; j < 4; j++) { test.fcsr = fcsr_inputs[j]; - for (int i = 0;i < tableLength;i++) { + for (int i = 0; i < tableLength; i++) { test.a = inputs[i]; (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); CHECK_EQ(test.b, outputs[j][i]); @@ -1762,111 +2330,736 @@ TEST(MIPS20) { } -TEST(MIPS21) { - if (kArchVariant == kMips64r6) { - const int tableLength = 30; +TEST(trunc_w) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double a; + float b; + int32_t c; // a trunc result + int32_t d; // b trunc result + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, + -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, + kFPUInvalidResult, kFPUInvalidResult, + kFPUInvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ trunc_w_d(f8, f4); + __ trunc_w_s(f10, f6); + __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); + } +} + + +TEST(round_w) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double a; + float b; + int32_t c; // a trunc result + int32_t d; // b trunc result + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, + -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, + kFPUInvalidResult, kFPUInvalidResult, + kFPUInvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ round_w_d(f8, f4); + __ round_w_s(f10, f6); + __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); + } +} + + +TEST(round_l) { CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); HandleScope scope(isolate); MacroAssembler assm(isolate, NULL, 0); - + const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); typedef struct test_float { double a; - double b; - int fcsr; - }TestFloat; + float b; + int64_t c; + int64_t d; + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, + -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, + 2147483648.0, dFPU64InvalidResult, + dFPU64InvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ round_l_d(f8, f4); + __ round_l_s(f10, f6); + __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + std::cout<< i<< "\n"; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); + } +} - TestFloat test; - double inputs[tableLength] = {18446744073709551617.0, - 4503599627370496.0, -4503599627370496.0, - 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, - 1.7976931348623157E308, 6.27463370218383111104242366943E-307, - 309485009821345068724781056.89, + +TEST(sub) { + const int tableLength = 12; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + float a; + float b; + float resultS; + double c; + double d; + double resultD; + }TestFloat; + + TestFloat test; + double inputfs_D[tableLength] = { + 5.3, 4.8, 2.9, -5.3, -4.8, -2.9, + 5.3, 4.8, 2.9, -5.3, -4.8, -2.9 + }; + double inputft_D[tableLength] = { + 4.8, 5.3, 2.9, 4.8, 5.3, 2.9, + -4.8, -5.3, -2.9, -4.8, -5.3, -2.9 + }; + double outputs_D[tableLength] = { + 0.5, -0.5, 0.0, -10.1, -10.1, -5.8, + 10.1, 10.1, 5.8, -0.5, 0.5, 0.0 + }; + float inputfs_S[tableLength] = { + 5.3, 4.8, 2.9, -5.3, -4.8, -2.9, + 5.3, 4.8, 2.9, -5.3, -4.8, -2.9 + }; + float inputft_S[tableLength] = { + 4.8, 5.3, 2.9, 4.8, 5.3, 2.9, + -4.8, -5.3, -2.9, -4.8, -5.3, -2.9 + }; + float outputs_S[tableLength] = { + 0.5, -0.5, 0.0, -10.1, -10.1, -5.8, + 10.1, 10.1, 5.8, -0.5, 0.5, 0.0 + }; + __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); + __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)) ); + __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); + __ ldc1(f10, MemOperand(a0, offsetof(TestFloat, d)) ); + __ sub_s(f6, f2, f4); + __ sub_d(f12, f8, f10); + __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) ); + __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputfs_S[i]; + test.b = inputft_S[i]; + test.c = inputfs_D[i]; + test.d = inputft_D[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.resultS, outputs_S[i]); + CHECK_EQ(test.resultD, outputs_D[i]); + } +} + + +TEST(sqrt_rsqrt_recip) { + const int tableLength = 4; + const double deltaDouble = 2E-15; + const float deltaFloat = 2E-7; + const float sqrt2_s = sqrt(2); + const double sqrt2_d = sqrt(2); + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + float a; + float resultS; + float resultS1; + float resultS2; + double c; + double resultD; + double resultD1; + double resultD2; + }TestFloat; + TestFloat test; + + double inputs_D[tableLength] = { + 0.0L, 4.0L, 2.0L, 4e-28L + }; + + double outputs_D[tableLength] = { + 0.0L, 2.0L, sqrt2_d, 2e-14L + }; + float inputs_S[tableLength] = { + 0.0, 4.0, 2.0, 4e-28 + }; + + float outputs_S[tableLength] = { + 0.0, 2.0, sqrt2_s, 2e-14 + }; + + + __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); + __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); + __ sqrt_s(f6, f2); + __ sqrt_d(f12, f8); + __ rsqrt_d(f14, f8); + __ rsqrt_s(f16, f2); + __ recip_d(f18, f8); + __ recip_s(f20, f2); + __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) ); + __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); + __ swc1(f16, MemOperand(a0, offsetof(TestFloat, resultS1)) ); + __ sdc1(f14, MemOperand(a0, offsetof(TestFloat, resultD1)) ); + __ swc1(f20, MemOperand(a0, offsetof(TestFloat, resultS2)) ); + __ sdc1(f18, MemOperand(a0, offsetof(TestFloat, resultD2)) ); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + + for (int i = 0; i < tableLength; i++) { + float f1; + double d1; + test.a = inputs_S[i]; + test.c = inputs_D[i]; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + + CHECK_EQ(test.resultS, outputs_S[i]); + CHECK_EQ(test.resultD, outputs_D[i]); + + if (i != 0) { + f1 = test.resultS1 - 1.0F/outputs_S[i]; + f1 = (f1 < 0) ? f1 : -f1; + CHECK(f1 <= deltaFloat); + d1 = test.resultD1 - 1.0L/outputs_D[i]; + d1 = (d1 < 0) ? d1 : -d1; + CHECK(d1 <= deltaDouble); + f1 = test.resultS2 - 1.0F/inputs_S[i]; + f1 = (f1 < 0) ? f1 : -f1; + CHECK(f1 <= deltaFloat); + d1 = test.resultD2 - 1.0L/inputs_D[i]; + d1 = (d1 < 0) ? d1 : -d1; + CHECK(d1 <= deltaDouble); + } else { + CHECK_EQ(test.resultS1, 1.0F/outputs_S[i]); + CHECK_EQ(test.resultD1, 1.0L/outputs_D[i]); + CHECK_EQ(test.resultS2, 1.0F/inputs_S[i]); + CHECK_EQ(test.resultD2, 1.0L/inputs_D[i]); + } + } +} + + +TEST(neg) { + const int tableLength = 2; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + float a; + float resultS; + double c; + double resultD; + }TestFloat; + + TestFloat test; + double inputs_D[tableLength] = { + 4.0, -2.0 + }; + + double outputs_D[tableLength] = { + -4.0, 2.0 + }; + float inputs_S[tableLength] = { + 4.0, -2.0 + }; + + float outputs_S[tableLength] = { + -4.0, 2.0 + }; + __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); + __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); + __ neg_s(f6, f2); + __ neg_d(f12, f8); + __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) ); + __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_S[i]; + test.c = inputs_D[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.resultS, outputs_S[i]); + CHECK_EQ(test.resultD, outputs_D[i]); + } +} + + + +TEST(mul) { + const int tableLength = 4; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + float a; + float b; + float resultS; + double c; + double d; + double resultD; + }TestFloat; + + TestFloat test; + double inputfs_D[tableLength] = { + 5.3, -5.3, 5.3, -2.9 + }; + double inputft_D[tableLength] = { + 4.8, 4.8, -4.8, -0.29 + }; + + float inputfs_S[tableLength] = { + 5.3, -5.3, 5.3, -2.9 + }; + float inputft_S[tableLength] = { + 4.8, 4.8, -4.8, -0.29 + }; + + __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); + __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)) ); + __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, c)) ); + __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, d)) ); + __ mul_s(f10, f2, f4); + __ mul_d(f12, f6, f8); + __ swc1(f10, MemOperand(a0, offsetof(TestFloat, resultS)) ); + __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputfs_S[i]; + test.b = inputft_S[i]; + test.c = inputfs_D[i]; + test.d = inputft_D[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.resultS, inputfs_S[i]*inputft_S[i]); + CHECK_EQ(test.resultD, inputfs_D[i]*inputft_D[i]); + } +} + + +TEST(mov) { + const int tableLength = 4; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double a; + double b; + float c; + float d; + }TestFloat; + + TestFloat test; + double inputs_D[tableLength] = { + 5.3, -5.3, 5.3, -2.9 + }; + double inputs_S[tableLength] = { + 4.8, 4.8, -4.8, -0.29 + }; + + float outputs_S[tableLength] = { + 4.8, 4.8, -4.8, -0.29 + }; + double outputs_D[tableLength] = { + 5.3, -5.3, 5.3, -2.9 + }; + + __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) ); + __ mov_s(f18, f6); + __ mov_d(f20, f2); + __ swc1(f18, MemOperand(a0, offsetof(TestFloat, d)) ); + __ sdc1(f20, MemOperand(a0, offsetof(TestFloat, b)) ); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.c = inputs_S[i]; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.b, outputs_D[i]); + CHECK_EQ(test.d, outputs_S[i]); + } +} + + +TEST(floor_w) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double a; + float b; + int32_t c; // a floor result + int32_t d; // b floor result + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, - 37778931862957161709568.0, 37778931862957161709569.0, - 37778931862957161709580.0, 37778931862957161709581.0, - 37778931862957161709582.0, 37778931862957161709583.0, - 37778931862957161709584.0, 37778931862957161709585.0, - 37778931862957161709586.0, 37778931862957161709587.0}; - double outputs_RN[tableLength] = {18446744073709551617.0, - 4503599627370496.0, -4503599627370496.0, - 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, - 1.7976931348623157E308, 0, - 309485009821345068724781057.0, - 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, - -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, - 37778931862957161709568.0, 37778931862957161709569.0, - 37778931862957161709580.0, 37778931862957161709581.0, - 37778931862957161709582.0, 37778931862957161709583.0, - 37778931862957161709584.0, 37778931862957161709585.0, - 37778931862957161709586.0, 37778931862957161709587.0}; - double outputs_RZ[tableLength] = {18446744073709551617.0, - 4503599627370496.0, -4503599627370496.0, - 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, - 1.7976931348623157E308, 0, - 309485009821345068724781057.0, - 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, - -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, - 37778931862957161709568.0, 37778931862957161709569.0, - 37778931862957161709580.0, 37778931862957161709581.0, - 37778931862957161709582.0, 37778931862957161709583.0, - 37778931862957161709584.0, 37778931862957161709585.0, - 37778931862957161709586.0, 37778931862957161709587.0}; - double outputs_RP[tableLength] = {18446744073709551617.0, - 4503599627370496.0, -4503599627370496.0, - 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, - 1.7976931348623157E308, 1, - 309485009821345068724781057.0, - 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, - -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, - 37778931862957161709568.0, 37778931862957161709569.0, - 37778931862957161709580.0, 37778931862957161709581.0, - 37778931862957161709582.0, 37778931862957161709583.0, - 37778931862957161709584.0, 37778931862957161709585.0, - 37778931862957161709586.0, 37778931862957161709587.0}; - double outputs_RM[tableLength] = {18446744073709551617.0, - 4503599627370496.0, -4503599627370496.0, - 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, - 1.7976931348623157E308, 0, - 309485009821345068724781057.0, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, - 37778931862957161709568.0, 37778931862957161709569.0, - 37778931862957161709580.0, 37778931862957161709581.0, - 37778931862957161709582.0, 37778931862957161709583.0, - 37778931862957161709584.0, 37778931862957161709585.0, - 37778931862957161709586.0, 37778931862957161709587.0}; - int fcsr_inputs[4] = - {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf}; - double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM}; - __ ldc1(f4, MemOperand(a0, OFFSET_OF(TestFloat, a)) ); - __ lw(t0, MemOperand(a0, OFFSET_OF(TestFloat, fcsr)) ); - __ cfc1(t1, FCSR); - __ ctc1(t0, FCSR); - __ rint_d(f8, f4); - __ sdc1(f8, MemOperand(a0, OFFSET_OF(TestFloat, b)) ); - __ ctc1(t1, FCSR); + kFPUInvalidResult, kFPUInvalidResult, + kFPUInvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ floor_w_d(f8, f4); + __ floor_w_s(f10, f6); + __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); + } +} + + +TEST(floor_l) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); + typedef struct test_float { + double a; + float b; + int64_t c; + int64_t d; + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, + -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, + 2147483648.0, dFPU64InvalidResult, + dFPU64InvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ floor_l_d(f8, f4); + __ floor_l_s(f10, f6); + __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); __ jr(ra); __ nop(); - + Test test; CodeDesc desc; assm.GetCode(&desc); Handle<Code> code = isolate->factory()->NewCode( desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); F3 f = FUNCTION_CAST<F3>(code->entry()); - for (int j = 0;j < 4;j++) { - test.fcsr = fcsr_inputs[j]; - for (int i = 0;i < tableLength;i++) { - test.a = inputs[i]; - (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); - CHECK_EQ(test.b, outputs[j][i]); - } + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); } +} + + +TEST(ceil_w) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double a; + float b; + int32_t c; // a floor result + int32_t d; // b floor result + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, + -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, + kFPUInvalidResult, kFPUInvalidResult, + kFPUInvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ ceil_w_d(f8, f4); + __ ceil_w_s(f10, f6); + __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); } } +TEST(ceil_l) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); + typedef struct test_float { + double a; + float b; + int64_t c; + int64_t d; + }Test; + const int tableLength = 15; + double inputs_D[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<double>::quiet_NaN(), + std::numeric_limits<double>::infinity() + }; + float inputs_S[tableLength] = { + 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, + -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, + 2147483648.0, + std::numeric_limits<float>::quiet_NaN(), + std::numeric_limits<float>::infinity() + }; + double outputs[tableLength] = { + 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, + -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, + 2147483648.0, dFPU64InvalidResult, + dFPU64InvalidResult}; + + __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); + __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); + __ ceil_l_d(f8, f4); + __ ceil_l_s(f10, f6); + __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); + __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); + __ jr(ra); + __ nop(); + Test test; + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + for (int i = 0; i < tableLength; i++) { + test.a = inputs_D[i]; + test.b = inputs_S[i]; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, outputs[i]); + CHECK_EQ(test.d, test.c); + } +} TEST(jump_tables1) { @@ -1930,8 +3123,9 @@ TEST(jump_tables1) { #endif F1 f = FUNCTION_CAST<F1>(code->entry()); for (int i = 0; i < kNumCases; ++i) { - int res = reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, i, 0, 0, 0, 0)); - ::printf("f(%d) = %d\n", i, res); + int64_t res = reinterpret_cast<int64_t>( + CALL_GENERATED_CODE(f, i, 0, 0, 0, 0)); + ::printf("f(%d) = %" PRId64 "\n", i, res); CHECK_EQ(values[i], static_cast<int>(res)); } } @@ -2002,8 +3196,9 @@ TEST(jump_tables2) { #endif F1 f = FUNCTION_CAST<F1>(code->entry()); for (int i = 0; i < kNumCases; ++i) { - int res = reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, i, 0, 0, 0, 0)); - ::printf("f(%d) = %d\n", i, res); + int64_t res = reinterpret_cast<int64_t>( + CALL_GENERATED_CODE(f, i, 0, 0, 0, 0)); + ::printf("f(%d) = %" PRId64 "\n", i, res); CHECK_EQ(values[i], res); } } @@ -2095,4 +3290,2080 @@ TEST(jump_tables3) { } +TEST(BITSWAP) { + // Test BITSWAP + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + typedef struct { + int64_t r1; + int64_t r2; + int64_t r3; + int64_t r4; + int64_t r5; + int64_t r6; + } T; + T t; + + Assembler assm(isolate, NULL, 0); + + __ ld(a4, MemOperand(a0, offsetof(T, r1))); + __ nop(); + __ bitswap(a6, a4); + __ sd(a6, MemOperand(a0, offsetof(T, r1))); + + __ ld(a4, MemOperand(a0, offsetof(T, r2))); + __ nop(); + __ bitswap(a6, a4); + __ sd(a6, MemOperand(a0, offsetof(T, r2))); + + __ ld(a4, MemOperand(a0, offsetof(T, r3))); + __ nop(); + __ bitswap(a6, a4); + __ sd(a6, MemOperand(a0, offsetof(T, r3))); + + __ ld(a4, MemOperand(a0, offsetof(T, r4))); + __ nop(); + __ bitswap(a6, a4); + __ sd(a6, MemOperand(a0, offsetof(T, r4))); + + __ ld(a4, MemOperand(a0, offsetof(T, r5))); + __ nop(); + __ dbitswap(a6, a4); + __ sd(a6, MemOperand(a0, offsetof(T, r5))); + + __ ld(a4, MemOperand(a0, offsetof(T, r6))); + __ nop(); + __ dbitswap(a6, a4); + __ sd(a6, MemOperand(a0, offsetof(T, r6))); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + t.r1 = 0x00102100781A15C3; + t.r2 = 0x001021008B71FCDE; + t.r3 = 0xFF8017FF781A15C3; + t.r4 = 0xFF8017FF8B71FCDE; + t.r5 = 0x10C021098B71FCDE; + t.r6 = 0xFB8017FF781A15C3; + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); + USE(dummy); + + CHECK_EQ(static_cast<int64_t>(0x000000001E58A8C3L), t.r1); + CHECK_EQ(static_cast<int64_t>(0xFFFFFFFFD18E3F7BL), t.r2); + CHECK_EQ(static_cast<int64_t>(0x000000001E58A8C3L), t.r3); + CHECK_EQ(static_cast<int64_t>(0xFFFFFFFFD18E3F7BL), t.r4); + CHECK_EQ(static_cast<int64_t>(0x08038490D18E3F7BL), t.r5); + CHECK_EQ(static_cast<int64_t>(0xDF01E8FF1E58A8C3L), t.r6); + } +} + + +TEST(class_fmt) { + if (kArchVariant == kMips64r6) { + // Test CLASS.fmt instruction. + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + typedef struct { + double dSignalingNan; + double dQuietNan; + double dNegInf; + double dNegNorm; + double dNegSubnorm; + double dNegZero; + double dPosInf; + double dPosNorm; + double dPosSubnorm; + double dPosZero; + float fSignalingNan; + float fQuietNan; + float fNegInf; + float fNegNorm; + float fNegSubnorm; + float fNegZero; + float fPosInf; + float fPosNorm; + float fPosSubnorm; + float fPosZero; } T; + T t; + + // Create a function that accepts &t, and loads, manipulates, and stores + // the doubles t.a ... t.f. + MacroAssembler assm(isolate, NULL, 0); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dSignalingNan))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dSignalingNan))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dQuietNan))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dQuietNan))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dNegInf))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dNegInf))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dNegNorm))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dNegNorm))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dNegSubnorm))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dNegSubnorm))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dNegZero))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dNegZero))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dPosInf))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dPosInf))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dPosNorm))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dPosNorm))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dPosSubnorm))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dPosSubnorm))); + + __ ldc1(f4, MemOperand(a0, offsetof(T, dPosZero))); + __ class_d(f6, f4); + __ sdc1(f6, MemOperand(a0, offsetof(T, dPosZero))); + + // Testing instruction CLASS.S + __ lwc1(f4, MemOperand(a0, offsetof(T, fSignalingNan))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fSignalingNan))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fQuietNan))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fQuietNan))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fNegInf))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fNegInf))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fNegNorm))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fNegNorm))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fNegSubnorm))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fNegSubnorm))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fNegZero))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fNegZero))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fPosInf))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fPosInf))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fPosNorm))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fPosNorm))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fPosSubnorm))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fPosSubnorm))); + + __ lwc1(f4, MemOperand(a0, offsetof(T, fPosZero))); + __ class_s(f6, f4); + __ swc1(f6, MemOperand(a0, offsetof(T, fPosZero))); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + + // Double test values. + t.dSignalingNan = std::numeric_limits<double>::signaling_NaN(); + t.dQuietNan = std::numeric_limits<double>::quiet_NaN(); + t.dNegInf = -1.0 / 0.0; + t.dNegNorm = -5.0; + t.dNegSubnorm = -DBL_MIN / 2.0; + t.dNegZero = -0.0; + t.dPosInf = 2.0 / 0.0; + t.dPosNorm = 275.35; + t.dPosSubnorm = DBL_MIN / 2.0; + t.dPosZero = +0.0; + // Float test values + + t.fSignalingNan = std::numeric_limits<float>::signaling_NaN(); + t.fQuietNan = std::numeric_limits<float>::quiet_NaN(); + t.fNegInf = -0.5/0.0; + t.fNegNorm = -FLT_MIN; + t.fNegSubnorm = -FLT_MIN / 1.5; + t.fNegZero = -0.0; + t.fPosInf = 100000.0 / 0.0; + t.fPosNorm = FLT_MAX; + t.fPosSubnorm = FLT_MIN / 20.0; + t.fPosZero = +0.0; + + Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); + USE(dummy); + // Expected double results. + CHECK_EQ(bit_cast<int64_t>(t.dNegInf), 0x004); + CHECK_EQ(bit_cast<int64_t>(t.dNegNorm), 0x008); + CHECK_EQ(bit_cast<int64_t>(t.dNegSubnorm), 0x010); + CHECK_EQ(bit_cast<int64_t>(t.dNegZero), 0x020); + CHECK_EQ(bit_cast<int64_t>(t.dPosInf), 0x040); + CHECK_EQ(bit_cast<int64_t>(t.dPosNorm), 0x080); + CHECK_EQ(bit_cast<int64_t>(t.dPosSubnorm), 0x100); + CHECK_EQ(bit_cast<int64_t>(t.dPosZero), 0x200); + + // Expected float results. + CHECK_EQ(bit_cast<int32_t>(t.fNegInf), 0x004); + CHECK_EQ(bit_cast<int32_t>(t.fNegNorm), 0x008); + CHECK_EQ(bit_cast<int32_t>(t.fNegSubnorm), 0x010); + CHECK_EQ(bit_cast<int32_t>(t.fNegZero), 0x020); + CHECK_EQ(bit_cast<int32_t>(t.fPosInf), 0x040); + CHECK_EQ(bit_cast<int32_t>(t.fPosNorm), 0x080); + CHECK_EQ(bit_cast<int32_t>(t.fPosSubnorm), 0x100); + CHECK_EQ(bit_cast<int32_t>(t.fPosZero), 0x200); + } +} + + +TEST(ABS) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + int64_t fir; + double a; + float b; + double fcsr; + } TestFloat; + + TestFloat test; + + // Save FIR. + __ cfc1(a1, FCSR); + __ sd(a1, MemOperand(a0, offsetof(TestFloat, fcsr))); + // Disable FPU exceptions. + __ ctc1(zero_reg, FCSR); + + __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); + __ abs_d(f10, f4); + __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, a))); + + __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b))); + __ abs_s(f10, f4); + __ swc1(f10, MemOperand(a0, offsetof(TestFloat, b))); + + // Restore FCSR. + __ ctc1(a1, FCSR); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + test.a = -2.0; + test.b = -2.0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.a, 2.0); + CHECK_EQ(test.b, 2.0); + + test.a = 2.0; + test.b = 2.0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.a, 2.0); + CHECK_EQ(test.b, 2.0); + + // Testing biggest positive number + test.a = std::numeric_limits<double>::max(); + test.b = std::numeric_limits<float>::max(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.a, std::numeric_limits<double>::max()); + CHECK_EQ(test.b, std::numeric_limits<float>::max()); + + // Testing smallest negative number + test.a = -std::numeric_limits<double>::max(); // lowest() + test.b = -std::numeric_limits<float>::max(); // lowest() + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.a, std::numeric_limits<double>::max()); + CHECK_EQ(test.b, std::numeric_limits<float>::max()); + + // Testing smallest positive number + test.a = -std::numeric_limits<double>::min(); + test.b = -std::numeric_limits<float>::min(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.a, std::numeric_limits<double>::min()); + CHECK_EQ(test.b, std::numeric_limits<float>::min()); + + // Testing infinity + test.a = -std::numeric_limits<double>::max() + / std::numeric_limits<double>::min(); + test.b = -std::numeric_limits<float>::max() + / std::numeric_limits<float>::min(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.a, std::numeric_limits<double>::max() + / std::numeric_limits<double>::min()); + CHECK_EQ(test.b, std::numeric_limits<float>::max() + / std::numeric_limits<float>::min()); + + test.a = std::numeric_limits<double>::quiet_NaN(); + test.b = std::numeric_limits<float>::quiet_NaN(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(std::isnan(test.a), true); + CHECK_EQ(std::isnan(test.b), true); + + test.a = std::numeric_limits<double>::signaling_NaN(); + test.b = std::numeric_limits<float>::signaling_NaN(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(std::isnan(test.a), true); + CHECK_EQ(std::isnan(test.b), true); +} + + +TEST(ADD_FMT) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double a; + double b; + double c; + float fa; + float fb; + float fc; + } TestFloat; + + TestFloat test; + + __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); + __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b))); + __ add_d(f10, f8, f4); + __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c))); + + __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, fa))); + __ lwc1(f8, MemOperand(a0, offsetof(TestFloat, fb))); + __ add_s(f10, f8, f4); + __ swc1(f10, MemOperand(a0, offsetof(TestFloat, fc))); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + test.a = 2.0; + test.b = 3.0; + test.fa = 2.0; + test.fb = 3.0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, 5.0); + CHECK_EQ(test.fc, 5.0); + + test.a = std::numeric_limits<double>::max(); + test.b = -std::numeric_limits<double>::max(); // lowest() + test.fa = std::numeric_limits<float>::max(); + test.fb = -std::numeric_limits<float>::max(); // lowest() + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.c, 0.0); + CHECK_EQ(test.fc, 0.0); + + test.a = std::numeric_limits<double>::max(); + test.b = std::numeric_limits<double>::max(); + test.fa = std::numeric_limits<float>::max(); + test.fb = std::numeric_limits<float>::max(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(std::isfinite(test.c), false); + CHECK_EQ(std::isfinite(test.fc), false); + + test.a = 5.0; + test.b = std::numeric_limits<double>::signaling_NaN(); + test.fa = 5.0; + test.fb = std::numeric_limits<float>::signaling_NaN(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(std::isnan(test.c), true); + CHECK_EQ(std::isnan(test.fc), true); +} + + +TEST(C_COND_FMT) { + if (kArchVariant == kMips64r2) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double dOp1; + double dOp2; + uint32_t dF; + uint32_t dUn; + uint32_t dEq; + uint32_t dUeq; + uint32_t dOlt; + uint32_t dUlt; + uint32_t dOle; + uint32_t dUle; + float fOp1; + float fOp2; + uint32_t fF; + uint32_t fUn; + uint32_t fEq; + uint32_t fUeq; + uint32_t fOlt; + uint32_t fUlt; + uint32_t fOle; + uint32_t fUle; + } TestFloat; + + TestFloat test; + + __ li(t1, 1); + + __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, dOp1))); + __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, dOp2))); + + __ lwc1(f14, MemOperand(a0, offsetof(TestFloat, fOp1))); + __ lwc1(f16, MemOperand(a0, offsetof(TestFloat, fOp2))); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(F, f4, f6, 0); + __ c_s(F, f14, f16, 2); + __ movt(t2, t1, 0); + __ movt(t3, t1, 2); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dF)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fF)) ); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(UN, f4, f6, 2); + __ c_s(UN, f14, f16, 4); + __ movt(t2, t1, 2); + __ movt(t3, t1, 4); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUn)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUn)) ); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(EQ, f4, f6, 4); + __ c_s(EQ, f14, f16, 6); + __ movt(t2, t1, 4); + __ movt(t3, t1, 6); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dEq)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fEq)) ); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(UEQ, f4, f6, 6); + __ c_s(UEQ, f14, f16, 0); + __ movt(t2, t1, 6); + __ movt(t3, t1, 0); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUeq)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUeq)) ); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(OLT, f4, f6, 0); + __ c_s(OLT, f14, f16, 2); + __ movt(t2, t1, 0); + __ movt(t3, t1, 2); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dOlt)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fOlt)) ); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(ULT, f4, f6, 2); + __ c_s(ULT, f14, f16, 4); + __ movt(t2, t1, 2); + __ movt(t3, t1, 4); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUlt)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUlt)) ); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(OLE, f4, f6, 4); + __ c_s(OLE, f14, f16, 6); + __ movt(t2, t1, 4); + __ movt(t3, t1, 6); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dOle)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fOle)) ); + + __ mov(t2, zero_reg); + __ mov(t3, zero_reg); + __ c_d(ULE, f4, f6, 6); + __ c_s(ULE, f14, f16, 0); + __ movt(t2, t1, 6); + __ movt(t3, t1, 0); + __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUle)) ); + __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUle)) ); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + test.dOp1 = 2.0; + test.dOp2 = 3.0; + test.fOp1 = 2.0; + test.fOp2 = 3.0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dF, 0U); + CHECK_EQ(test.dUn, 0U); + CHECK_EQ(test.dEq, 0U); + CHECK_EQ(test.dUeq, 0U); + CHECK_EQ(test.dOlt, 1U); + CHECK_EQ(test.dUlt, 1U); + CHECK_EQ(test.dOle, 1U); + CHECK_EQ(test.dUle, 1U); + CHECK_EQ(test.fF, 0U); + CHECK_EQ(test.fUn, 0U); + CHECK_EQ(test.fEq, 0U); + CHECK_EQ(test.fUeq, 0U); + CHECK_EQ(test.fOlt, 1U); + CHECK_EQ(test.fUlt, 1U); + CHECK_EQ(test.fOle, 1U); + CHECK_EQ(test.fUle, 1U); + + test.dOp1 = std::numeric_limits<double>::max(); + test.dOp2 = std::numeric_limits<double>::min(); + test.fOp1 = std::numeric_limits<float>::min(); + test.fOp2 = -std::numeric_limits<float>::max(); // lowest() + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dF, 0U); + CHECK_EQ(test.dUn, 0U); + CHECK_EQ(test.dEq, 0U); + CHECK_EQ(test.dUeq, 0U); + CHECK_EQ(test.dOlt, 0U); + CHECK_EQ(test.dUlt, 0U); + CHECK_EQ(test.dOle, 0U); + CHECK_EQ(test.dUle, 0U); + CHECK_EQ(test.fF, 0U); + CHECK_EQ(test.fUn, 0U); + CHECK_EQ(test.fEq, 0U); + CHECK_EQ(test.fUeq, 0U); + CHECK_EQ(test.fOlt, 0U); + CHECK_EQ(test.fUlt, 0U); + CHECK_EQ(test.fOle, 0U); + CHECK_EQ(test.fUle, 0U); + + test.dOp1 = -std::numeric_limits<double>::max(); // lowest() + test.dOp2 = -std::numeric_limits<double>::max(); // lowest() + test.fOp1 = std::numeric_limits<float>::max(); + test.fOp2 = std::numeric_limits<float>::max(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dF, 0U); + CHECK_EQ(test.dUn, 0U); + CHECK_EQ(test.dEq, 1U); + CHECK_EQ(test.dUeq, 1U); + CHECK_EQ(test.dOlt, 0U); + CHECK_EQ(test.dUlt, 0U); + CHECK_EQ(test.dOle, 1U); + CHECK_EQ(test.dUle, 1U); + CHECK_EQ(test.fF, 0U); + CHECK_EQ(test.fUn, 0U); + CHECK_EQ(test.fEq, 1U); + CHECK_EQ(test.fUeq, 1U); + CHECK_EQ(test.fOlt, 0U); + CHECK_EQ(test.fUlt, 0U); + CHECK_EQ(test.fOle, 1U); + CHECK_EQ(test.fUle, 1U); + + test.dOp1 = std::numeric_limits<double>::quiet_NaN(); + test.dOp2 = 0.0; + test.fOp1 = std::numeric_limits<float>::quiet_NaN(); + test.fOp2 = 0.0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dF, 0U); + CHECK_EQ(test.dUn, 1U); + CHECK_EQ(test.dEq, 0U); + CHECK_EQ(test.dUeq, 1U); + CHECK_EQ(test.dOlt, 0U); + CHECK_EQ(test.dUlt, 1U); + CHECK_EQ(test.dOle, 0U); + CHECK_EQ(test.dUle, 1U); + CHECK_EQ(test.fF, 0U); + CHECK_EQ(test.fUn, 1U); + CHECK_EQ(test.fEq, 0U); + CHECK_EQ(test.fUeq, 1U); + CHECK_EQ(test.fOlt, 0U); + CHECK_EQ(test.fUlt, 1U); + CHECK_EQ(test.fOle, 0U); + CHECK_EQ(test.fUle, 1U); + } +} + + +TEST(CMP_COND_FMT) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + double dOp1; + double dOp2; + double dF; + double dUn; + double dEq; + double dUeq; + double dOlt; + double dUlt; + double dOle; + double dUle; + double dOr; + double dUne; + double dNe; + float fOp1; + float fOp2; + float fF; + float fUn; + float fEq; + float fUeq; + float fOlt; + float fUlt; + float fOle; + float fUle; + float fOr; + float fUne; + float fNe; + } TestFloat; + + TestFloat test; + + __ li(t1, 1); + + __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, dOp1))); + __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, dOp2))); + + __ lwc1(f14, MemOperand(a0, offsetof(TestFloat, fOp1))); + __ lwc1(f16, MemOperand(a0, offsetof(TestFloat, fOp2))); + + __ cmp_d(F, f2, f4, f6); + __ cmp_s(F, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dF)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fF)) ); + + __ cmp_d(UN, f2, f4, f6); + __ cmp_s(UN, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUn)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUn)) ); + + __ cmp_d(EQ, f2, f4, f6); + __ cmp_s(EQ, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dEq)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fEq)) ); + + __ cmp_d(UEQ, f2, f4, f6); + __ cmp_s(UEQ, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUeq)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUeq)) ); + + __ cmp_d(LT, f2, f4, f6); + __ cmp_s(LT, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOlt)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOlt)) ); + + __ cmp_d(ULT, f2, f4, f6); + __ cmp_s(ULT, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUlt)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUlt)) ); + + __ cmp_d(LE, f2, f4, f6); + __ cmp_s(LE, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOle)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOle)) ); + + __ cmp_d(ULE, f2, f4, f6); + __ cmp_s(ULE, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUle)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUle)) ); + + __ cmp_d(ORD, f2, f4, f6); + __ cmp_s(ORD, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOr)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOr)) ); + + __ cmp_d(UNE, f2, f4, f6); + __ cmp_s(UNE, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUne)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUne)) ); + + __ cmp_d(NE, f2, f4, f6); + __ cmp_s(NE, f12, f14, f16); + __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dNe)) ); + __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fNe)) ); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + uint64_t dTrue = 0xFFFFFFFFFFFFFFFF; + uint64_t dFalse = 0x0000000000000000; + uint32_t fTrue = 0xFFFFFFFF; + uint32_t fFalse = 0x00000000; + + test.dOp1 = 2.0; + test.dOp2 = 3.0; + test.fOp1 = 2.0; + test.fOp2 = 3.0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue); + + test.dOp1 = std::numeric_limits<double>::max(); + test.dOp2 = std::numeric_limits<double>::min(); + test.fOp1 = std::numeric_limits<float>::min(); + test.fOp2 = -std::numeric_limits<float>::max(); // lowest() + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUle), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUle), fFalse); + + test.dOp1 = -std::numeric_limits<double>::max(); // lowest() + test.dOp2 = -std::numeric_limits<double>::max(); // lowest() + test.fOp1 = std::numeric_limits<float>::max(); + test.fOp2 = std::numeric_limits<float>::max(); + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dEq), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dUne), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fEq), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue); + + test.dOp1 = std::numeric_limits<double>::quiet_NaN(); + test.dOp2 = 0.0; + test.fOp1 = std::numeric_limits<float>::quiet_NaN(); + test.fOp2 = 0.0; + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUn), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dOr), dFalse); + CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue); + CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUn), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue); + CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse); + CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue); + } +} + + +TEST(CVT) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test_float { + float cvt_d_s_in; + double cvt_d_s_out; + int32_t cvt_d_w_in; + double cvt_d_w_out; + int64_t cvt_d_l_in; + double cvt_d_l_out; + + float cvt_l_s_in; + int64_t cvt_l_s_out; + double cvt_l_d_in; + int64_t cvt_l_d_out; + + double cvt_s_d_in; + float cvt_s_d_out; + int32_t cvt_s_w_in; + float cvt_s_w_out; + int64_t cvt_s_l_in; + float cvt_s_l_out; + + float cvt_w_s_in; + int32_t cvt_w_s_out; + double cvt_w_d_in; + int32_t cvt_w_d_out; + } TestFloat; + + TestFloat test; + + // Save FCSR. + __ cfc1(a1, FCSR); + // Disable FPU exceptions. + __ ctc1(zero_reg, FCSR); + +#define GENERATE_CVT_TEST(x, y, z) \ + __ y##c1(f0, MemOperand(a0, offsetof(TestFloat, x##_in))); \ + __ x(f0, f0); \ + __ nop(); \ + __ z##c1(f0, MemOperand(a0, offsetof(TestFloat, x##_out))); + + GENERATE_CVT_TEST(cvt_d_s, lw, sd) + GENERATE_CVT_TEST(cvt_d_w, lw, sd) + GENERATE_CVT_TEST(cvt_d_l, ld, sd) + + GENERATE_CVT_TEST(cvt_l_s, lw, sd) + GENERATE_CVT_TEST(cvt_l_d, ld, sd) + + GENERATE_CVT_TEST(cvt_s_d, ld, sw) + GENERATE_CVT_TEST(cvt_s_w, lw, sw) + GENERATE_CVT_TEST(cvt_s_l, ld, sw) + + GENERATE_CVT_TEST(cvt_w_s, lw, sw) + GENERATE_CVT_TEST(cvt_w_d, ld, sw) + + // Restore FCSR. + __ ctc1(a1, FCSR); + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + + test.cvt_d_s_in = -0.51; + test.cvt_d_w_in = -1; + test.cvt_d_l_in = -1; + test.cvt_l_s_in = -0.51; + test.cvt_l_d_in = -0.51; + test.cvt_s_d_in = -0.51; + test.cvt_s_w_in = -1; + test.cvt_s_l_in = -1; + test.cvt_w_s_in = -0.51; + test.cvt_w_d_in = -0.51; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); + CHECK_EQ(test.cvt_l_s_out, -1); + CHECK_EQ(test.cvt_l_d_out, -1); + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); + CHECK_EQ(test.cvt_w_s_out, -1); + CHECK_EQ(test.cvt_w_d_out, -1); + + + test.cvt_d_s_in = 0.49; + test.cvt_d_w_in = 1; + test.cvt_d_l_in = 1; + test.cvt_l_s_in = 0.49; + test.cvt_l_d_in = 0.49; + test.cvt_s_d_in = 0.49; + test.cvt_s_w_in = 1; + test.cvt_s_l_in = 1; + test.cvt_w_s_in = 0.49; + test.cvt_w_d_in = 0.49; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); + CHECK_EQ(test.cvt_l_s_out, 0); + CHECK_EQ(test.cvt_l_d_out, 0); + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); + CHECK_EQ(test.cvt_w_s_out, 0); + CHECK_EQ(test.cvt_w_d_out, 0); + + test.cvt_d_s_in = std::numeric_limits<float>::max(); + test.cvt_d_w_in = std::numeric_limits<int32_t>::max(); + test.cvt_d_l_in = std::numeric_limits<int64_t>::max(); + test.cvt_l_s_in = std::numeric_limits<float>::max(); + test.cvt_l_d_in = std::numeric_limits<double>::max(); + test.cvt_s_d_in = std::numeric_limits<double>::max(); + test.cvt_s_w_in = std::numeric_limits<int32_t>::max(); + test.cvt_s_l_in = std::numeric_limits<int64_t>::max(); + test.cvt_w_s_in = std::numeric_limits<float>::max(); + test.cvt_w_d_in = std::numeric_limits<double>::max(); + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); + CHECK_EQ(test.cvt_l_s_out, std::numeric_limits<int64_t>::max()); + CHECK_EQ(test.cvt_l_d_out, std::numeric_limits<int64_t>::max()); + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); + CHECK_EQ(test.cvt_w_s_out, std::numeric_limits<int32_t>::max()); + CHECK_EQ(test.cvt_w_d_out, std::numeric_limits<int32_t>::max()); + + + test.cvt_d_s_in = -std::numeric_limits<float>::max(); // lowest() + test.cvt_d_w_in = std::numeric_limits<int32_t>::min(); // lowest() + test.cvt_d_l_in = std::numeric_limits<int64_t>::min(); // lowest() + test.cvt_l_s_in = -std::numeric_limits<float>::max(); // lowest() + test.cvt_l_d_in = -std::numeric_limits<double>::max(); // lowest() + test.cvt_s_d_in = -std::numeric_limits<double>::max(); // lowest() + test.cvt_s_w_in = std::numeric_limits<int32_t>::min(); // lowest() + test.cvt_s_l_in = std::numeric_limits<int64_t>::min(); // lowest() + test.cvt_w_s_in = -std::numeric_limits<float>::max(); // lowest() + test.cvt_w_d_in = -std::numeric_limits<double>::max(); // lowest() + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); + // The returned value when converting from fixed-point to float-point + // is not consistent between board, simulator and specification + // in this test case, therefore modifying the test + CHECK(test.cvt_l_s_out == std::numeric_limits<int64_t>::min() || + test.cvt_l_s_out == std::numeric_limits<int64_t>::max()); + CHECK(test.cvt_l_d_out == std::numeric_limits<int64_t>::min() || + test.cvt_l_d_out == std::numeric_limits<int64_t>::max()); + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); + CHECK(test.cvt_w_s_out == std::numeric_limits<int32_t>::min() || + test.cvt_w_s_out == std::numeric_limits<int32_t>::max()); + CHECK(test.cvt_w_d_out == std::numeric_limits<int32_t>::min() || + test.cvt_w_d_out == std::numeric_limits<int32_t>::max()); + + + test.cvt_d_s_in = std::numeric_limits<float>::min(); + test.cvt_d_w_in = std::numeric_limits<int32_t>::min(); + test.cvt_d_l_in = std::numeric_limits<int64_t>::min(); + test.cvt_l_s_in = std::numeric_limits<float>::min(); + test.cvt_l_d_in = std::numeric_limits<double>::min(); + test.cvt_s_d_in = std::numeric_limits<double>::min(); + test.cvt_s_w_in = std::numeric_limits<int32_t>::min(); + test.cvt_s_l_in = std::numeric_limits<int64_t>::min(); + test.cvt_w_s_in = std::numeric_limits<float>::min(); + test.cvt_w_d_in = std::numeric_limits<double>::min(); + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); + CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); + CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); + CHECK_EQ(test.cvt_l_s_out, 0); + CHECK_EQ(test.cvt_l_d_out, 0); + CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); + CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); + CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); + CHECK_EQ(test.cvt_w_s_out, 0); + CHECK_EQ(test.cvt_w_d_out, 0); +} + + +TEST(DIV_FMT) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assm(isolate, NULL, 0); + + typedef struct test { + double dOp1; + double dOp2; + double dRes; + float fOp1; + float fOp2; + float fRes; + } Test; + + Test test; + + // Save FCSR. + __ cfc1(a1, FCSR); + // Disable FPU exceptions. + __ ctc1(zero_reg, FCSR); + + __ ldc1(f4, MemOperand(a0, offsetof(Test, dOp1)) ); + __ ldc1(f2, MemOperand(a0, offsetof(Test, dOp2)) ); + __ nop(); + __ div_d(f6, f4, f2); + __ sdc1(f6, MemOperand(a0, offsetof(Test, dRes)) ); + + __ lwc1(f4, MemOperand(a0, offsetof(Test, fOp1)) ); + __ lwc1(f2, MemOperand(a0, offsetof(Test, fOp2)) ); + __ nop(); + __ div_s(f6, f4, f2); + __ swc1(f6, MemOperand(a0, offsetof(Test, fRes)) ); + + // Restore FCSR. + __ ctc1(a1, FCSR); + + __ jr(ra); + __ nop(); + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + F3 f = FUNCTION_CAST<F3>(code->entry()); + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + + const int test_size = 3; + + double dOp1[test_size] = { + 5.0, + DBL_MAX, + DBL_MAX, + }; + double dOp2[test_size] = { + 2.0, + 2.0, + -DBL_MAX, + }; + double dRes[test_size] = { + 2.5, + DBL_MAX / 2.0, + -1.0, + }; + float fOp1[test_size] = { + 5.0, + FLT_MAX, + FLT_MAX, + }; + float fOp2[test_size] = { + 2.0, + 2.0, + -FLT_MAX, + }; + float fRes[test_size] = { + 2.5, + FLT_MAX / 2.0, + -1.0, + }; + + for (int i = 0; i < test_size; i++) { + test.dOp1 = dOp1[i]; + test.dOp2 = dOp2[i]; + test.fOp1 = fOp1[i]; + test.fOp2 = fOp2[i]; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(test.dRes, dRes[i]); + CHECK_EQ(test.fRes, fRes[i]); + } + + test.dOp1 = DBL_MAX; + test.dOp2 = -0.0; + test.fOp1 = FLT_MAX; + test.fOp2 = -0.0; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(false, std::isfinite(test.dRes)); + CHECK_EQ(false, std::isfinite(test.fRes)); + + test.dOp1 = 0.0; + test.dOp2 = -0.0; + test.fOp1 = 0.0; + test.fOp2 = -0.0; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(true, std::isnan(test.dRes)); + CHECK_EQ(true, std::isnan(test.fRes)); + + test.dOp1 = std::numeric_limits<double>::quiet_NaN(); + test.dOp2 = -5.0; + test.fOp1 = std::numeric_limits<float>::quiet_NaN(); + test.fOp2 = -5.0; + + (CALL_GENERATED_CODE(f, &test, 0, 0, 0, 0)); + CHECK_EQ(true, std::isnan(test.dRes)); + CHECK_EQ(true, std::isnan(test.fRes)); +} + + +uint64_t run_align(uint64_t rs_value, uint64_t rt_value, uint8_t bp) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + __ align(v0, a0, a1, bp); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + uint64_t res = + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, rs_value, + rt_value, + 0, 0, 0)); + + return res; +} + + +TEST(r6_align) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + + struct TestCaseAlign { + uint64_t rs_value; + uint64_t rt_value; + uint8_t bp; + uint64_t expected_res; + }; + + struct TestCaseAlign tc[] = { + // rs_value, rt_value, bp, expected_res + { 0x11223344, 0xaabbccdd, 0, 0xffffffffaabbccdd }, + { 0x11223344, 0xaabbccdd, 1, 0xffffffffbbccdd11 }, + { 0x11223344, 0xaabbccdd, 2, 0xffffffffccdd1122 }, + { 0x11223344, 0xaabbccdd, 3, 0xffffffffdd112233 }, + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAlign); + for (size_t i = 0; i < nr_test_cases; ++i) { + CHECK_EQ(tc[i].expected_res, run_align(tc[i].rs_value, + tc[i].rt_value, + tc[i].bp)); + } + } +} + + +uint64_t run_dalign(uint64_t rs_value, uint64_t rt_value, uint8_t bp) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + __ dalign(v0, a0, a1, bp); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F4 f = FUNCTION_CAST<F4>(code->entry()); + uint64_t res = + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, rs_value, + rt_value, + 0, 0, 0)); + + return res; +} + + +TEST(r6_dalign) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + + struct TestCaseDalign { + uint64_t rs_value; + uint64_t rt_value; + uint8_t bp; + uint64_t expected_res; + }; + + struct TestCaseDalign tc[] = { + // rs_value, rt_value, bp, expected_res + { 0x1122334455667700, 0xaabbccddeeff8899, 0, 0xaabbccddeeff8899 }, + { 0x1122334455667700, 0xaabbccddeeff8899, 1, 0xbbccddeeff889911 }, + { 0x1122334455667700, 0xaabbccddeeff8899, 2, 0xccddeeff88991122 }, + { 0x1122334455667700, 0xaabbccddeeff8899, 3, 0xddeeff8899112233 }, + { 0x1122334455667700, 0xaabbccddeeff8899, 4, 0xeeff889911223344 }, + { 0x1122334455667700, 0xaabbccddeeff8899, 5, 0xff88991122334455 }, + { 0x1122334455667700, 0xaabbccddeeff8899, 6, 0x8899112233445566 }, + { 0x1122334455667700, 0xaabbccddeeff8899, 7, 0x9911223344556677 } + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseDalign); + for (size_t i = 0; i < nr_test_cases; ++i) { + CHECK_EQ(tc[i].expected_res, run_dalign(tc[i].rs_value, + tc[i].rt_value, + tc[i].bp)); + } + } +} + + +uint64_t PC; // The program counter. + +uint64_t run_aluipc(int16_t offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + __ aluipc(v0, offset); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + PC = (uint64_t) f; // Set the program counter. + + uint64_t res = + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_aluipc) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + + struct TestCaseAluipc { + int16_t offset; + }; + + struct TestCaseAluipc tc[] = { + // offset + { -32768 }, // 0x8000 + { -1 }, // 0xFFFF + { 0 }, + { 1 }, + { 32767 }, // 0x7FFF + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAluipc); + for (size_t i = 0; i < nr_test_cases; ++i) { + PC = 0; + uint64_t res = run_aluipc(tc[i].offset); + // Now, the program_counter (PC) is set. + uint64_t expected_res = ~0x0FFFF & (PC + (tc[i].offset << 16)); + CHECK_EQ(expected_res, res); + } + } +} + + +uint64_t run_auipc(int16_t offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + __ auipc(v0, offset); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + PC = (uint64_t) f; // Set the program counter. + + uint64_t res = + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_auipc) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + + struct TestCaseAuipc { + int16_t offset; + }; + + struct TestCaseAuipc tc[] = { + // offset + { -32768 }, // 0x8000 + { -1 }, // 0xFFFF + { 0 }, + { 1 }, + { 32767 }, // 0x7FFF + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAuipc); + for (size_t i = 0; i < nr_test_cases; ++i) { + PC = 0; + uint64_t res = run_auipc(tc[i].offset); + // Now, the program_counter (PC) is set. + uint64_t expected_res = PC + (tc[i].offset << 16); + CHECK_EQ(expected_res, res); + } + } +} + + +uint64_t run_lwpc(int offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + // 256k instructions; 2^8k + // addiu t3, a4, 0xffff; (0x250fffff) + // ... + // addiu t0, a4, 0x0000; (0x250c0000) + uint32_t addiu_start_1 = 0x25000000; + for (int32_t i = 0xfffff; i >= 0xc0000; --i) { + uint32_t addiu_new = addiu_start_1 + i; + __ dd(addiu_new); + } + + __ lwpc(t8, offset); // offset 0; 0xef080000 (t8 register) + __ mov(v0, t8); + + // 256k instructions; 2^8k + // addiu a4, a4, 0x0000; (0x25080000) + // ... + // addiu a7, a4, 0xffff; (0x250bffff) + uint32_t addiu_start_2 = 0x25000000; + for (int32_t i = 0x80000; i <= 0xbffff; ++i) { + uint32_t addiu_new = addiu_start_2 + i; + __ dd(addiu_new); + } + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + uint64_t res = + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_lwpc) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + + struct TestCaseLwpc { + int offset; + uint64_t expected_res; + }; + + struct TestCaseLwpc tc[] = { + // offset, expected_res + { -262144, 0x250fffff }, // offset 0x40000 + { -4, 0x250c0003 }, + { -1, 0x250c0000 }, + { 0, 0xffffffffef080000 }, + { 1, 0x03001025 }, // mov(v0, t8) + { 2, 0x25080000 }, + { 4, 0x25080002 }, + { 262143, 0x250bfffd }, // offset 0x3ffff + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLwpc); + for (size_t i = 0; i < nr_test_cases; ++i) { + uint64_t res = run_lwpc(tc[i].offset); + CHECK_EQ(tc[i].expected_res, res); + } + } +} + + +uint64_t run_lwupc(int offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + // 256k instructions; 2^8k + // addiu t3, a4, 0xffff; (0x250fffff) + // ... + // addiu t0, a4, 0x0000; (0x250c0000) + uint32_t addiu_start_1 = 0x25000000; + for (int32_t i = 0xfffff; i >= 0xc0000; --i) { + uint32_t addiu_new = addiu_start_1 + i; + __ dd(addiu_new); + } + + __ lwupc(t8, offset); // offset 0; 0xef080000 (t8 register) + __ mov(v0, t8); + + // 256k instructions; 2^8k + // addiu a4, a4, 0x0000; (0x25080000) + // ... + // addiu a7, a4, 0xffff; (0x250bffff) + uint32_t addiu_start_2 = 0x25000000; + for (int32_t i = 0x80000; i <= 0xbffff; ++i) { + uint32_t addiu_new = addiu_start_2 + i; + __ dd(addiu_new); + } + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + uint64_t res = + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_lwupc) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + + struct TestCaseLwupc { + int offset; + uint64_t expected_res; + }; + + struct TestCaseLwupc tc[] = { + // offset, expected_res + { -262144, 0x250fffff }, // offset 0x40000 + { -4, 0x250c0003 }, + { -1, 0x250c0000 }, + { 0, 0xef100000 }, + { 1, 0x03001025 }, // mov(v0, t8) + { 2, 0x25080000 }, + { 4, 0x25080002 }, + { 262143, 0x250bfffd }, // offset 0x3ffff + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLwupc); + for (size_t i = 0; i < nr_test_cases; ++i) { + uint64_t res = run_lwupc(tc[i].offset); + CHECK_EQ(tc[i].expected_res, res); + } + } +} + + +uint64_t run_jic(int16_t offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + Label get_program_counter, stop_execution; + __ push(ra); + __ li(v0, 0); + __ li(t1, 0x66); + + __ addiu(v0, v0, 0x1); // <-- offset = -32 + __ addiu(v0, v0, 0x2); + __ addiu(v0, v0, 0x10); + __ addiu(v0, v0, 0x20); + __ beq(v0, t1, &stop_execution); + __ nop(); + + __ bal(&get_program_counter); // t0 <- program counter + __ nop(); + __ jic(t0, offset); + + __ addiu(v0, v0, 0x100); + __ addiu(v0, v0, 0x200); + __ addiu(v0, v0, 0x1000); + __ addiu(v0, v0, 0x2000); // <--- offset = 16 + __ pop(ra); + __ jr(ra); + __ nop(); + + __ bind(&get_program_counter); + __ mov(t0, ra); + __ jr(ra); + __ nop(); + + __ bind(&stop_execution); + __ pop(ra); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + uint64_t res = + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_jic) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + + struct TestCaseJic { + // As rt will be used t0 register which will have value of + // the program counter for the jic instruction. + int16_t offset; + uint32_t expected_res; + }; + + struct TestCaseJic tc[] = { + // offset, expected_result + { 16, 0x2033 }, + { 4, 0x3333 }, + { -32, 0x66 }, + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJic); + for (size_t i = 0; i < nr_test_cases; ++i) { + uint64_t res = run_jic(tc[i].offset); + CHECK_EQ(tc[i].expected_res, res); + } + } +} + + +uint64_t run_beqzc(int32_t value, int32_t offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + Label stop_execution; + __ li(v0, 0); + __ li(t1, 0x66); + + __ addiu(v0, v0, 0x1); // <-- offset = -8 + __ addiu(v0, v0, 0x2); + __ addiu(v0, v0, 0x10); + __ addiu(v0, v0, 0x20); + __ beq(v0, t1, &stop_execution); + __ nop(); + + __ beqzc(a0, offset); + + __ addiu(v0, v0, 0x1); + __ addiu(v0, v0, 0x100); + __ addiu(v0, v0, 0x200); + __ addiu(v0, v0, 0x1000); + __ addiu(v0, v0, 0x2000); // <--- offset = 4 + __ jr(ra); + __ nop(); + + __ bind(&stop_execution); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + uint64_t res = + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, value, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_beqzc) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + + struct TestCaseBeqzc { + uint32_t value; + int32_t offset; + uint32_t expected_res; + }; + + struct TestCaseBeqzc tc[] = { + // value, offset, expected_res + { 0x0, -8, 0x66 }, + { 0x0, 0, 0x3334 }, + { 0x0, 1, 0x3333 }, + { 0xabc, 1, 0x3334 }, + { 0x0, 4, 0x2033 }, + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBeqzc); + for (size_t i = 0; i < nr_test_cases; ++i) { + uint64_t res = run_beqzc(tc[i].value, tc[i].offset); + CHECK_EQ(tc[i].expected_res, res); + } + } +} + + +uint64_t run_jialc(int16_t offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + Label main_block, get_program_counter; + __ push(ra); + __ li(v0, 0); + __ beq(v0, v0, &main_block); + __ nop(); + + // Block 1 + __ addiu(v0, v0, 0x1); // <-- offset = -40 + __ addiu(v0, v0, 0x2); + __ jr(ra); + __ nop(); + + // Block 2 + __ addiu(v0, v0, 0x10); // <-- offset = -24 + __ addiu(v0, v0, 0x20); + __ jr(ra); + __ nop(); + + // Block 3 (Main) + __ bind(&main_block); + __ bal(&get_program_counter); // t0 <- program counter + __ nop(); + __ jialc(t0, offset); + __ addiu(v0, v0, 0x4); + __ pop(ra); + __ jr(ra); + __ nop(); + + // Block 4 + __ addiu(v0, v0, 0x100); // <-- offset = 20 + __ addiu(v0, v0, 0x200); + __ jr(ra); + __ nop(); + + // Block 5 + __ addiu(v0, v0, 0x1000); // <--- offset = 36 + __ addiu(v0, v0, 0x2000); + __ jr(ra); + __ nop(); + + __ bind(&get_program_counter); + __ mov(t0, ra); + __ jr(ra); + __ nop(); + + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + uint64_t res = + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_jialc) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + + struct TestCaseJialc { + // As rt will be used t0 register which will have value of + // the program counter for the jialc instruction. + int16_t offset; + uint32_t expected_res; + }; + + struct TestCaseJialc tc[] = { + // offset, expected_res + { -40, 0x7 }, + { -24, 0x34 }, + { 20, 0x304 }, + { 36, 0x3004 } + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJialc); + for (size_t i = 0; i < nr_test_cases; ++i) { + uint64_t res = run_jialc(tc[i].offset); + CHECK_EQ(tc[i].expected_res, res); + } + } +} + + +uint64_t run_addiupc(int32_t imm19) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + __ addiupc(v0, imm19); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + PC = (uint64_t) f; // Set the program counter. + + uint64_t res = + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_addiupc) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + + struct TestCaseAddiupc { + int32_t imm19; + }; + + struct TestCaseAddiupc tc[] = { + // imm19 + { -262144 }, // 0x40000 + { -1 }, // 0x7FFFF + { 0 }, + { 1 }, // 0x00001 + { 262143 } // 0x3FFFF + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAddiupc); + for (size_t i = 0; i < nr_test_cases; ++i) { + PC = 0; + uint64_t res = run_addiupc(tc[i].imm19); + // Now, the program_counter (PC) is set. + uint64_t expected_res = PC + (tc[i].imm19 << 2); + CHECK_EQ(expected_res, res); + } + } +} + + +uint64_t run_ldpc(int offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + // 256k instructions; 2 * 2^7k = 2^8k + // addiu t3, a4, 0xffff; (0x250fffff) + // ... + // addiu t0, a4, 0x0000; (0x250c0000) + uint32_t addiu_start_1 = 0x25000000; + for (int32_t i = 0xfffff; i >= 0xc0000; --i) { + uint32_t addiu_new = addiu_start_1 + i; + __ dd(addiu_new); + } + + __ ldpc(t8, offset); // offset 0; 0xef080000 (t8 register) + __ mov(v0, t8); + + // 256k instructions; 2 * 2^7k = 2^8k + // addiu a4, a4, 0x0000; (0x25080000) + // ... + // addiu a7, a4, 0xffff; (0x250bffff) + uint32_t addiu_start_2 = 0x25000000; + for (int32_t i = 0x80000; i <= 0xbffff; ++i) { + uint32_t addiu_new = addiu_start_2 + i; + __ dd(addiu_new); + } + + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + uint64_t res = + reinterpret_cast<uint64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_ldpc) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + + struct TestCaseLdpc { + int offset; + uint64_t expected_res; + }; + + struct TestCaseLdpc tc[] = { + // offset, expected_res + { -131072, 0x250ffffe250fffff }, + { -4, 0x250c0006250c0007 }, + { -1, 0x250c0000250c0001 }, + { 0, 0x03001025ef180000 }, + { 1, 0x2508000125080000 }, + { 4, 0x2508000725080006 }, + { 131071, 0x250bfffd250bfffc }, + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLdpc); + for (size_t i = 0; i < nr_test_cases; ++i) { + uint64_t res = run_ldpc(tc[i].offset); + CHECK_EQ(tc[i].expected_res, res); + } + } +} + + +int64_t run_bc(int32_t offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + Label continue_1, stop_execution; + __ push(ra); + __ li(v0, 0); + __ li(t8, 0); + __ li(t9, 2); // Condition for the stopping execution. + + uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1 + for (int32_t i = -100; i <= -11; ++i) { + __ dd(instruction_addiu); + } + + __ addiu(t8, t8, 1); // -10 + + __ beq(t8, t9, &stop_execution); // -9 + __ nop(); // -8 + __ beq(t8, t8, &continue_1); // -7 + __ nop(); // -6 + + __ bind(&stop_execution); + __ pop(ra); // -5, -4 + __ jr(ra); // -3 + __ nop(); // -2 + + __ bind(&continue_1); + __ bc(offset); // -1 + + for (int32_t i = 0; i <= 99; ++i) { + __ dd(instruction_addiu); + } + + __ pop(ra); + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + int64_t res = + reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_bc) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + + struct TestCaseBc { + int32_t offset; + int64_t expected_res; + }; + + struct TestCaseBc tc[] = { + // offset, expected_result + { -100, (abs(-100) - 10) * 2 }, + { -11, (abs(-100) - 10 + 1) }, + { 0, (abs(-100) - 10 + 1 + 99) }, + { 1, (abs(-100) - 10 + 99) }, + { 99, (abs(-100) - 10 + 1) }, + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBc); + for (size_t i = 0; i < nr_test_cases; ++i) { + int64_t res = run_bc(tc[i].offset); + CHECK_EQ(tc[i].expected_res, res); + } + } +} + + +int64_t run_balc(int32_t offset) { + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assm(isolate, NULL, 0); + + Label continue_1, stop_execution; + __ push(ra); + __ li(v0, 0); + __ li(t8, 0); + __ li(t9, 2); // Condition for stopping execution. + + __ beq(t8, t8, &continue_1); + __ nop(); + + uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1 + for (int32_t i = -117; i <= -57; ++i) { + __ dd(instruction_addiu); + } + __ jr(ra); // -56 + __ nop(); // -55 + + for (int32_t i = -54; i <= -4; ++i) { + __ dd(instruction_addiu); + } + __ jr(ra); // -3 + __ nop(); // -2 + + __ bind(&continue_1); + __ balc(offset); // -1 + + __ pop(ra); // 0, 1 + __ jr(ra); // 2 + __ nop(); // 3 + + for (int32_t i = 4; i <= 44; ++i) { + __ dd(instruction_addiu); + } + __ jr(ra); + __ nop(); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); + + F2 f = FUNCTION_CAST<F2>(code->entry()); + + int64_t res = + reinterpret_cast<int64_t>(CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); + + return res; +} + + +TEST(r6_balc) { + if (kArchVariant == kMips64r6) { + CcTest::InitializeVM(); + + struct TestCaseBalc { + int32_t offset; + int64_t expected_res; + }; + + struct TestCaseBalc tc[] = { + // offset, expected_result + { -117, 61 }, + { -54, 51 }, + { 0, 0 }, + { 4, 41 }, + }; + + size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBalc); + for (size_t i = 0; i < nr_test_cases; ++i) { + int64_t res = run_balc(tc[i].offset); + CHECK_EQ(tc[i].expected_res, res); + } + } +} + + #undef __ diff --git a/deps/v8/test/cctest/test-assembler-ppc.cc b/deps/v8/test/cctest/test-assembler-ppc.cc index 4a2e7d3983..b2dca6a9fc 100644 --- a/deps/v8/test/cctest/test-assembler-ppc.cc +++ b/deps/v8/test/cctest/test-assembler-ppc.cc @@ -194,21 +194,21 @@ TEST(3) { __ mr(r4, r3); // modify field int i of struct - __ lwz(r3, MemOperand(r4, OFFSET_OF(T, i))); + __ lwz(r3, MemOperand(r4, offsetof(T, i))); __ srwi(r5, r3, Operand(1)); - __ stw(r5, MemOperand(r4, OFFSET_OF(T, i))); + __ stw(r5, MemOperand(r4, offsetof(T, i))); // modify field char c of struct - __ lbz(r5, MemOperand(r4, OFFSET_OF(T, c))); + __ lbz(r5, MemOperand(r4, offsetof(T, c))); __ add(r3, r5, r3); __ slwi(r5, r5, Operand(2)); - __ stb(r5, MemOperand(r4, OFFSET_OF(T, c))); + __ stb(r5, MemOperand(r4, offsetof(T, c))); // modify field int16_t s of struct - __ lhz(r5, MemOperand(r4, OFFSET_OF(T, s))); + __ lhz(r5, MemOperand(r4, offsetof(T, s))); __ add(r3, r5, r3); __ srwi(r5, r5, Operand(3)); - __ sth(r5, MemOperand(r4, OFFSET_OF(T, s))); + __ sth(r5, MemOperand(r4, offsetof(T, s))); // restore frame #if V8_TARGET_ARCH_PPC64 @@ -278,59 +278,59 @@ TEST(4) { __ sub(fp, ip, Operand(4)); __ mov(r4, Operand(r0)); - __ vldr(d6, r4, OFFSET_OF(T, a)); - __ vldr(d7, r4, OFFSET_OF(T, b)); + __ vldr(d6, r4, offsetof(T, a)); + __ vldr(d7, r4, offsetof(T, b)); __ vadd(d5, d6, d7); - __ vstr(d5, r4, OFFSET_OF(T, c)); + __ vstr(d5, r4, offsetof(T, c)); __ vmov(r2, r3, d5); __ vmov(d4, r2, r3); - __ vstr(d4, r4, OFFSET_OF(T, b)); + __ vstr(d4, r4, offsetof(T, b)); // Load t.x and t.y, switch values, and store back to the struct. - __ vldr(s0, r4, OFFSET_OF(T, x)); - __ vldr(s31, r4, OFFSET_OF(T, y)); + __ vldr(s0, r4, offsetof(T, x)); + __ vldr(s31, r4, offsetof(T, y)); __ vmov(s16, s0); __ vmov(s0, s31); __ vmov(s31, s16); - __ vstr(s0, r4, OFFSET_OF(T, x)); - __ vstr(s31, r4, OFFSET_OF(T, y)); + __ vstr(s0, r4, offsetof(T, x)); + __ vstr(s31, r4, offsetof(T, y)); // Move a literal into a register that can be encoded in the instruction. __ vmov(d4, 1.0); - __ vstr(d4, r4, OFFSET_OF(T, e)); + __ vstr(d4, r4, offsetof(T, e)); // Move a literal into a register that requires 64 bits to encode. // 0x3ff0000010000000 = 1.000000059604644775390625 __ vmov(d4, 1.000000059604644775390625); - __ vstr(d4, r4, OFFSET_OF(T, d)); + __ vstr(d4, r4, offsetof(T, d)); // Convert from floating point to integer. __ vmov(d4, 2.0); __ vcvt_s32_f64(s31, d4); - __ vstr(s31, r4, OFFSET_OF(T, i)); + __ vstr(s31, r4, offsetof(T, i)); // Convert from integer to floating point. __ mov(lr, Operand(42)); __ vmov(s31, lr); __ vcvt_f64_s32(d4, s31); - __ vstr(d4, r4, OFFSET_OF(T, f)); + __ vstr(d4, r4, offsetof(T, f)); // Test vabs. - __ vldr(d1, r4, OFFSET_OF(T, g)); + __ vldr(d1, r4, offsetof(T, g)); __ vabs(d0, d1); - __ vstr(d0, r4, OFFSET_OF(T, g)); - __ vldr(d2, r4, OFFSET_OF(T, h)); + __ vstr(d0, r4, offsetof(T, g)); + __ vldr(d2, r4, offsetof(T, h)); __ vabs(d0, d2); - __ vstr(d0, r4, OFFSET_OF(T, h)); + __ vstr(d0, r4, offsetof(T, h)); // Test vneg. - __ vldr(d1, r4, OFFSET_OF(T, m)); + __ vldr(d1, r4, offsetof(T, m)); __ vneg(d0, d1); - __ vstr(d0, r4, OFFSET_OF(T, m)); - __ vldr(d1, r4, OFFSET_OF(T, n)); + __ vstr(d0, r4, offsetof(T, m)); + __ vldr(d1, r4, offsetof(T, n)); __ vneg(d0, d1); - __ vstr(d0, r4, OFFSET_OF(T, n)); + __ vstr(d0, r4, offsetof(T, n)); __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); @@ -677,19 +677,19 @@ TEST(8) { __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); __ sub(fp, ip, Operand(4)); - __ addi(r4, r0, Operand(OFFSET_OF(D, a))); + __ addi(r4, r0, Operand(offsetof(D, a))); __ vldm(ia_w, r4, d0, d3); __ vldm(ia_w, r4, d4, d7); - __ addi(r4, r0, Operand(OFFSET_OF(D, a))); + __ addi(r4, r0, Operand(offsetof(D, a))); __ vstm(ia_w, r4, d6, d7); __ vstm(ia_w, r4, d0, d5); - __ addi(r4, r1, Operand(OFFSET_OF(F, a))); + __ addi(r4, r1, Operand(offsetof(F, a))); __ vldm(ia_w, r4, s0, s3); __ vldm(ia_w, r4, s4, s7); - __ addi(r4, r1, Operand(OFFSET_OF(F, a))); + __ addi(r4, r1, Operand(offsetof(F, a))); __ vstm(ia_w, r4, s6, s7); __ vstm(ia_w, r4, s0, s5); @@ -789,22 +789,22 @@ TEST(9) { __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); __ sub(fp, ip, Operand(4)); - __ addi(r4, r0, Operand(OFFSET_OF(D, a))); + __ addi(r4, r0, Operand(offsetof(D, a))); __ vldm(ia, r4, d0, d3); __ addi(r4, r4, Operand(4 * 8)); __ vldm(ia, r4, d4, d7); - __ addi(r4, r0, Operand(OFFSET_OF(D, a))); + __ addi(r4, r0, Operand(offsetof(D, a))); __ vstm(ia, r4, d6, d7); __ addi(r4, r4, Operand(2 * 8)); __ vstm(ia, r4, d0, d5); - __ addi(r4, r1, Operand(OFFSET_OF(F, a))); + __ addi(r4, r1, Operand(offsetof(F, a))); __ vldm(ia, r4, s0, s3); __ addi(r4, r4, Operand(4 * 4)); __ vldm(ia, r4, s4, s7); - __ addi(r4, r1, Operand(OFFSET_OF(F, a))); + __ addi(r4, r1, Operand(offsetof(F, a))); __ vstm(ia, r4, s6, s7); __ addi(r4, r4, Operand(2 * 4)); __ vstm(ia, r4, s0, s5); @@ -905,19 +905,19 @@ TEST(10) { __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); __ sub(fp, ip, Operand(4)); - __ addi(r4, r0, Operand(OFFSET_OF(D, h) + 8)); + __ addi(r4, r0, Operand(offsetof(D, h) + 8)); __ vldm(db_w, r4, d4, d7); __ vldm(db_w, r4, d0, d3); - __ addi(r4, r0, Operand(OFFSET_OF(D, h) + 8)); + __ addi(r4, r0, Operand(offsetof(D, h) + 8)); __ vstm(db_w, r4, d0, d5); __ vstm(db_w, r4, d6, d7); - __ addi(r4, r1, Operand(OFFSET_OF(F, h) + 4)); + __ addi(r4, r1, Operand(offsetof(F, h) + 4)); __ vldm(db_w, r4, s4, s7); __ vldm(db_w, r4, s0, s3); - __ addi(r4, r1, Operand(OFFSET_OF(F, h) + 4)); + __ addi(r4, r1, Operand(offsetof(F, h) + 4)); __ vstm(db_w, r4, s0, s5); __ vstm(db_w, r4, s6, s7); @@ -996,28 +996,28 @@ TEST(11) { Assembler assm(isolate, NULL, 0); // Test HeapObject untagging. - __ ldr(r1, MemOperand(r0, OFFSET_OF(I, a))); + __ ldr(r1, MemOperand(r0, offsetof(I, a))); __ mov(r1, Operand(r1, ASR, 1), SetCC); __ adc(r1, r1, Operand(r1), LeaveCC, cs); - __ str(r1, MemOperand(r0, OFFSET_OF(I, a))); + __ str(r1, MemOperand(r0, offsetof(I, a))); - __ ldr(r2, MemOperand(r0, OFFSET_OF(I, b))); + __ ldr(r2, MemOperand(r0, offsetof(I, b))); __ mov(r2, Operand(r2, ASR, 1), SetCC); __ adc(r2, r2, Operand(r2), LeaveCC, cs); - __ str(r2, MemOperand(r0, OFFSET_OF(I, b))); + __ str(r2, MemOperand(r0, offsetof(I, b))); // Test corner cases. __ mov(r1, Operand(0xffffffff)); __ mov(r2, Operand::Zero()); __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry. __ adc(r3, r1, Operand(r2)); - __ str(r3, MemOperand(r0, OFFSET_OF(I, c))); + __ str(r3, MemOperand(r0, offsetof(I, c))); __ mov(r1, Operand(0xffffffff)); __ mov(r2, Operand::Zero()); __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry. __ adc(r3, r1, Operand(r2)); - __ str(r3, MemOperand(r0, OFFSET_OF(I, d))); + __ str(r3, MemOperand(r0, offsetof(I, d))); __ mov(pc, Operand(lr)); diff --git a/deps/v8/test/cctest/test-code-stubs-arm64.cc b/deps/v8/test/cctest/test-code-stubs-arm64.cc index 6d5b0f49be..8b38b96600 100644 --- a/deps/v8/test/cctest/test-code-stubs-arm64.cc +++ b/deps/v8/test/cctest/test-code-stubs-arm64.cc @@ -142,8 +142,8 @@ int32_t RunGeneratedCodeCallWrapper(ConvertDToIFunc func, Simulator::CallArgument(from), Simulator::CallArgument::End() }; - return Simulator::current(Isolate::Current())->CallInt64( - FUNCTION_ADDR(func), args); + return static_cast<int32_t>(Simulator::current(Isolate::Current()) + ->CallInt64(FUNCTION_ADDR(func), args)); #else return (*func)(from); #endif diff --git a/deps/v8/test/cctest/test-code-stubs-mips64.cc b/deps/v8/test/cctest/test-code-stubs-mips64.cc index 1f7df380e1..9f146f65fd 100644 --- a/deps/v8/test/cctest/test-code-stubs-mips64.cc +++ b/deps/v8/test/cctest/test-code-stubs-mips64.cc @@ -144,7 +144,8 @@ int32_t RunGeneratedCodeCallWrapper(ConvertDToIFunc func, double from) { #ifdef USE_SIMULATOR Simulator::current(Isolate::Current())->CallFP(FUNCTION_ADDR(func), from, 0.); - return Simulator::current(Isolate::Current())->get_register(v0.code()); + return static_cast<int32_t>( + Simulator::current(Isolate::Current())->get_register(v0.code())); #else return (*func)(from); #endif diff --git a/deps/v8/test/cctest/test-compiler.cc b/deps/v8/test/cctest/test-compiler.cc index ed8b1c6d99..3b25480a4a 100644 --- a/deps/v8/test/cctest/test-compiler.cc +++ b/deps/v8/test/cctest/test-compiler.cc @@ -60,8 +60,8 @@ static Handle<JSFunction> Compile(const char* source) { Handle<String> source_code = isolate->factory()->NewStringFromUtf8( CStrVector(source)).ToHandleChecked(); Handle<SharedFunctionInfo> shared_function = Compiler::CompileScript( - source_code, Handle<String>(), 0, 0, false, false, Handle<Object>(), - Handle<Context>(isolate->native_context()), NULL, NULL, + source_code, Handle<String>(), 0, 0, v8::ScriptOriginOptions(), + Handle<Object>(), Handle<Context>(isolate->native_context()), NULL, NULL, v8::ScriptCompiler::kNoCompileOptions, NOT_NATIVES_CODE, false); return isolate->factory()->NewFunctionFromSharedFunctionInfo( shared_function, isolate->native_context()); @@ -362,7 +362,7 @@ TEST(FeedbackVectorUnaffectedByScopeChanges) { // Now a feedback vector is allocated. CHECK(f->shared()->is_compiled()); int expected_slots = 0; - int expected_ic_slots = FLAG_vector_ics ? 2 : 1; + int expected_ic_slots = 2; CHECK_EQ(expected_slots, f->shared()->feedback_vector()->Slots()); CHECK_EQ(expected_ic_slots, f->shared()->feedback_vector()->ICSlots()); } @@ -370,40 +370,92 @@ TEST(FeedbackVectorUnaffectedByScopeChanges) { // Test that optimized code for different closures is actually shared // immediately by the FastNewClosureStub when run in the same context. -TEST(OptimizedCodeSharing) { - // Skip test if --cache-optimized-code is not activated by default because - // FastNewClosureStub that is baked into the snapshot is incorrect. - if (!FLAG_cache_optimized_code) return; +TEST(OptimizedCodeSharing1) { FLAG_stress_compaction = false; FLAG_allow_natives_syntax = true; + FLAG_cache_optimized_code = true; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); for (int i = 0; i < 10; i++) { LocalContext env; env->Global()->Set(v8::String::NewFromUtf8(CcTest::isolate(), "x"), v8::Integer::New(CcTest::isolate(), i)); - CompileRun("function MakeClosure() {" - " return function() { return x; };" - "}" - "var closure0 = MakeClosure();" - "%DebugPrint(closure0());" - "%OptimizeFunctionOnNextCall(closure0);" - "%DebugPrint(closure0());" - "var closure1 = MakeClosure();" - "var closure2 = MakeClosure();"); + CompileRun( + "function MakeClosure() {" + " return function() { return x; };" + "}" + "var closure0 = MakeClosure();" + "%DebugPrint(closure0());" + "%OptimizeFunctionOnNextCall(closure0);" + "%DebugPrint(closure0());" + "var closure1 = MakeClosure();" + "var closure2 = MakeClosure();"); Handle<JSFunction> fun1 = v8::Utils::OpenHandle( *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure1")))); Handle<JSFunction> fun2 = v8::Utils::OpenHandle( *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure2")))); - CHECK(fun1->IsOptimized() - || !CcTest::i_isolate()->use_crankshaft() || !fun1->IsOptimizable()); - CHECK(fun2->IsOptimized() - || !CcTest::i_isolate()->use_crankshaft() || !fun2->IsOptimizable()); + CHECK(fun1->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); + CHECK(fun2->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); CHECK_EQ(fun1->code(), fun2->code()); } } +// Test that optimized code for different closures is actually shared +// immediately by the FastNewClosureStub when run different contexts. +TEST(OptimizedCodeSharing2) { + if (FLAG_stress_compaction) return; + FLAG_allow_natives_syntax = true; + FLAG_cache_optimized_code = true; + FLAG_turbo_cache_shared_code = true; + const char* flag = "--turbo-filter=*"; + FlagList::SetFlagsFromString(flag, StrLength(flag)); + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + v8::Local<v8::Script> script = v8_compile( + "function MakeClosure() {" + " return function() { return x; };" + "}"); + Handle<Code> reference_code; + { + LocalContext env; + env->Global()->Set(v8::String::NewFromUtf8(CcTest::isolate(), "x"), + v8::Integer::New(CcTest::isolate(), 23)); + script->GetUnboundScript()->BindToCurrentContext()->Run(); + CompileRun( + "var closure0 = MakeClosure();" + "%DebugPrint(closure0());" + "%OptimizeFunctionOnNextCall(closure0);" + "%DebugPrint(closure0());"); + Handle<JSFunction> fun0 = v8::Utils::OpenHandle( + *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure0")))); + CHECK(fun0->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); + reference_code = handle(fun0->code()); + } + for (int i = 0; i < 10; i++) { + LocalContext env; + env->Global()->Set(v8::String::NewFromUtf8(CcTest::isolate(), "x"), + v8::Integer::New(CcTest::isolate(), i)); + script->GetUnboundScript()->BindToCurrentContext()->Run(); + CompileRun( + "var closure0 = MakeClosure();" + "%DebugPrint(closure0());" + "%OptimizeFunctionOnNextCall(closure0);" + "%DebugPrint(closure0());" + "var closure1 = MakeClosure();" + "var closure2 = MakeClosure();"); + Handle<JSFunction> fun1 = v8::Utils::OpenHandle( + *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure1")))); + Handle<JSFunction> fun2 = v8::Utils::OpenHandle( + *v8::Local<v8::Function>::Cast(env->Global()->Get(v8_str("closure2")))); + CHECK(fun1->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); + CHECK(fun2->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); + CHECK_EQ(*reference_code, fun1->code()); + CHECK_EQ(*reference_code, fun2->code()); + } +} + + TEST(CompileFunctionInContext) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -533,6 +585,9 @@ static void CheckCodeForUnsafeLiteral(Handle<JSFunction> f) { int decode_size = Min(f->code()->instruction_size(), static_cast<int>(f->code()->back_edge_table_offset())); + if (FLAG_enable_embedded_constant_pool) { + decode_size = Min(decode_size, f->code()->constant_pool_offset()); + } Address end = pc + decode_size; v8::internal::EmbeddedVector<char, 128> decode_buffer; diff --git a/deps/v8/test/cctest/test-constantpool.cc b/deps/v8/test/cctest/test-constantpool.cc index 4592074742..ce3abb0edb 100644 --- a/deps/v8/test/cctest/test-constantpool.cc +++ b/deps/v8/test/cctest/test-constantpool.cc @@ -1,337 +1,247 @@ -// Copyright 2013 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Test constant pool array code. +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Test embedded constant pool builder code. #include "src/v8.h" -#include "src/factory.h" -#include "src/objects.h" +#include "src/assembler.h" #include "test/cctest/cctest.h" using namespace v8::internal; -static ConstantPoolArray::Type kTypes[] = { ConstantPoolArray::INT64, - ConstantPoolArray::CODE_PTR, - ConstantPoolArray::HEAP_PTR, - ConstantPoolArray::INT32 }; -static ConstantPoolArray::LayoutSection kSmall = - ConstantPoolArray::SMALL_SECTION; -static ConstantPoolArray::LayoutSection kExtended = - ConstantPoolArray::EXTENDED_SECTION; - -Code* DummyCode(LocalContext* context) { - CompileRun("function foo() {};"); - i::Handle<i::JSFunction> fun = v8::Utils::OpenHandle( - *v8::Local<v8::Function>::Cast( - (*context)->Global()->Get(v8_str("foo")))); - return fun->code(); -} +const ConstantPoolEntry::Type kPtrType = ConstantPoolEntry::INTPTR; +const ConstantPoolEntry::Type kDblType = ConstantPoolEntry::DOUBLE; +const ConstantPoolEntry::Access kRegAccess = ConstantPoolEntry::REGULAR; +const ConstantPoolEntry::Access kOvflAccess = ConstantPoolEntry::OVERFLOWED; +const int kReachBits = 6; // Use reach of 64-bytes to test overflow. +const int kReach = 1 << kReachBits; -TEST(ConstantPoolSmall) { - LocalContext context; - Isolate* isolate = CcTest::i_isolate(); - Factory* factory = isolate->factory(); - v8::HandleScope scope(context->GetIsolate()); - // Check construction. - ConstantPoolArray::NumberOfEntries small(3, 1, 2, 1); - Handle<ConstantPoolArray> array = factory->NewConstantPoolArray(small); +TEST(ConstantPoolPointers) { + ConstantPoolBuilder builder(kReachBits, kReachBits); + const int kRegularCount = kReach / kPointerSize; + ConstantPoolEntry::Access access; + int pos = 0; + intptr_t value = 0; + bool sharing_ok = true; - int expected_counts[] = { 3, 1, 2, 1 }; - int expected_first_idx[] = { 0, 3, 4, 6 }; - int expected_last_idx[] = { 2, 3, 5, 6 }; - for (int i = 0; i < 4; i++) { - CHECK_EQ(expected_counts[i], array->number_of_entries(kTypes[i], kSmall)); - CHECK_EQ(expected_first_idx[i], array->first_index(kTypes[i], kSmall)); - CHECK_EQ(expected_last_idx[i], array->last_index(kTypes[i], kSmall)); + CHECK(builder.IsEmpty()); + while (builder.NextAccess(kPtrType) == kRegAccess) { + access = builder.AddEntry(pos++, value++, sharing_ok); + CHECK_EQ(access, kRegAccess); } - CHECK(!array->is_extended_layout()); - - // Check getters and setters. - int64_t big_number = V8_2PART_UINT64_C(0x12345678, 9ABCDEF0); - Handle<Object> object = factory->NewHeapNumber(4.0, IMMUTABLE, TENURED); - Code* code = DummyCode(&context); - array->set(0, big_number); - array->set(1, 0.5); - array->set(2, 3e-24); - array->set(3, code->entry()); - array->set(4, code); - array->set(5, *object); - array->set(6, 50); - CHECK_EQ(big_number, array->get_int64_entry(0)); - CHECK_EQ(0.5, array->get_int64_entry_as_double(1)); - CHECK_EQ(3e-24, array->get_int64_entry_as_double(2)); - CHECK_EQ(code->entry(), array->get_code_ptr_entry(3)); - CHECK_EQ(code, array->get_heap_ptr_entry(4)); - CHECK_EQ(*object, array->get_heap_ptr_entry(5)); - CHECK_EQ(50, array->get_int32_entry(6)); + CHECK(!builder.IsEmpty()); + CHECK_EQ(pos, kRegularCount); + + access = builder.AddEntry(pos, value, sharing_ok); + CHECK_EQ(access, kOvflAccess); } -TEST(ConstantPoolExtended) { - LocalContext context; - Isolate* isolate = CcTest::i_isolate(); - Factory* factory = isolate->factory(); - v8::HandleScope scope(context->GetIsolate()); - - // Check construction. - ConstantPoolArray::NumberOfEntries small(1, 2, 3, 4); - ConstantPoolArray::NumberOfEntries extended(5, 6, 7, 8); - Handle<ConstantPoolArray> array = - factory->NewExtendedConstantPoolArray(small, extended); - - // Check small section. - int small_counts[] = { 1, 2, 3, 4 }; - int small_first_idx[] = { 0, 1, 3, 6 }; - int small_last_idx[] = { 0, 2, 5, 9 }; - for (int i = 0; i < 4; i++) { - CHECK_EQ(small_counts[i], array->number_of_entries(kTypes[i], kSmall)); - CHECK_EQ(small_first_idx[i], array->first_index(kTypes[i], kSmall)); - CHECK_EQ(small_last_idx[i], array->last_index(kTypes[i], kSmall)); - } +TEST(ConstantPoolDoubles) { + ConstantPoolBuilder builder(kReachBits, kReachBits); + const int kRegularCount = kReach / kDoubleSize; + ConstantPoolEntry::Access access; + int pos = 0; + double value = 0.0; - // Check extended layout. - CHECK(array->is_extended_layout()); - int extended_counts[] = { 5, 6, 7, 8 }; - int extended_first_idx[] = { 10, 15, 21, 28 }; - int extended_last_idx[] = { 14, 20, 27, 35 }; - for (int i = 0; i < 4; i++) { - CHECK_EQ(extended_counts[i], - array->number_of_entries(kTypes[i], kExtended)); - CHECK_EQ(extended_first_idx[i], array->first_index(kTypes[i], kExtended)); - CHECK_EQ(extended_last_idx[i], array->last_index(kTypes[i], kExtended)); + CHECK(builder.IsEmpty()); + while (builder.NextAccess(kDblType) == kRegAccess) { + access = builder.AddEntry(pos++, value); + value += 0.5; + CHECK_EQ(access, kRegAccess); } + CHECK(!builder.IsEmpty()); + CHECK_EQ(pos, kRegularCount); - // Check small and large section's don't overlap. - int64_t small_section_int64 = V8_2PART_UINT64_C(0x56781234, DEF09ABC); - Code* small_section_code_ptr = DummyCode(&context); - Handle<Object> small_section_heap_ptr = - factory->NewHeapNumber(4.0, IMMUTABLE, TENURED); - int32_t small_section_int32 = 0xab12cd45; - - int64_t extended_section_int64 = V8_2PART_UINT64_C(0x12345678, 9ABCDEF0); - Code* extended_section_code_ptr = DummyCode(&context); - Handle<Object> extended_section_heap_ptr = - factory->NewHeapNumber(5.0, IMMUTABLE, TENURED); - int32_t extended_section_int32 = 0xef67ab89; - - for (int i = array->first_index(ConstantPoolArray::INT64, kSmall); - i <= array->last_index(ConstantPoolArray::INT32, kSmall); i++) { - if (i <= array->last_index(ConstantPoolArray::INT64, kSmall)) { - array->set(i, small_section_int64); - } else if (i <= array->last_index(ConstantPoolArray::CODE_PTR, kSmall)) { - array->set(i, small_section_code_ptr->entry()); - } else if (i <= array->last_index(ConstantPoolArray::HEAP_PTR, kSmall)) { - array->set(i, *small_section_heap_ptr); - } else { - CHECK(i <= array->last_index(ConstantPoolArray::INT32, kSmall)); - array->set(i, small_section_int32); - } - } - for (int i = array->first_index(ConstantPoolArray::INT64, kExtended); - i <= array->last_index(ConstantPoolArray::INT32, kExtended); i++) { - if (i <= array->last_index(ConstantPoolArray::INT64, kExtended)) { - array->set(i, extended_section_int64); - } else if (i <= array->last_index(ConstantPoolArray::CODE_PTR, kExtended)) { - array->set(i, extended_section_code_ptr->entry()); - } else if (i <= array->last_index(ConstantPoolArray::HEAP_PTR, kExtended)) { - array->set(i, *extended_section_heap_ptr); - } else { - CHECK(i <= array->last_index(ConstantPoolArray::INT32, kExtended)); - array->set(i, extended_section_int32); - } - } + access = builder.AddEntry(pos, value); + CHECK_EQ(access, kOvflAccess); +} - for (int i = array->first_index(ConstantPoolArray::INT64, kSmall); - i <= array->last_index(ConstantPoolArray::INT32, kSmall); i++) { - if (i <= array->last_index(ConstantPoolArray::INT64, kSmall)) { - CHECK_EQ(small_section_int64, array->get_int64_entry(i)); - } else if (i <= array->last_index(ConstantPoolArray::CODE_PTR, kSmall)) { - CHECK_EQ(small_section_code_ptr->entry(), array->get_code_ptr_entry(i)); - } else if (i <= array->last_index(ConstantPoolArray::HEAP_PTR, kSmall)) { - CHECK_EQ(*small_section_heap_ptr, array->get_heap_ptr_entry(i)); - } else { - CHECK(i <= array->last_index(ConstantPoolArray::INT32, kSmall)); - CHECK_EQ(small_section_int32, array->get_int32_entry(i)); - } - } - for (int i = array->first_index(ConstantPoolArray::INT64, kExtended); - i <= array->last_index(ConstantPoolArray::INT32, kExtended); i++) { - if (i <= array->last_index(ConstantPoolArray::INT64, kExtended)) { - CHECK_EQ(extended_section_int64, array->get_int64_entry(i)); - } else if (i <= array->last_index(ConstantPoolArray::CODE_PTR, kExtended)) { - CHECK_EQ(extended_section_code_ptr->entry(), - array->get_code_ptr_entry(i)); - } else if (i <= array->last_index(ConstantPoolArray::HEAP_PTR, kExtended)) { - CHECK_EQ(*extended_section_heap_ptr, array->get_heap_ptr_entry(i)); + +TEST(ConstantPoolMixedTypes) { + ConstantPoolBuilder builder(kReachBits, kReachBits); + const int kRegularCount = (((kReach / (kDoubleSize + kPointerSize)) * 2) + + ((kPointerSize < kDoubleSize) ? 1 : 0)); + ConstantPoolEntry::Type type = kPtrType; + ConstantPoolEntry::Access access; + int pos = 0; + intptr_t ptrValue = 0; + double dblValue = 0.0; + bool sharing_ok = true; + + CHECK(builder.IsEmpty()); + while (builder.NextAccess(type) == kRegAccess) { + if (type == kPtrType) { + access = builder.AddEntry(pos++, ptrValue++, sharing_ok); + type = kDblType; } else { - CHECK(i <= array->last_index(ConstantPoolArray::INT32, kExtended)); - CHECK_EQ(extended_section_int32, array->get_int32_entry(i)); + access = builder.AddEntry(pos++, dblValue); + dblValue += 0.5; + type = kPtrType; } + CHECK_EQ(access, kRegAccess); } + CHECK(!builder.IsEmpty()); + CHECK_EQ(pos, kRegularCount); + + access = builder.AddEntry(pos++, ptrValue, sharing_ok); + CHECK_EQ(access, kOvflAccess); + access = builder.AddEntry(pos, dblValue); + CHECK_EQ(access, kOvflAccess); } -static void CheckIterator(Handle<ConstantPoolArray> array, - ConstantPoolArray::Type type, - int expected_indexes[], - int count) { - int i = 0; - ConstantPoolArray::Iterator iter(*array, type); - while (!iter.is_finished()) { - CHECK_EQ(expected_indexes[i++], iter.next_index()); +TEST(ConstantPoolMixedReach) { + const int ptrReachBits = kReachBits + 2; + const int ptrReach = 1 << ptrReachBits; + const int dblReachBits = kReachBits; + const int dblReach = kReach; + const int dblRegularCount = + Min(dblReach / kDoubleSize, ptrReach / (kDoubleSize + kPointerSize)); + const int ptrRegularCount = + ((ptrReach - (dblRegularCount * (kDoubleSize + kPointerSize))) / + kPointerSize) + + dblRegularCount; + ConstantPoolBuilder builder(ptrReachBits, dblReachBits); + ConstantPoolEntry::Access access; + int pos = 0; + intptr_t ptrValue = 0; + double dblValue = 0.0; + bool sharing_ok = true; + int ptrCount = 0; + int dblCount = 0; + + CHECK(builder.IsEmpty()); + while (builder.NextAccess(kDblType) == kRegAccess) { + access = builder.AddEntry(pos++, dblValue); + dblValue += 0.5; + dblCount++; + CHECK_EQ(access, kRegAccess); + + access = builder.AddEntry(pos++, ptrValue++, sharing_ok); + ptrCount++; + CHECK_EQ(access, kRegAccess); } - CHECK_EQ(count, i); -} + CHECK(!builder.IsEmpty()); + CHECK_EQ(dblCount, dblRegularCount); + while (ptrCount < ptrRegularCount) { + access = builder.AddEntry(pos++, dblValue); + dblValue += 0.5; + CHECK_EQ(access, kOvflAccess); -TEST(ConstantPoolIteratorSmall) { - LocalContext context; - Isolate* isolate = CcTest::i_isolate(); - Factory* factory = isolate->factory(); - v8::HandleScope scope(context->GetIsolate()); - - ConstantPoolArray::NumberOfEntries small(1, 5, 2, 0); - Handle<ConstantPoolArray> array = factory->NewConstantPoolArray(small); + access = builder.AddEntry(pos++, ptrValue++, sharing_ok); + ptrCount++; + CHECK_EQ(access, kRegAccess); + } + CHECK_EQ(builder.NextAccess(kPtrType), kOvflAccess); - int expected_int64_indexs[] = { 0 }; - CheckIterator(array, ConstantPoolArray::INT64, expected_int64_indexs, 1); - int expected_code_indexs[] = { 1, 2, 3, 4, 5 }; - CheckIterator(array, ConstantPoolArray::CODE_PTR, expected_code_indexs, 5); - int expected_heap_indexs[] = { 6, 7 }; - CheckIterator(array, ConstantPoolArray::HEAP_PTR, expected_heap_indexs, 2); - int expected_int32_indexs[1]; - CheckIterator(array, ConstantPoolArray::INT32, expected_int32_indexs, 0); + access = builder.AddEntry(pos++, ptrValue, sharing_ok); + CHECK_EQ(access, kOvflAccess); + access = builder.AddEntry(pos, dblValue); + CHECK_EQ(access, kOvflAccess); } -TEST(ConstantPoolIteratorExtended) { - LocalContext context; - Isolate* isolate = CcTest::i_isolate(); - Factory* factory = isolate->factory(); - v8::HandleScope scope(context->GetIsolate()); - - ConstantPoolArray::NumberOfEntries small(1, 0, 0, 4); - ConstantPoolArray::NumberOfEntries extended(5, 0, 3, 0); - Handle<ConstantPoolArray> array = - factory->NewExtendedConstantPoolArray(small, extended); - - int expected_int64_indexs[] = { 0, 5, 6, 7, 8, 9 }; - CheckIterator(array, ConstantPoolArray::INT64, expected_int64_indexs, 6); - int expected_code_indexs[1]; - CheckIterator(array, ConstantPoolArray::CODE_PTR, expected_code_indexs, 0); - int expected_heap_indexs[] = { 10, 11, 12 }; - CheckIterator(array, ConstantPoolArray::HEAP_PTR, expected_heap_indexs, 3); - int expected_int32_indexs[] = { 1, 2, 3, 4 }; - CheckIterator(array, ConstantPoolArray::INT32, expected_int32_indexs, 4); -} +TEST(ConstantPoolSharing) { + ConstantPoolBuilder builder(kReachBits, kReachBits); + const int kRegularCount = (((kReach / (kDoubleSize + kPointerSize)) * 2) + + ((kPointerSize < kDoubleSize) ? 1 : 0)); + ConstantPoolEntry::Access access; + CHECK(builder.IsEmpty()); -TEST(ConstantPoolPreciseGC) { - LocalContext context; - Isolate* isolate = CcTest::i_isolate(); - Heap* heap = isolate->heap(); - Factory* factory = isolate->factory(); - v8::HandleScope scope(context->GetIsolate()); - - ConstantPoolArray::NumberOfEntries small(1, 0, 0, 1); - Handle<ConstantPoolArray> array = factory->NewConstantPoolArray(small); - - // Check that the store buffer knows which entries are pointers and which are - // not. To do this, make non-pointer entries which look like new space - // pointers but are actually invalid and ensure the GC doesn't try to move - // them. - Handle<HeapObject> object = factory->NewHeapNumber(4.0); - Object* raw_ptr = *object; - // If interpreted as a pointer, this should be right inside the heap number - // which will cause a crash when trying to lookup the 'map' pointer. - intptr_t invalid_ptr = reinterpret_cast<intptr_t>(raw_ptr) + kInt32Size; - int32_t invalid_ptr_int32 = static_cast<int32_t>(invalid_ptr); - int64_t invalid_ptr_int64 = static_cast<int64_t>(invalid_ptr); - array->set(0, invalid_ptr_int64); - array->set(1, invalid_ptr_int32); - - // Ensure we perform a scan on scavenge for the constant pool's page. - MemoryChunk::FromAddress(array->address())->set_scan_on_scavenge(true); - heap->CollectGarbage(NEW_SPACE); - - // Check the object was moved by GC. - CHECK_NE(*object, raw_ptr); - - // Check the non-pointer entries weren't changed. - CHECK_EQ(invalid_ptr_int64, array->get_int64_entry(0)); - CHECK_EQ(invalid_ptr_int32, array->get_int32_entry(1)); + ConstantPoolEntry::Type type = kPtrType; + int pos = 0; + intptr_t ptrValue = 0; + double dblValue = 0.0; + bool sharing_ok = true; + while (builder.NextAccess(type) == kRegAccess) { + if (type == kPtrType) { + access = builder.AddEntry(pos++, ptrValue++, sharing_ok); + type = kDblType; + } else { + access = builder.AddEntry(pos++, dblValue); + dblValue += 0.5; + type = kPtrType; + } + CHECK_EQ(access, kRegAccess); + } + CHECK(!builder.IsEmpty()); + CHECK_EQ(pos, kRegularCount); + + type = kPtrType; + ptrValue = 0; + dblValue = 0.0; + while (pos < kRegularCount * 2) { + if (type == kPtrType) { + access = builder.AddEntry(pos++, ptrValue++, sharing_ok); + type = kDblType; + } else { + access = builder.AddEntry(pos++, dblValue); + dblValue += 0.5; + type = kPtrType; + } + CHECK_EQ(access, kRegAccess); + } + + access = builder.AddEntry(pos++, ptrValue, sharing_ok); + CHECK_EQ(access, kOvflAccess); + access = builder.AddEntry(pos, dblValue); + CHECK_EQ(access, kOvflAccess); } -TEST(ConstantPoolCompacting) { - if (i::FLAG_never_compact) return; - i::FLAG_always_compact = true; - LocalContext context; - Isolate* isolate = CcTest::i_isolate(); - Heap* heap = isolate->heap(); - Factory* factory = isolate->factory(); - v8::HandleScope scope(context->GetIsolate()); - - ConstantPoolArray::NumberOfEntries small(0, 0, 1, 0); - ConstantPoolArray::NumberOfEntries extended(0, 0, 1, 0); - Handle<ConstantPoolArray> array = - factory->NewExtendedConstantPoolArray(small, extended); - - // Start a second old-space page so that the heap pointer added to the - // constant pool array ends up on the an evacuation candidate page. - Page* first_page = heap->old_space()->anchor()->next_page(); - { - HandleScope scope(isolate); - int dummy_array_size = Page::kMaxRegularHeapObjectSize - 92 * KB; - Handle<HeapObject> temp = - factory->NewFixedDoubleArray(dummy_array_size / kDoubleSize, TENURED); - CHECK(heap->InOldSpace(temp->address())); - Handle<HeapObject> heap_ptr = - factory->NewHeapNumber(5.0, IMMUTABLE, TENURED); - CHECK(heap->InOldSpace(heap_ptr->address())); - CHECK(!first_page->Contains(heap_ptr->address())); - array->set(0, *heap_ptr); - array->set(1, *heap_ptr); - } +TEST(ConstantPoolNoSharing) { + ConstantPoolBuilder builder(kReachBits, kReachBits); + const int kRegularCount = (((kReach / (kDoubleSize + kPointerSize)) * 2) + + ((kPointerSize < kDoubleSize) ? 1 : 0)); + ConstantPoolEntry::Access access; - // Check heap pointers are correctly updated on GC. - Object* old_ptr = array->get_heap_ptr_entry(0); - Handle<Object> object(old_ptr, isolate); - CHECK_EQ(old_ptr, *object); - CHECK_EQ(old_ptr, array->get_heap_ptr_entry(1)); + CHECK(builder.IsEmpty()); - // Force compacting garbage collection. - CHECK(FLAG_always_compact); - heap->CollectAllGarbage(); + ConstantPoolEntry::Type type = kPtrType; + int pos = 0; + intptr_t ptrValue = 0; + double dblValue = 0.0; + bool sharing_ok = false; + while (builder.NextAccess(type) == kRegAccess) { + if (type == kPtrType) { + access = builder.AddEntry(pos++, ptrValue++, sharing_ok); + type = kDblType; + } else { + access = builder.AddEntry(pos++, dblValue); + dblValue += 0.5; + type = kPtrType; + } + CHECK_EQ(access, kRegAccess); + } + CHECK(!builder.IsEmpty()); + CHECK_EQ(pos, kRegularCount); + + type = kPtrType; + ptrValue = 0; + dblValue = 0.0; + sharing_ok = true; + while (pos < kRegularCount * 2) { + if (type == kPtrType) { + access = builder.AddEntry(pos++, ptrValue++, sharing_ok); + type = kDblType; + CHECK_EQ(access, kOvflAccess); + } else { + access = builder.AddEntry(pos++, dblValue); + dblValue += 0.5; + type = kPtrType; + CHECK_EQ(access, kRegAccess); + } + } - CHECK_NE(old_ptr, *object); - CHECK_EQ(*object, array->get_heap_ptr_entry(0)); - CHECK_EQ(*object, array->get_heap_ptr_entry(1)); + access = builder.AddEntry(pos++, ptrValue, sharing_ok); + CHECK_EQ(access, kOvflAccess); + access = builder.AddEntry(pos, dblValue); + CHECK_EQ(access, kOvflAccess); } diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc index 2f6cf6e9a2..a6ffdca179 100644 --- a/deps/v8/test/cctest/test-debug.cc +++ b/deps/v8/test/cctest/test-debug.cc @@ -115,8 +115,9 @@ class DebugLocalContext { v8::Utils::OpenHandle(*context_->Global()))); Handle<v8::internal::String> debug_string = factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("debug")); - v8::internal::Runtime::DefineObjectProperty(global, debug_string, - handle(debug_context->global_proxy(), isolate), DONT_ENUM).Check(); + v8::internal::JSObject::SetOwnPropertyIgnoreAttributes( + global, debug_string, handle(debug_context->global_proxy()), DONT_ENUM) + .Check(); } private: @@ -211,7 +212,7 @@ static int SetScriptBreakPointByIdFromJS(v8::Isolate* isolate, int script_id, } buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0'; { - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); v8::Handle<v8::String> str = v8::String::NewFromUtf8(isolate, buffer.start()); v8::Handle<v8::Value> value = v8::Script::Compile(str)->Run(); @@ -240,7 +241,7 @@ static int SetScriptBreakPointByNameFromJS(v8::Isolate* isolate, } buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0'; { - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); v8::Handle<v8::String> str = v8::String::NewFromUtf8(isolate, buffer.start()); v8::Handle<v8::Value> value = v8::Script::Compile(str)->Run(); @@ -425,7 +426,8 @@ void CheckDebuggerUnloaded(bool check_functions) { } -} } // namespace v8::internal +} // namespace internal +} // namespace v8 // Check that the debugger has been fully unloaded. @@ -443,6 +445,7 @@ void CheckDebugBreakFunction(DebugLocalContext* env, const char* source, const char* name, int position, v8::internal::RelocInfo::Mode mode, Code* debug_break) { + EnableDebugger(); i::Debug* debug = CcTest::i_isolate()->debug(); // Create function and set the break point. @@ -486,6 +489,8 @@ void CheckDebugBreakFunction(DebugLocalContext* env, i::RelocInfo rinfo = location.rinfo(); CHECK(!rinfo.IsPatchedReturnSequence()); } + + DisableDebugger(); } @@ -964,92 +969,6 @@ static void MessageCallbackCount(v8::Handle<v8::Message> message, // --- T h e A c t u a l T e s t s - -// Test that the debug break function is the expected one for different kinds -// of break locations. -TEST(DebugStub) { - using ::v8::internal::Builtins; - using ::v8::internal::Isolate; - DebugLocalContext env; - v8::HandleScope scope(env->GetIsolate()); - - CheckDebugBreakFunction(&env, - "function f1(){}", "f1", - 0, - v8::internal::RelocInfo::JS_RETURN, - NULL); - CheckDebugBreakFunction(&env, - "function f2(){x=1;}", "f2", - 0, - v8::internal::RelocInfo::CODE_TARGET, - CcTest::i_isolate()->builtins()->builtin( - Builtins::kStoreIC_DebugBreak)); - CheckDebugBreakFunction(&env, - "function f3(){var a=x;}", "f3", - 0, - v8::internal::RelocInfo::CODE_TARGET, - CcTest::i_isolate()->builtins()->builtin( - Builtins::kLoadIC_DebugBreak)); - -// TODO(1240753): Make the test architecture independent or split -// parts of the debugger into architecture dependent files. This -// part currently disabled as it is not portable between IA32/ARM. -// Currently on ICs for keyed store/load on ARM. -#if !defined (__arm__) && !defined(__thumb__) - CheckDebugBreakFunction( - &env, - "function f4(){var index='propertyName'; var a={}; a[index] = 'x';}", - "f4", - 0, - v8::internal::RelocInfo::CODE_TARGET, - CcTest::i_isolate()->builtins()->builtin( - Builtins::kKeyedStoreIC_DebugBreak)); - CheckDebugBreakFunction( - &env, - "function f5(){var index='propertyName'; var a={}; return a[index];}", - "f5", - 0, - v8::internal::RelocInfo::CODE_TARGET, - CcTest::i_isolate()->builtins()->builtin( - Builtins::kKeyedLoadIC_DebugBreak)); -#endif - - CheckDebugBreakFunction( - &env, - "function f6(a){return a==null;}", - "f6", - 0, - v8::internal::RelocInfo::CODE_TARGET, - CcTest::i_isolate()->builtins()->builtin( - Builtins::kCompareNilIC_DebugBreak)); - - // Check the debug break code stubs for call ICs with different number of - // parameters. - // TODO(verwaest): XXX update test. - // Handle<Code> debug_break_0 = v8::internal::ComputeCallDebugBreak(0); - // Handle<Code> debug_break_1 = v8::internal::ComputeCallDebugBreak(1); - // Handle<Code> debug_break_4 = v8::internal::ComputeCallDebugBreak(4); - - // CheckDebugBreakFunction(&env, - // "function f4_0(){x();}", "f4_0", - // 0, - // v8::internal::RelocInfo::CODE_TARGET, - // *debug_break_0); - - // CheckDebugBreakFunction(&env, - // "function f4_1(){x(1);}", "f4_1", - // 0, - // v8::internal::RelocInfo::CODE_TARGET, - // *debug_break_1); - - // CheckDebugBreakFunction(&env, - // "function f4_4(){x(1,2,3,4);}", "f4_4", - // 0, - // v8::internal::RelocInfo::CODE_TARGET, - // *debug_break_4); -} - - // Test that the debug info in the VM is in sync with the functions being // debugged. TEST(DebugInfo) { @@ -1064,6 +983,7 @@ TEST(DebugInfo) { CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length()); CHECK(!HasDebugInfo(foo)); CHECK(!HasDebugInfo(bar)); + EnableDebugger(); // One function (foo) is debugged. int bp1 = SetBreakPoint(foo, 0); CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length()); @@ -1081,6 +1001,7 @@ TEST(DebugInfo) { CHECK(HasDebugInfo(bar)); // No functions are debugged. ClearBreakPoint(bp2); + DisableDebugger(); CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length()); CHECK(!HasDebugInfo(foo)); CHECK(!HasDebugInfo(bar)); @@ -2288,11 +2209,12 @@ TEST(RemoveBreakPointInBreak) { v8::Local<v8::Function> foo = CompileFunction(&env, "function foo(){a=1;}", "foo"); - debug_event_remove_break_point = SetBreakPoint(foo, 0); // Register the debug event listener pasing the function v8::Debug::SetDebugEventListener(DebugEventRemoveBreakPoint, foo); + debug_event_remove_break_point = SetBreakPoint(foo, 0); + break_point_hit_count = 0; foo->Call(env->Global(), 0, NULL); CHECK_EQ(1, break_point_hit_count); @@ -2348,7 +2270,7 @@ TEST(DebuggerStatementBreakpoint) { v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast( env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo"))); - // The debugger statement triggers breakpint hit + // The debugger statement triggers breakpoint hit foo->Call(env->Global(), 0, NULL); CHECK_EQ(1, break_point_hit_count); @@ -2779,11 +2701,11 @@ TEST(DebugStepLinear) { // Run foo to allow it to get optimized. CompileRun("a=0; b=0; c=0; foo();"); - SetBreakPoint(foo, 3); - // Register a debug event listener which steps and counts. v8::Debug::SetDebugEventListener(DebugEventStep); + SetBreakPoint(foo, 3); + step_action = StepIn; break_point_hit_count = 0; foo->Call(env->Global(), 0, NULL); @@ -3272,6 +3194,13 @@ TEST(DebugStepDoWhile) { v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo"); SetBreakPoint(foo, 8); // "var a = 0;" + // Looping 0 times. + step_action = StepIn; + break_point_hit_count = 0; + v8::Handle<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)}; + foo->Call(env->Global(), argc, argv_0); + CHECK_EQ(4, break_point_hit_count); + // Looping 10 times. step_action = StepIn; break_point_hit_count = 0; @@ -3314,19 +3243,26 @@ TEST(DebugStepFor) { SetBreakPoint(foo, 8); // "a = 1;" + // Looping 0 times. + step_action = StepIn; + break_point_hit_count = 0; + v8::Handle<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)}; + foo->Call(env->Global(), argc, argv_0); + CHECK_EQ(4, break_point_hit_count); + // Looping 10 times. step_action = StepIn; break_point_hit_count = 0; v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) }; foo->Call(env->Global(), argc, argv_10); - CHECK_EQ(45, break_point_hit_count); + CHECK_EQ(34, break_point_hit_count); // Looping 100 times. step_action = StepIn; break_point_hit_count = 0; v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) }; foo->Call(env->Global(), argc, argv_100); - CHECK_EQ(405, break_point_hit_count); + CHECK_EQ(304, break_point_hit_count); // Get rid of the debug event listener. v8::Debug::SetDebugEventListener(NULL); @@ -3541,14 +3477,14 @@ TEST(DebugConditional) { step_action = StepIn; break_point_hit_count = 0; foo->Call(env->Global(), 0, NULL); - CHECK_EQ(5, break_point_hit_count); + CHECK_EQ(4, break_point_hit_count); step_action = StepIn; break_point_hit_count = 0; const int argc = 1; v8::Handle<v8::Value> argv_true[argc] = { v8::True(isolate) }; foo->Call(env->Global(), argc, argv_true); - CHECK_EQ(5, break_point_hit_count); + CHECK_EQ(4, break_point_hit_count); // Get rid of the debug event listener. v8::Debug::SetDebugEventListener(NULL); @@ -3823,6 +3759,48 @@ TEST(DebugStepFunctionCall) { } +// Test that step in works with Function.call.apply. +TEST(DebugStepFunctionCallApply) { + DebugLocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope scope(isolate); + + // Create a function for testing stepping. + v8::Local<v8::Function> foo = + CompileFunction(&env, + "function bar() { }" + "function foo(){ debugger;" + " Function.call.apply(bar);" + " Function.call.apply(Function.call, " + "[Function.call, bar]);" + "}", + "foo"); + + // Register a debug event listener which steps and counts. + v8::Debug::SetDebugEventListener(DebugEventStep); + step_action = StepIn; + + break_point_hit_count = 0; + foo->Call(env->Global(), 0, NULL); + CHECK_EQ(5, break_point_hit_count); + + v8::Debug::SetDebugEventListener(NULL); + CheckDebuggerUnloaded(); + + // Register a debug event listener which just counts. + v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount); + + break_point_hit_count = 0; + foo->Call(env->Global(), 0, NULL); + + // Without stepping only the debugger statement is hit. + CHECK_EQ(1, break_point_hit_count); + + v8::Debug::SetDebugEventListener(NULL); + CheckDebuggerUnloaded(); +} + + // Tests that breakpoint will be hit if it's set in script. TEST(PauseInScript) { DebugLocalContext env; @@ -3856,6 +3834,13 @@ TEST(PauseInScript) { } +static void DebugEventCounterCheck(int caught, int uncaught, int message) { + CHECK_EQ(caught, exception_hit_count); + CHECK_EQ(uncaught, uncaught_exception_hit_count); + CHECK_EQ(message, message_callback_count); +} + + // Test break on exceptions. For each exception break combination the number // of debug event exception callbacks and message callbacks are collected. The // number of debug event exception callbacks are used to check that the @@ -3875,6 +3860,15 @@ TEST(BreakOnException) { "caught"); v8::Local<v8::Function> notCaught = CompileFunction(&env, "function notCaught(){throws();}", "notCaught"); + v8::Local<v8::Function> notCaughtFinally = CompileFunction( + &env, "function notCaughtFinally(){try{throws();}finally{}}", + "notCaughtFinally"); + // In this edge case, even though this finally does not propagate the + // exception, the debugger considers this uncaught, since we want to break + // at the first throw for the general case where finally implicitly rethrows. + v8::Local<v8::Function> edgeCaseFinally = CompileFunction( + &env, "function caughtFinally(){L:try{throws();}finally{break L;}}", + "caughtFinally"); v8::V8::AddMessageListener(MessageCallbackCount); v8::Debug::SetDebugEventListener(DebugEventCounter); @@ -3883,117 +3877,117 @@ TEST(BreakOnException) { DebugEventCounterClear(); MessageCallbackCountClear(); caught->Call(env->Global(), 0, NULL); - CHECK_EQ(0, exception_hit_count); - CHECK_EQ(0, uncaught_exception_hit_count); - CHECK_EQ(0, message_callback_count); + DebugEventCounterCheck(0, 0, 0); notCaught->Call(env->Global(), 0, NULL); - CHECK_EQ(0, exception_hit_count); - CHECK_EQ(0, uncaught_exception_hit_count); - CHECK_EQ(1, message_callback_count); + DebugEventCounterCheck(0, 0, 1); + notCaughtFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(0, 0, 2); + edgeCaseFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(0, 0, 2); // No break on exception DebugEventCounterClear(); MessageCallbackCountClear(); ChangeBreakOnException(false, false); caught->Call(env->Global(), 0, NULL); - CHECK_EQ(0, exception_hit_count); - CHECK_EQ(0, uncaught_exception_hit_count); - CHECK_EQ(0, message_callback_count); + DebugEventCounterCheck(0, 0, 0); notCaught->Call(env->Global(), 0, NULL); - CHECK_EQ(0, exception_hit_count); - CHECK_EQ(0, uncaught_exception_hit_count); - CHECK_EQ(1, message_callback_count); + DebugEventCounterCheck(0, 0, 1); + notCaughtFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(0, 0, 2); + edgeCaseFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(0, 0, 2); // Break on uncaught exception DebugEventCounterClear(); MessageCallbackCountClear(); ChangeBreakOnException(false, true); caught->Call(env->Global(), 0, NULL); - CHECK_EQ(0, exception_hit_count); - CHECK_EQ(0, uncaught_exception_hit_count); - CHECK_EQ(0, message_callback_count); + DebugEventCounterCheck(0, 0, 0); notCaught->Call(env->Global(), 0, NULL); - CHECK_EQ(1, exception_hit_count); - CHECK_EQ(1, uncaught_exception_hit_count); - CHECK_EQ(1, message_callback_count); + DebugEventCounterCheck(1, 1, 1); + notCaughtFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(2, 2, 2); + edgeCaseFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(3, 3, 2); // Break on exception and uncaught exception DebugEventCounterClear(); MessageCallbackCountClear(); ChangeBreakOnException(true, true); caught->Call(env->Global(), 0, NULL); - CHECK_EQ(1, exception_hit_count); - CHECK_EQ(0, uncaught_exception_hit_count); - CHECK_EQ(0, message_callback_count); + DebugEventCounterCheck(1, 0, 0); notCaught->Call(env->Global(), 0, NULL); - CHECK_EQ(2, exception_hit_count); - CHECK_EQ(1, uncaught_exception_hit_count); - CHECK_EQ(1, message_callback_count); + DebugEventCounterCheck(2, 1, 1); + notCaughtFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(3, 2, 2); + edgeCaseFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(4, 3, 2); // Break on exception DebugEventCounterClear(); MessageCallbackCountClear(); ChangeBreakOnException(true, false); caught->Call(env->Global(), 0, NULL); - CHECK_EQ(1, exception_hit_count); - CHECK_EQ(0, uncaught_exception_hit_count); - CHECK_EQ(0, message_callback_count); + DebugEventCounterCheck(1, 0, 0); notCaught->Call(env->Global(), 0, NULL); - CHECK_EQ(2, exception_hit_count); - CHECK_EQ(1, uncaught_exception_hit_count); - CHECK_EQ(1, message_callback_count); + DebugEventCounterCheck(2, 1, 1); + notCaughtFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(3, 2, 2); + edgeCaseFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(4, 3, 2); // No break on exception using JavaScript DebugEventCounterClear(); MessageCallbackCountClear(); ChangeBreakOnExceptionFromJS(env->GetIsolate(), false, false); caught->Call(env->Global(), 0, NULL); - CHECK_EQ(0, exception_hit_count); - CHECK_EQ(0, uncaught_exception_hit_count); - CHECK_EQ(0, message_callback_count); + DebugEventCounterCheck(0, 0, 0); notCaught->Call(env->Global(), 0, NULL); - CHECK_EQ(0, exception_hit_count); - CHECK_EQ(0, uncaught_exception_hit_count); - CHECK_EQ(1, message_callback_count); + DebugEventCounterCheck(0, 0, 1); + notCaughtFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(0, 0, 2); + edgeCaseFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(0, 0, 2); // Break on uncaught exception using JavaScript DebugEventCounterClear(); MessageCallbackCountClear(); ChangeBreakOnExceptionFromJS(env->GetIsolate(), false, true); caught->Call(env->Global(), 0, NULL); - CHECK_EQ(0, exception_hit_count); - CHECK_EQ(0, uncaught_exception_hit_count); - CHECK_EQ(0, message_callback_count); + DebugEventCounterCheck(0, 0, 0); notCaught->Call(env->Global(), 0, NULL); - CHECK_EQ(1, exception_hit_count); - CHECK_EQ(1, uncaught_exception_hit_count); - CHECK_EQ(1, message_callback_count); + DebugEventCounterCheck(1, 1, 1); + notCaughtFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(2, 2, 2); + edgeCaseFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(3, 3, 2); // Break on exception and uncaught exception using JavaScript DebugEventCounterClear(); MessageCallbackCountClear(); ChangeBreakOnExceptionFromJS(env->GetIsolate(), true, true); caught->Call(env->Global(), 0, NULL); - CHECK_EQ(1, exception_hit_count); - CHECK_EQ(0, message_callback_count); - CHECK_EQ(0, uncaught_exception_hit_count); + DebugEventCounterCheck(1, 0, 0); notCaught->Call(env->Global(), 0, NULL); - CHECK_EQ(2, exception_hit_count); - CHECK_EQ(1, uncaught_exception_hit_count); - CHECK_EQ(1, message_callback_count); + DebugEventCounterCheck(2, 1, 1); + notCaughtFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(3, 2, 2); + edgeCaseFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(4, 3, 2); // Break on exception using JavaScript DebugEventCounterClear(); MessageCallbackCountClear(); ChangeBreakOnExceptionFromJS(env->GetIsolate(), true, false); caught->Call(env->Global(), 0, NULL); - CHECK_EQ(1, exception_hit_count); - CHECK_EQ(0, uncaught_exception_hit_count); - CHECK_EQ(0, message_callback_count); + DebugEventCounterCheck(1, 0, 0); notCaught->Call(env->Global(), 0, NULL); - CHECK_EQ(2, exception_hit_count); - CHECK_EQ(1, uncaught_exception_hit_count); - CHECK_EQ(1, message_callback_count); + DebugEventCounterCheck(2, 1, 1); + notCaughtFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(3, 2, 2); + edgeCaseFinally->Call(env->Global(), 0, NULL); + DebugEventCounterCheck(4, 3, 2); v8::Debug::SetDebugEventListener(NULL); CheckDebuggerUnloaded(); @@ -4001,6 +3995,35 @@ TEST(BreakOnException) { } +static void try_finally_original_message(v8::Handle<v8::Message> message, + v8::Handle<v8::Value> data) { + CHECK_EQ(2, message->GetLineNumber()); + CHECK_EQ(2, message->GetStartColumn()); + message_callback_count++; +} + + +TEST(TryFinallyOriginalMessage) { + // Test that the debugger plays nicely with the pending message. + message_callback_count = 0; + DebugEventCounterClear(); + v8::V8::AddMessageListener(try_finally_original_message); + v8::Debug::SetDebugEventListener(DebugEventCounter); + ChangeBreakOnException(true, true); + DebugLocalContext env; + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + CompileRun( + "try {\n" + " throw 1;\n" + "} finally {\n" + "}\n"); + DebugEventCounterCheck(1, 1, 1); + v8::Debug::SetDebugEventListener(NULL); + v8::V8::RemoveMessageListeners(try_finally_original_message); +} + + TEST(EvalJSInDebugEventListenerOnNativeReThrownException) { DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -4023,7 +4046,7 @@ TEST(EvalJSInDebugEventListenerOnNativeReThrownException) { // ReThrow native error { - v8::TryCatch tryCatch; + v8::TryCatch tryCatch(env->GetIsolate()); env->GetIsolate()->ThrowException(v8::Exception::TypeError( v8::String::NewFromUtf8(env->GetIsolate(), "Type error"))); CHECK(tryCatch.HasCaught()); @@ -5532,11 +5555,6 @@ TEST(RecursiveBreakpointsGlobal) { } -static void DummyDebugEventListener( - const v8::Debug::EventDetails& event_details) { -} - - TEST(SetDebugEventListenerOnUninitializedVM) { v8::Debug::SetDebugEventListener(DummyDebugEventListener); } @@ -5602,7 +5620,7 @@ static void CheckDataParameter( CHECK(v8::Debug::Call(debugger_call_with_data, data)->IsString()); for (int i = 0; i < 3; i++) { - v8::TryCatch catcher; + v8::TryCatch catcher(args.GetIsolate()); CHECK(v8::Debug::Call(debugger_call_with_data).IsEmpty()); CHECK(catcher.HasCaught()); CHECK(catcher.Exception()->IsString()); @@ -5910,7 +5928,7 @@ TEST(DebugGetLoadedScripts) { v8::String::NewExternal(env->GetIsolate(), &source_ext_str); v8::Handle<v8::Script> evil_script(v8::Script::Compile(source)); // "use" evil_script to make the compiler happy. - (void) evil_script; + USE(evil_script); Handle<i::ExternalTwoByteString> i_source( i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source))); // This situation can happen if source was an external string disposed @@ -5919,12 +5937,23 @@ TEST(DebugGetLoadedScripts) { bool allow_natives_syntax = i::FLAG_allow_natives_syntax; i::FLAG_allow_natives_syntax = true; - CompileRun( - "var scripts = %DebugGetLoadedScripts();" - "var count = scripts.length;" - "for (var i = 0; i < count; ++i) {" - " scripts[i].line_ends;" - "}"); + EnableDebugger(); + v8::MaybeLocal<v8::Value> result = + CompileRun(env.context(), + "var scripts = %DebugGetLoadedScripts();" + "var count = scripts.length;" + "for (var i = 0; i < count; ++i) {" + " var lines = scripts[i].lineCount();" + " if (lines < 1) throw 'lineCount';" + " var last = -1;" + " for (var j = 0; j < lines; ++j) {" + " var end = scripts[i].lineEnd(j);" + " if (last >= end) throw 'lineEnd';" + " last = end;" + " }" + "}"); + CHECK(!result.IsEmpty()); + DisableDebugger(); // Must not crash while accessing line_ends. i::FLAG_allow_natives_syntax = allow_natives_syntax; @@ -6492,6 +6521,8 @@ TEST(ProvisionalBreakpointOnLineOutOfRange) { const char* script = "function f() {};"; const char* resource_name = "test_resource"; + v8::Debug::SetMessageHandler(AfterCompileMessageHandler); + // Set a couple of provisional breakpoint on lines out of the script lines // range. int sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), resource_name, @@ -6500,7 +6531,6 @@ TEST(ProvisionalBreakpointOnLineOutOfRange) { SetScriptBreakPointByNameFromJS(env->GetIsolate(), resource_name, 5, 5); after_compile_message_count = 0; - v8::Debug::SetMessageHandler(AfterCompileMessageHandler); v8::ScriptOrigin origin( v8::String::NewFromUtf8(env->GetIsolate(), resource_name), @@ -6925,6 +6955,13 @@ TEST(DebugContextIsPreservedBetweenAccesses) { } +TEST(NoDebugContextWhenDebuggerDisabled) { + v8::HandleScope scope(CcTest::isolate()); + v8::Local<v8::Context> context = v8::Debug::GetDebugContext(); + CHECK(context.IsEmpty()); +} + + static v8::Handle<v8::Value> expected_callback_data; static void DebugEventContextChecker(const v8::Debug::EventDetails& details) { CHECK(details.GetEventContext() == expected_context); @@ -7260,7 +7297,7 @@ static void DebugEventStepNext( static void RunScriptInANewCFrame(const char* source) { - v8::TryCatch try_catch; + v8::TryCatch try_catch(CcTest::isolate()); CompileRun(source); CHECK(try_catch.HasCaught()); } @@ -7440,7 +7477,7 @@ TEST(DebugBreakOffThreadTerminate) { v8::Debug::SetDebugEventListener(DebugBreakTriggerTerminate); TerminationThread terminator(isolate); terminator.Start(); - v8::TryCatch try_catch; + v8::TryCatch try_catch(env->GetIsolate()); v8::Debug::DebugBreak(isolate); CompileRun("while (true);"); CHECK(try_catch.HasTerminated()); @@ -7456,7 +7493,7 @@ static void DebugEventExpectNoException( static void TryCatchWrappedThrowCallback( const v8::FunctionCallbackInfo<v8::Value>& args) { - v8::TryCatch try_catch; + v8::TryCatch try_catch(args.GetIsolate()); CompileRun("throw 'rejection';"); CHECK(try_catch.HasCaught()); } diff --git a/deps/v8/test/cctest/test-decls.cc b/deps/v8/test/cctest/test-decls.cc index f3dc777102..347ca9a6bc 100644 --- a/deps/v8/test/cctest/test-decls.cc +++ b/deps/v8/test/cctest/test-decls.cc @@ -130,6 +130,10 @@ void DeclarationContext::InitializeIfNeeded() { context_.Reset(isolate, context); context->Enter(); is_initialized_ = true; + // Reset counts. Bootstrapping might have called into the interceptor. + get_count_ = 0; + set_count_ = 0; + query_count_ = 0; PostInitializeContext(context); } @@ -143,7 +147,7 @@ void DeclarationContext::Check(const char* source, // to avoid that. CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE); HandleScope scope(CcTest::isolate()); - TryCatch catcher; + TryCatch catcher(CcTest::isolate()); catcher.SetVerbose(true); Local<Script> script = Script::Compile(String::NewFromUtf8(CcTest::isolate(), source)); @@ -567,7 +571,7 @@ class SimpleContext { Expectations expectations, v8::Handle<Value> value = Local<Value>()) { HandleScope scope(context_->GetIsolate()); - TryCatch catcher; + TryCatch catcher(context_->GetIsolate()); catcher.SetVerbose(true); Local<Script> script = Script::Compile(String::NewFromUtf8(context_->GetIsolate(), source)); diff --git a/deps/v8/test/cctest/test-deoptimization.cc b/deps/v8/test/cctest/test-deoptimization.cc index 674291524d..1d512e0a75 100644 --- a/deps/v8/test/cctest/test-deoptimization.cc +++ b/deps/v8/test/cctest/test-deoptimization.cc @@ -112,8 +112,6 @@ static Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj, TEST(DeoptimizeSimple) { - i::FLAG_turbo_deoptimization = true; - LocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -152,8 +150,6 @@ TEST(DeoptimizeSimple) { TEST(DeoptimizeSimpleWithArguments) { - i::FLAG_turbo_deoptimization = true; - LocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -193,8 +189,6 @@ TEST(DeoptimizeSimpleWithArguments) { TEST(DeoptimizeSimpleNested) { - i::FLAG_turbo_deoptimization = true; - LocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -220,7 +214,6 @@ TEST(DeoptimizeSimpleNested) { TEST(DeoptimizeRecursive) { - i::FLAG_turbo_deoptimization = true; LocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -248,7 +241,6 @@ TEST(DeoptimizeRecursive) { TEST(DeoptimizeMultiple) { - i::FLAG_turbo_deoptimization = true; LocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -277,7 +269,6 @@ TEST(DeoptimizeMultiple) { TEST(DeoptimizeConstructor) { - i::FLAG_turbo_deoptimization = true; LocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -316,7 +307,6 @@ TEST(DeoptimizeConstructor) { TEST(DeoptimizeConstructorMultiple) { - i::FLAG_turbo_deoptimization = true; LocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -346,7 +336,6 @@ TEST(DeoptimizeConstructorMultiple) { UNINITIALIZED_TEST(DeoptimizeBinaryOperationADDString) { - i::FLAG_turbo_deoptimization = true; i::FLAG_concurrent_recompilation = false; AllowNativesSyntaxNoInlining options; v8::Isolate::CreateParams create_params; @@ -451,7 +440,6 @@ static void TestDeoptimizeBinaryOpHelper(LocalContext* env, UNINITIALIZED_TEST(DeoptimizeBinaryOperationADD) { - i::FLAG_turbo_deoptimization = true; i::FLAG_concurrent_recompilation = false; v8::Isolate::CreateParams create_params; create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); @@ -474,7 +462,6 @@ UNINITIALIZED_TEST(DeoptimizeBinaryOperationADD) { UNINITIALIZED_TEST(DeoptimizeBinaryOperationSUB) { - i::FLAG_turbo_deoptimization = true; i::FLAG_concurrent_recompilation = false; v8::Isolate::CreateParams create_params; create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); @@ -497,7 +484,6 @@ UNINITIALIZED_TEST(DeoptimizeBinaryOperationSUB) { UNINITIALIZED_TEST(DeoptimizeBinaryOperationMUL) { - i::FLAG_turbo_deoptimization = true; i::FLAG_concurrent_recompilation = false; v8::Isolate::CreateParams create_params; create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); @@ -520,7 +506,6 @@ UNINITIALIZED_TEST(DeoptimizeBinaryOperationMUL) { UNINITIALIZED_TEST(DeoptimizeBinaryOperationDIV) { - i::FLAG_turbo_deoptimization = true; i::FLAG_concurrent_recompilation = false; v8::Isolate::CreateParams create_params; create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); @@ -543,7 +528,6 @@ UNINITIALIZED_TEST(DeoptimizeBinaryOperationDIV) { UNINITIALIZED_TEST(DeoptimizeBinaryOperationMOD) { - i::FLAG_turbo_deoptimization = true; i::FLAG_concurrent_recompilation = false; v8::Isolate::CreateParams create_params; create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); @@ -566,7 +550,6 @@ UNINITIALIZED_TEST(DeoptimizeBinaryOperationMOD) { UNINITIALIZED_TEST(DeoptimizeCompare) { - i::FLAG_turbo_deoptimization = true; i::FLAG_concurrent_recompilation = false; v8::Isolate::CreateParams create_params; create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); @@ -623,7 +606,6 @@ UNINITIALIZED_TEST(DeoptimizeCompare) { UNINITIALIZED_TEST(DeoptimizeLoadICStoreIC) { - i::FLAG_turbo_deoptimization = true; i::FLAG_concurrent_recompilation = false; v8::Isolate::CreateParams create_params; create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); @@ -716,7 +698,6 @@ UNINITIALIZED_TEST(DeoptimizeLoadICStoreIC) { UNINITIALIZED_TEST(DeoptimizeLoadICStoreICNested) { - i::FLAG_turbo_deoptimization = true; i::FLAG_concurrent_recompilation = false; v8::Isolate::CreateParams create_params; create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); diff --git a/deps/v8/test/cctest/test-disasm-arm64.cc b/deps/v8/test/cctest/test-disasm-arm64.cc index 208f1f5afb..b3b50acf9d 100644 --- a/deps/v8/test/cctest/test-disasm-arm64.cc +++ b/deps/v8/test/cctest/test-disasm-arm64.cc @@ -83,10 +83,11 @@ using namespace v8::internal; abort(); \ } -#define CLEANUP() \ - delete disasm; \ - delete decoder; \ - delete assm +#define CLEANUP() \ + delete disasm; \ + delete decoder; \ + delete assm; \ + free(buf) static bool vm_initialized = false; diff --git a/deps/v8/test/cctest/test-disasm-mips.cc b/deps/v8/test/cctest/test-disasm-mips.cc index b66554e55e..c04cd23bf5 100644 --- a/deps/v8/test/cctest/test-disasm-mips.cc +++ b/deps/v8/test/cctest/test-disasm-mips.cc @@ -92,6 +92,45 @@ if (failure) { \ } +#define COMPARE_PC_REL_COMPACT(asm_, compare_string, offset) \ + { \ + int pc_offset = assm.pc_offset(); \ + byte *progcounter = &buffer[pc_offset]; \ + char str_with_address[100]; \ + snprintf(str_with_address, sizeof(str_with_address), "%s -> %p", \ + compare_string, progcounter + 4 + (offset << 2)); \ + assm.asm_; \ + if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \ + } + + +#define COMPARE_PC_REL(asm_, compare_string, offset) \ + { \ + int pc_offset = assm.pc_offset(); \ + byte *progcounter = &buffer[pc_offset]; \ + char str_with_address[100]; \ + snprintf(str_with_address, sizeof(str_with_address), "%s -> %p", \ + compare_string, progcounter + (offset << 2)); \ + assm.asm_; \ + if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \ + } + + +#define COMPARE_PC_JUMP(asm_, compare_string, target) \ + { \ + int pc_offset = assm.pc_offset(); \ + byte *progcounter = &buffer[pc_offset]; \ + char str_with_address[100]; \ + int instr_index = target >> 2; \ + snprintf(str_with_address, sizeof(str_with_address), "%s -> %p", \ + compare_string, reinterpret_cast<byte *>( \ + ((uint32_t)(progcounter + 1) & ~0xfffffff) | \ + (instr_index << 2))); \ + assm.asm_; \ + if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \ + } + + TEST(Type0) { SET_UP(); @@ -199,39 +238,241 @@ TEST(Type0) { COMPARE(modu(v0, v1, a0), "006410db modu v0, v1, a0"); - COMPARE(bovc(a0, a0, static_cast<int16_t>(0)), - "20840000 bovc a0, a0, 0"); - COMPARE(bovc(a1, a0, static_cast<int16_t>(0)), - "20a40000 bovc a1, a0, 0"); - COMPARE(bovc(a1, a0, 32767), - "20a47fff bovc a1, a0, 32767"); - COMPARE(bovc(a1, a0, -32768), - "20a48000 bovc a1, a0, -32768"); - - COMPARE(bnvc(a0, a0, static_cast<int16_t>(0)), - "60840000 bnvc a0, a0, 0"); - COMPARE(bnvc(a1, a0, static_cast<int16_t>(0)), - "60a40000 bnvc a1, a0, 0"); - COMPARE(bnvc(a1, a0, 32767), - "60a47fff bnvc a1, a0, 32767"); - COMPARE(bnvc(a1, a0, -32768), - "60a48000 bnvc a1, a0, -32768"); - - COMPARE(beqzc(a0, 0), - "d8800000 beqzc a0, 0x0"); - COMPARE(beqzc(a0, 0xfffff), // 0x0fffff == 1048575. - "d88fffff beqzc a0, 0xfffff"); - COMPARE(beqzc(a0, 0x100000), // 0x100000 == -1048576. - "d8900000 beqzc a0, 0x100000"); - - COMPARE(bnezc(a0, 0), - "f8800000 bnezc a0, 0x0"); - COMPARE(bnezc(a0, 0xfffff), // 0x0fffff == 1048575. - "f88fffff bnezc a0, 0xfffff"); - COMPARE(bnezc(a0, 0x100000), // 0x100000 == -1048576. - "f8900000 bnezc a0, 0x100000"); + COMPARE_PC_REL_COMPACT(bovc(a0, a0, static_cast<int16_t>(0)), + "20840000 bovc a0, a0, 0", 0); + COMPARE_PC_REL_COMPACT(bovc(a1, a0, static_cast<int16_t>(0)), + "20a40000 bovc a1, a0, 0", 0); + COMPARE_PC_REL_COMPACT(bovc(a1, a0, 32767), + "20a47fff bovc a1, a0, 32767", 32767); + COMPARE_PC_REL_COMPACT(bovc(a1, a0, -32768), + "20a48000 bovc a1, a0, -32768", -32768); + + COMPARE_PC_REL_COMPACT(bnvc(a0, a0, static_cast<int16_t>(0)), + "60840000 bnvc a0, a0, 0", 0); + COMPARE_PC_REL_COMPACT(bnvc(a1, a0, static_cast<int16_t>(0)), + "60a40000 bnvc a1, a0, 0", 0); + COMPARE_PC_REL_COMPACT(bnvc(a1, a0, 32767), + "60a47fff bnvc a1, a0, 32767", 32767); + COMPARE_PC_REL_COMPACT(bnvc(a1, a0, -32768), + "60a48000 bnvc a1, a0, -32768", -32768); + + COMPARE_PC_REL_COMPACT(beqzc(a0, -1048576), + "d8900000 beqzc a0, -1048576", -1048576); + COMPARE_PC_REL_COMPACT(beqzc(a0, -1), "d89fffff beqzc a0, -1", -1); + COMPARE_PC_REL_COMPACT(beqzc(a0, 0), "d8800000 beqzc a0, 0", 0); + COMPARE_PC_REL_COMPACT(beqzc(a0, 1), "d8800001 beqzc a0, 1", 1); + COMPARE_PC_REL_COMPACT(beqzc(a0, 1048575), + "d88fffff beqzc a0, 1048575", 1048575); + + COMPARE_PC_REL_COMPACT(bnezc(a0, 0), "f8800000 bnezc a0, 0x0", 0); + COMPARE_PC_REL_COMPACT(bnezc(a0, 0xfffff), // 0x0fffff == 1048575. + "f88fffff bnezc a0, 0xfffff", 1048575); + COMPARE_PC_REL_COMPACT(bnezc(a0, 0x100000), // 0x100000 == -1048576. + "f8900000 bnezc a0, 0x100000", -1048576); + + COMPARE_PC_REL_COMPACT(bc(-33554432), "ca000000 bc -33554432", + -33554432); + COMPARE_PC_REL_COMPACT(bc(-1), "cbffffff bc -1", -1); + COMPARE_PC_REL_COMPACT(bc(0), "c8000000 bc 0", 0); + COMPARE_PC_REL_COMPACT(bc(1), "c8000001 bc 1", 1); + COMPARE_PC_REL_COMPACT(bc(33554431), "c9ffffff bc 33554431", + 33554431); + + COMPARE_PC_REL_COMPACT(balc(-33554432), "ea000000 balc -33554432", + -33554432); + COMPARE_PC_REL_COMPACT(balc(-1), "ebffffff balc -1", -1); + COMPARE_PC_REL_COMPACT(balc(0), "e8000000 balc 0", 0); + COMPARE_PC_REL_COMPACT(balc(1), "e8000001 balc 1", 1); + COMPARE_PC_REL_COMPACT(balc(33554431), "e9ffffff balc 33554431", + 33554431); + + COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, -32768), + "18858000 bgeuc a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, -1), + "1885ffff bgeuc a0, a1, -1", -1); + COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, 1), + "18850001 bgeuc a0, a1, 1", 1); + COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, 32767), + "18857fff bgeuc a0, a1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bgezalc(a0, -32768), + "18848000 bgezalc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(bgezalc(a0, -1), "1884ffff bgezalc a0, -1", + -1); + COMPARE_PC_REL_COMPACT(bgezalc(a0, 1), "18840001 bgezalc a0, 1", 1); + COMPARE_PC_REL_COMPACT(bgezalc(a0, 32767), + "18847fff bgezalc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(blezalc(a0, -32768), + "18048000 blezalc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(blezalc(a0, -1), "1804ffff blezalc a0, -1", + -1); + COMPARE_PC_REL_COMPACT(blezalc(a0, 1), "18040001 blezalc a0, 1", 1); + COMPARE_PC_REL_COMPACT(blezalc(a0, 32767), + "18047fff blezalc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bltuc(a0, a1, -32768), + "1c858000 bltuc a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bltuc(a0, a1, -1), + "1c85ffff bltuc a0, a1, -1", -1); + COMPARE_PC_REL_COMPACT(bltuc(a0, a1, 1), "1c850001 bltuc a0, a1, 1", + 1); + COMPARE_PC_REL_COMPACT(bltuc(a0, a1, 32767), + "1c857fff bltuc a0, a1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bltzalc(a0, -32768), + "1c848000 bltzalc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(bltzalc(a0, -1), "1c84ffff bltzalc a0, -1", + -1); + COMPARE_PC_REL_COMPACT(bltzalc(a0, 1), "1c840001 bltzalc a0, 1", 1); + COMPARE_PC_REL_COMPACT(bltzalc(a0, 32767), + "1c847fff bltzalc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bgtzalc(a0, -32768), + "1c048000 bgtzalc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(bgtzalc(a0, -1), "1c04ffff bgtzalc a0, -1", + -1); + COMPARE_PC_REL_COMPACT(bgtzalc(a0, 1), "1c040001 bgtzalc a0, 1", 1); + COMPARE_PC_REL_COMPACT(bgtzalc(a0, 32767), + "1c047fff bgtzalc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bgezc(a0, -32768), + "58848000 bgezc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(bgezc(a0, -1), "5884ffff bgezc a0, -1", -1); + COMPARE_PC_REL_COMPACT(bgezc(a0, 1), "58840001 bgezc a0, 1", 1); + COMPARE_PC_REL_COMPACT(bgezc(a0, 32767), + "58847fff bgezc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bgec(a0, a1, -32768), + "58858000 bgec a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bgec(a0, a1, -1), + "5885ffff bgec a0, a1, -1", -1); + COMPARE_PC_REL_COMPACT(bgec(a0, a1, 1), "58850001 bgec a0, a1, 1", + 1); + COMPARE_PC_REL_COMPACT(bgec(a0, a1, 32767), + "58857fff bgec a0, a1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(blezc(a0, -32768), + "58048000 blezc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(blezc(a0, -1), "5804ffff blezc a0, -1", -1); + COMPARE_PC_REL_COMPACT(blezc(a0, 1), "58040001 blezc a0, 1", 1); + COMPARE_PC_REL_COMPACT(blezc(a0, 32767), + "58047fff blezc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bltzc(a0, -32768), + "5c848000 bltzc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(bltzc(a0, -1), "5c84ffff bltzc a0, -1", -1); + COMPARE_PC_REL_COMPACT(bltzc(a0, 1), "5c840001 bltzc a0, 1", 1); + COMPARE_PC_REL_COMPACT(bltzc(a0, 32767), + "5c847fff bltzc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bltc(a0, a1, -32768), + "5c858000 bltc a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bltc(a0, a1, -1), + "5c85ffff bltc a0, a1, -1", -1); + COMPARE_PC_REL_COMPACT(bltc(a0, a1, 1), "5c850001 bltc a0, a1, 1", + 1); + COMPARE_PC_REL_COMPACT(bltc(a0, a1, 32767), + "5c857fff bltc a0, a1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bgtzc(a0, -32768), + "5c048000 bgtzc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(bgtzc(a0, -1), "5c04ffff bgtzc a0, -1", -1); + COMPARE_PC_REL_COMPACT(bgtzc(a0, 1), "5c040001 bgtzc a0, 1", 1); + COMPARE_PC_REL_COMPACT(bgtzc(a0, 32767), + "5c047fff bgtzc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bc1eqz(-32768, f1), + "45218000 bc1eqz f1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bc1eqz(-1, f1), "4521ffff bc1eqz f1, -1", + -1); + COMPARE_PC_REL_COMPACT(bc1eqz(1, f1), "45210001 bc1eqz f1, 1", 1); + COMPARE_PC_REL_COMPACT(bc1eqz(32767, f1), + "45217fff bc1eqz f1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bc1nez(-32768, f1), + "45a18000 bc1nez f1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bc1nez(-1, f1), "45a1ffff bc1nez f1, -1", + -1); + COMPARE_PC_REL_COMPACT(bc1nez(1, f1), "45a10001 bc1nez f1, 1", 1); + COMPARE_PC_REL_COMPACT(bc1nez(32767, f1), + "45a17fff bc1nez f1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bovc(a1, a0, -1), "20a4ffff bovc a1, a0, -1", + -1); + COMPARE_PC_REL_COMPACT(bovc(a0, a0, 1), "20840001 bovc a0, a0, 1", + 1); + + COMPARE_PC_REL_COMPACT(beqc(a0, a1, -32768), + "20858000 beqc a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(beqc(a0, a1, -1), "2085ffff beqc a0, a1, -1", + -1); + COMPARE_PC_REL_COMPACT(beqc(a0, a1, 1), "20850001 beqc a0, a1, 1", + 1); + COMPARE_PC_REL_COMPACT(beqc(a0, a1, 32767), + "20857fff beqc a0, a1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bnec(a0, a1, -32768), + "60858000 bnec a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bnec(a0, a1, -1), "6085ffff bnec a0, a1, -1", + -1); + COMPARE_PC_REL_COMPACT(bnec(a0, a1, 1), "60850001 bnec a0, a1, 1", + 1); + COMPARE_PC_REL_COMPACT(bnec(a0, a1, 32767), + "60857fff bnec a0, a1, 32767", 32767); } + COMPARE_PC_REL_COMPACT(bne(a0, a1, -32768), + "14858000 bne a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bne(a0, a1, -1), "1485ffff bne a0, a1, -1", + -1); + COMPARE_PC_REL_COMPACT(bne(a0, a1, 1), "14850001 bne a0, a1, 1", 1); + COMPARE_PC_REL_COMPACT(bne(a0, a1, 32767), + "14857fff bne a0, a1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(beq(a0, a1, -32768), + "10858000 beq a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(beq(a0, a1, -1), "1085ffff beq a0, a1, -1", + -1); + COMPARE_PC_REL_COMPACT(beq(a0, a1, 1), "10850001 beq a0, a1, 1", 1); + COMPARE_PC_REL_COMPACT(beq(a0, a1, 32767), + "10857fff beq a0, a1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bltz(a0, -32768), "04808000 bltz a0, -32768", + -32768); + COMPARE_PC_REL_COMPACT(bltz(a0, -1), "0480ffff bltz a0, -1", -1); + COMPARE_PC_REL_COMPACT(bltz(a0, 1), "04800001 bltz a0, 1", 1); + COMPARE_PC_REL_COMPACT(bltz(a0, 32767), "04807fff bltz a0, 32767", + 32767); + + COMPARE_PC_REL_COMPACT(bgez(a0, -32768), "04818000 bgez a0, -32768", + -32768); + COMPARE_PC_REL_COMPACT(bgez(a0, -1), "0481ffff bgez a0, -1", -1); + COMPARE_PC_REL_COMPACT(bgez(a0, 1), "04810001 bgez a0, 1", 1); + COMPARE_PC_REL_COMPACT(bgez(a0, 32767), "04817fff bgez a0, 32767", + 32767); + + COMPARE_PC_REL_COMPACT(blez(a0, -32768), "18808000 blez a0, -32768", + -32768); + COMPARE_PC_REL_COMPACT(blez(a0, -1), "1880ffff blez a0, -1", -1); + COMPARE_PC_REL_COMPACT(blez(a0, 1), "18800001 blez a0, 1", 1); + COMPARE_PC_REL_COMPACT(blez(a0, 32767), "18807fff blez a0, 32767", + 32767); + + COMPARE_PC_REL_COMPACT(bgtz(a0, -32768), "1c808000 bgtz a0, -32768", + -32768); + COMPARE_PC_REL_COMPACT(bgtz(a0, -1), "1c80ffff bgtz a0, -1", -1); + COMPARE_PC_REL_COMPACT(bgtz(a0, 1), "1c800001 bgtz a0, 1", 1); + COMPARE_PC_REL_COMPACT(bgtz(a0, 32767), "1c807fff bgtz a0, 32767", + 32767); + + COMPARE_PC_JUMP(j(0x4), "08000001 j 0x4", 0x4); + COMPARE_PC_JUMP(j(0xffffffc), "0bffffff j 0xffffffc", 0xffffffc); + + COMPARE_PC_JUMP(jal(0x4), "0c000001 jal 0x4", 0x4); + COMPARE_PC_JUMP(jal(0xffffffc), "0fffffff jal 0xffffffc", + 0xffffffc); + COMPARE(addiu(a0, a1, 0x0), "24a40000 addiu a0, a1, 0"); COMPARE(addiu(s0, s1, 32767), @@ -506,7 +747,7 @@ TEST(Type0) { } } - if (IsMipsArchVariant(kMips32r2)) { + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { COMPARE(ins_(a0, a1, 31, 1), "7ca4ffc4 ins a0, a1, 31, 1"); COMPARE(ins_(s6, s7, 30, 2), @@ -520,26 +761,280 @@ TEST(Type0) { COMPARE(ext_(v0, v1, 0, 32), "7c62f800 ext v0, v1, 0, 32"); } + COMPARE(add_s(f4, f6, f8), "46083100 add.s f4, f6, f8"); + COMPARE(add_d(f12, f14, f16), "46307300 add.d f12, f14, f16"); + + if (IsMipsArchVariant(kMips32r6)) { + COMPARE(bitswap(a0, a1), "7c052020 bitswap a0, a1"); + COMPARE(bitswap(t8, s0), "7c10c020 bitswap t8, s0"); + } + + COMPARE(abs_s(f6, f8), "46004185 abs.s f6, f8"); + COMPARE(abs_d(f10, f12), "46206285 abs.d f10, f12"); + + COMPARE(div_s(f2, f4, f6), "46062083 div.s f2, f4, f6"); + COMPARE(div_d(f2, f4, f6), "46262083 div.d f2, f4, f6"); + + if (IsMipsArchVariant(kMips32r6)) { + COMPARE(align(v0, a0, a1, 0), "7c851220 align v0, a0, a1, 0"); + COMPARE(align(v0, a0, a1, 1), "7c851260 align v0, a0, a1, 1"); + COMPARE(align(v0, a0, a1, 2), "7c8512a0 align v0, a0, a1, 2"); + COMPARE(align(v0, a0, a1, 3), "7c8512e0 align v0, a0, a1, 3"); + } + + if (IsMipsArchVariant(kMips32r6)) { + COMPARE(aluipc(v0, 0), "ec5f0000 aluipc v0, 0"); + COMPARE(aluipc(v0, 1), "ec5f0001 aluipc v0, 1"); + COMPARE(aluipc(v0, 32767), "ec5f7fff aluipc v0, 32767"); + COMPARE(aluipc(v0, -32768), "ec5f8000 aluipc v0, -32768"); + COMPARE(aluipc(v0, -1), "ec5fffff aluipc v0, -1"); + } + + if (IsMipsArchVariant(kMips32r6)) { + COMPARE(auipc(t8, 0), "ef1e0000 auipc t8, 0"); + COMPARE(auipc(t8, 1), "ef1e0001 auipc t8, 1"); + COMPARE(auipc(t8, 32767), "ef1e7fff auipc t8, 32767"); + COMPARE(auipc(t8, -32768), "ef1e8000 auipc t8, -32768"); + COMPARE(auipc(t8, -1), "ef1effff auipc t8, -1"); + } + + if (IsMipsArchVariant(kMips32r6)) { + COMPARE(lwpc(t1, 0), "ed280000 lwpc t1, 0"); + COMPARE(lwpc(t1, 4), "ed280004 lwpc t1, 4"); + COMPARE(lwpc(t1, -4), "ed2ffffc lwpc t1, -4"); + } + + if (IsMipsArchVariant(kMips32r6)) { + COMPARE(jic(t0, -32768), "d8088000 jic t0, -32768"); + COMPARE(jic(t0, -1), "d808ffff jic t0, -1"); + COMPARE(jic(t0, 0), "d8080000 jic t0, 0"); + COMPARE(jic(t0, 4), "d8080004 jic t0, 4"); + COMPARE(jic(t0, 32767), "d8087fff jic t0, 32767"); + } + + if (IsMipsArchVariant(kMips32r6)) { + COMPARE(addiupc(a0, 262143), "ec83ffff addiupc a0, 262143"); + COMPARE(addiupc(a0, -1), "ec87ffff addiupc a0, -1"); + COMPARE(addiupc(v0, 0), "ec400000 addiupc v0, 0"); + COMPARE(addiupc(s1, 1), "ee200001 addiupc s1, 1"); + COMPARE(addiupc(a0, -262144), "ec840000 addiupc a0, -262144"); + } + + if (IsMipsArchVariant(kMips32r6)) { + COMPARE(jialc(a0, -32768), "f8048000 jialc a0, 0x8000"); + COMPARE(jialc(a0, -1), "f804ffff jialc a0, 0xffff"); + COMPARE(jialc(v0, 0), "f8020000 jialc v0, 0x0"); + COMPARE(jialc(s1, 1), "f8110001 jialc s1, 0x1"); + COMPARE(jialc(a0, 32767), "f8047fff jialc a0, 0x7fff"); + } VERIFY_RUN(); } -// Tests only seleqz, selnez, seleqz.fmt and selnez.fmt TEST(Type1) { + SET_UP(); if (IsMipsArchVariant(kMips32r6)) { - SET_UP(); COMPARE(seleqz(a0, a1, a2), "00a62035 seleqz a0, a1, a2"); COMPARE(selnez(a0, a1, a2), "00a62037 selnez a0, a1, a2"); - COMPARE(seleqz(D, f3, f4, f5), "462520d4 seleqz.d f3, f4, f5"); - COMPARE(selnez(D, f3, f4, f5), "462520d7 selnez.d f3, f4, f5"); + COMPARE(seleqz_d(f3, f4, f5), "462520d4 seleqz.d f3, f4, f5"); + COMPARE(selnez_d(f3, f4, f5), "462520d7 selnez.d f3, f4, f5"); + COMPARE(seleqz_s(f3, f4, f5), "460520d4 seleqz.s f3, f4, f5"); + COMPARE(selnez_s(f3, f4, f5), "460520d7 selnez.s f3, f4, f5"); COMPARE(min_d(f3, f4, f5), "462520dc min.d f3, f4, f5"); COMPARE(max_d(f3, f4, f5), "462520de max.d f3, f4, f5"); + + COMPARE(sel_s(f3, f4, f5), "460520d0 sel.s f3, f4, f5"); + COMPARE(sel_d(f3, f4, f5), "462520d0 sel.d f3, f4, f5"); + COMPARE(rint_d(f8, f6), "4620321a rint.d f8, f6"); + COMPARE(rint_s(f8, f6), "4600321a rint.s f8, f6"); + + COMPARE(min_s(f3, f4, f5), "460520dc min.s f3, f4, f5"); + COMPARE(max_s(f3, f4, f5), "460520de max.s f3, f4, f5"); + + COMPARE(mina_d(f3, f4, f5), "462520dd mina.d f3, f4, f5"); + COMPARE(mina_s(f3, f4, f5), "460520dd mina.s f3, f4, f5"); + + COMPARE(maxa_d(f3, f4, f5), "462520df maxa.d f3, f4, f5"); + COMPARE(maxa_s(f3, f4, f5), "460520df maxa.s f3, f4, f5"); + } + + COMPARE(trunc_w_d(f8, f6), "4620320d trunc.w.d f8, f6"); + COMPARE(trunc_w_s(f8, f6), "4600320d trunc.w.s f8, f6"); + + COMPARE(round_w_s(f8, f6), "4600320c round.w.s f8, f6"); + COMPARE(round_w_d(f8, f6), "4620320c round.w.d f8, f6"); + + COMPARE(round_l_s(f8, f6), "46003208 round.l.s f8, f6"); + COMPARE(round_l_d(f8, f6), "46203208 round.l.d f8, f6"); + + COMPARE(floor_w_s(f8, f6), "4600320f floor.w.s f8, f6"); + COMPARE(floor_w_d(f8, f6), "4620320f floor.w.d f8, f6"); + + COMPARE(floor_l_s(f8, f6), "4600320b floor.l.s f8, f6"); + COMPARE(floor_l_d(f8, f6), "4620320b floor.l.d f8, f6"); + + COMPARE(ceil_w_s(f8, f6), "4600320e ceil.w.s f8, f6"); + COMPARE(ceil_w_d(f8, f6), "4620320e ceil.w.d f8, f6"); + + COMPARE(ceil_l_s(f8, f6), "4600320a ceil.l.s f8, f6"); + COMPARE(ceil_l_d(f8, f6), "4620320a ceil.l.d f8, f6"); + + COMPARE(sub_s(f10, f8, f6), "46064281 sub.s f10, f8, f6"); + COMPARE(sub_d(f10, f8, f6), "46264281 sub.d f10, f8, f6"); + + COMPARE(sqrt_s(f8, f6), "46003204 sqrt.s f8, f6"); + COMPARE(sqrt_d(f8, f6), "46203204 sqrt.d f8, f6"); + + COMPARE(neg_s(f8, f6), "46003207 neg.s f8, f6"); + COMPARE(neg_d(f8, f6), "46203207 neg.d f8, f6"); + + COMPARE(mul_s(f8, f6, f4), "46043202 mul.s f8, f6, f4"); + COMPARE(mul_d(f8, f6, f4), "46243202 mul.d f8, f6, f4"); + + if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { + COMPARE(rsqrt_s(f8, f6), "46003216 rsqrt.s f8, f6"); + COMPARE(rsqrt_d(f8, f6), "46203216 rsqrt.d f8, f6"); + + COMPARE(recip_s(f8, f6), "46003215 recip.s f8, f6"); + COMPARE(recip_d(f8, f6), "46203215 recip.d f8, f6"); + } + + COMPARE(mov_s(f6, f4), "46002186 mov.s f6, f4"); + COMPARE(mov_d(f6, f4), "46202186 mov.d f6, f4"); + + if (IsMipsArchVariant(kMips32r2)) { + COMPARE(trunc_l_d(f8, f6), "46203209 trunc.l.d f8, f6"); + COMPARE(trunc_l_s(f8, f6), "46003209 trunc.l.s f8, f6"); + + COMPARE(movz_s(f6, f4, t0), "46082192 movz.s f6, f4, t0"); + COMPARE(movz_d(f6, f4, t0), "46282192 movz.d f6, f4, t0"); + + COMPARE(movt_s(f6, f4, 4), "46112191 movt.s f6, f4, cc(1)"); + COMPARE(movt_d(f6, f4, 4), "46312191 movt.d f6, f4, cc(1)"); + + COMPARE(movf_s(f6, f4, 4), "46102191 movf.s f6, f4, cc(1)"); + COMPARE(movf_d(f6, f4, 4), "46302191 movf.d f6, f4, cc(1)"); + + COMPARE(movn_s(f6, f4, t0), "46082193 movn.s f6, f4, t0"); + COMPARE(movn_d(f6, f4, t0), "46282193 movn.d f6, f4, t0"); + } + VERIFY_RUN(); +} + + +TEST(Type2) { + if (IsMipsArchVariant(kMips32r6)) { + SET_UP(); + + COMPARE(class_s(f3, f4), "460020db class.s f3, f4"); + COMPARE(class_d(f2, f3), "4620189b class.d f2, f3"); + + VERIFY_RUN(); + } +} + + +TEST(C_FMT_DISASM) { + if (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2)) { + SET_UP(); + + COMPARE(c_s(F, f8, f10, 0), "460a4030 c.f.s f8, f10, cc(0)"); + COMPARE(c_d(F, f8, f10, 0), "462a4030 c.f.d f8, f10, cc(0)"); + + COMPARE(c_s(UN, f8, f10, 2), "460a4231 c.un.s f8, f10, cc(2)"); + COMPARE(c_d(UN, f8, f10, 2), "462a4231 c.un.d f8, f10, cc(2)"); + + COMPARE(c_s(EQ, f8, f10, 4), "460a4432 c.eq.s f8, f10, cc(4)"); + COMPARE(c_d(EQ, f8, f10, 4), "462a4432 c.eq.d f8, f10, cc(4)"); + + COMPARE(c_s(UEQ, f8, f10, 6), "460a4633 c.ueq.s f8, f10, cc(6)"); + COMPARE(c_d(UEQ, f8, f10, 6), "462a4633 c.ueq.d f8, f10, cc(6)"); + + COMPARE(c_s(OLT, f8, f10, 0), "460a4034 c.olt.s f8, f10, cc(0)"); + COMPARE(c_d(OLT, f8, f10, 0), "462a4034 c.olt.d f8, f10, cc(0)"); + + COMPARE(c_s(ULT, f8, f10, 2), "460a4235 c.ult.s f8, f10, cc(2)"); + COMPARE(c_d(ULT, f8, f10, 2), "462a4235 c.ult.d f8, f10, cc(2)"); + + COMPARE(c_s(OLE, f8, f10, 4), "460a4436 c.ole.s f8, f10, cc(4)"); + COMPARE(c_d(OLE, f8, f10, 4), "462a4436 c.ole.d f8, f10, cc(4)"); + + COMPARE(c_s(ULE, f8, f10, 6), "460a4637 c.ule.s f8, f10, cc(6)"); + COMPARE(c_d(ULE, f8, f10, 6), "462a4637 c.ule.d f8, f10, cc(6)"); VERIFY_RUN(); } } + + +TEST(COND_FMT_DISASM) { + if (IsMipsArchVariant(kMips32r6)) { + SET_UP(); + + COMPARE(cmp_s(F, f6, f8, f10), "468a4180 cmp.af.s f6, f8, f10"); + COMPARE(cmp_d(F, f6, f8, f10), "46aa4180 cmp.af.d f6, f8, f10"); + + COMPARE(cmp_s(UN, f6, f8, f10), "468a4181 cmp.un.s f6, f8, f10"); + COMPARE(cmp_d(UN, f6, f8, f10), "46aa4181 cmp.un.d f6, f8, f10"); + + COMPARE(cmp_s(EQ, f6, f8, f10), "468a4182 cmp.eq.s f6, f8, f10"); + COMPARE(cmp_d(EQ, f6, f8, f10), "46aa4182 cmp.eq.d f6, f8, f10"); + + COMPARE(cmp_s(UEQ, f6, f8, f10), "468a4183 cmp.ueq.s f6, f8, f10"); + COMPARE(cmp_d(UEQ, f6, f8, f10), "46aa4183 cmp.ueq.d f6, f8, f10"); + + COMPARE(cmp_s(LT, f6, f8, f10), "468a4184 cmp.lt.s f6, f8, f10"); + COMPARE(cmp_d(LT, f6, f8, f10), "46aa4184 cmp.lt.d f6, f8, f10"); + + COMPARE(cmp_s(ULT, f6, f8, f10), "468a4185 cmp.ult.s f6, f8, f10"); + COMPARE(cmp_d(ULT, f6, f8, f10), "46aa4185 cmp.ult.d f6, f8, f10"); + + COMPARE(cmp_s(LE, f6, f8, f10), "468a4186 cmp.le.s f6, f8, f10"); + COMPARE(cmp_d(LE, f6, f8, f10), "46aa4186 cmp.le.d f6, f8, f10"); + + COMPARE(cmp_s(ULE, f6, f8, f10), "468a4187 cmp.ule.s f6, f8, f10"); + COMPARE(cmp_d(ULE, f6, f8, f10), "46aa4187 cmp.ule.d f6, f8, f10"); + + COMPARE(cmp_s(ORD, f6, f8, f10), "468a4191 cmp.or.s f6, f8, f10"); + COMPARE(cmp_d(ORD, f6, f8, f10), "46aa4191 cmp.or.d f6, f8, f10"); + + COMPARE(cmp_s(UNE, f6, f8, f10), "468a4192 cmp.une.s f6, f8, f10"); + COMPARE(cmp_d(UNE, f6, f8, f10), "46aa4192 cmp.une.d f6, f8, f10"); + + COMPARE(cmp_s(NE, f6, f8, f10), "468a4193 cmp.ne.s f6, f8, f10"); + COMPARE(cmp_d(NE, f6, f8, f10), "46aa4193 cmp.ne.d f6, f8, f10"); + + VERIFY_RUN(); + } +} + + +TEST(CVT_DISSASM) { + SET_UP(); + COMPARE(cvt_d_s(f22, f24), "4600c5a1 cvt.d.s f22, f24"); + COMPARE(cvt_d_w(f22, f24), "4680c5a1 cvt.d.w f22, f24"); + if (IsMipsArchVariant(kMips32r6) || IsMipsArchVariant(kMips32r2)) { + COMPARE(cvt_d_l(f22, f24), "46a0c5a1 cvt.d.l f22, f24"); + } + + if (IsMipsArchVariant(kMips32r6) || IsMipsArchVariant(kMips32r2)) { + COMPARE(cvt_l_s(f22, f24), "4600c5a5 cvt.l.s f22, f24"); + COMPARE(cvt_l_d(f22, f24), "4620c5a5 cvt.l.d f22, f24"); + } + + COMPARE(cvt_s_d(f22, f24), "4620c5a0 cvt.s.d f22, f24"); + COMPARE(cvt_s_w(f22, f24), "4680c5a0 cvt.s.w f22, f24"); + if (IsMipsArchVariant(kMips32r6) || IsMipsArchVariant(kMips32r2)) { + COMPARE(cvt_s_l(f22, f24), "46a0c5a0 cvt.s.l f22, f24"); + } + + COMPARE(cvt_s_d(f22, f24), "4620c5a0 cvt.s.d f22, f24"); + COMPARE(cvt_s_w(f22, f24), "4680c5a0 cvt.s.w f22, f24"); + + VERIFY_RUN(); +} diff --git a/deps/v8/test/cctest/test-disasm-mips64.cc b/deps/v8/test/cctest/test-disasm-mips64.cc index 492265b2e7..225a1e7f0b 100644 --- a/deps/v8/test/cctest/test-disasm-mips64.cc +++ b/deps/v8/test/cctest/test-disasm-mips64.cc @@ -92,6 +92,45 @@ if (failure) { \ } +#define COMPARE_PC_REL_COMPACT(asm_, compare_string, offset) \ + { \ + int pc_offset = assm.pc_offset(); \ + byte *progcounter = &buffer[pc_offset]; \ + char str_with_address[100]; \ + snprintf(str_with_address, sizeof(str_with_address), "%s -> %p", \ + compare_string, progcounter + 4 + (offset << 2)); \ + assm.asm_; \ + if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \ + } + + +#define COMPARE_PC_REL(asm_, compare_string, offset) \ + { \ + int pc_offset = assm.pc_offset(); \ + byte *progcounter = &buffer[pc_offset]; \ + char str_with_address[100]; \ + snprintf(str_with_address, sizeof(str_with_address), "%s -> %p", \ + compare_string, progcounter + (offset << 2)); \ + assm.asm_; \ + if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \ + } + + +#define COMPARE_PC_JUMP(asm_, compare_string, target) \ + { \ + int pc_offset = assm.pc_offset(); \ + byte *progcounter = &buffer[pc_offset]; \ + char str_with_address[100]; \ + int instr_index = target >> 2; \ + snprintf(str_with_address, sizeof(str_with_address), "%s -> %p", \ + compare_string, reinterpret_cast<byte *>( \ + ((uint64_t)(progcounter + 1) & ~0xfffffff) | \ + (instr_index << 2))); \ + assm.asm_; \ + if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \ + } + + TEST(Type0) { SET_UP(); @@ -279,38 +318,6 @@ TEST(Type0) { "0064109f ddivu v0, v1, a0"); COMPARE(dmodu(v0, v1, a0), "006410df dmodu v0, v1, a0"); - - COMPARE(bovc(a0, a0, static_cast<int16_t>(0)), - "20840000 bovc a0, a0, 0"); - COMPARE(bovc(a1, a0, static_cast<int16_t>(0)), - "20a40000 bovc a1, a0, 0"); - COMPARE(bovc(a1, a0, 32767), - "20a47fff bovc a1, a0, 32767"); - COMPARE(bovc(a1, a0, -32768), - "20a48000 bovc a1, a0, -32768"); - - COMPARE(bnvc(a0, a0, static_cast<int16_t>(0)), - "60840000 bnvc a0, a0, 0"); - COMPARE(bnvc(a1, a0, static_cast<int16_t>(0)), - "60a40000 bnvc a1, a0, 0"); - COMPARE(bnvc(a1, a0, 32767), - "60a47fff bnvc a1, a0, 32767"); - COMPARE(bnvc(a1, a0, -32768), - "60a48000 bnvc a1, a0, -32768"); - - COMPARE(beqzc(a0, 0), - "d8800000 beqzc a0, 0x0"); - COMPARE(beqzc(a0, 0xfffff), // 0x0fffff == 1048575. - "d88fffff beqzc a0, 0xfffff"); - COMPARE(beqzc(a0, 0x100000), // 0x100000 == -1048576. - "d8900000 beqzc a0, 0x100000"); - - COMPARE(bnezc(a0, 0), - "f8800000 bnezc a0, 0x0"); - COMPARE(bnezc(a0, 0xfffff), // 0x0fffff == 1048575. - "f88fffff bnezc a0, 0xfffff"); - COMPARE(bnezc(a0, 0x100000), // 0x100000 == -1048576. - "f8900000 bnezc a0, 0x100000"); } COMPARE(addiu(a0, a1, 0x0), @@ -669,23 +676,551 @@ TEST(Type0) { COMPARE(ext_(v0, v1, 0, 32), "7c62f800 ext v0, v1, 0, 32"); + COMPARE(add_s(f4, f6, f8), "46083100 add.s f4, f6, f8"); + COMPARE(add_d(f12, f14, f16), "46307300 add.d f12, f14, f16"); + + if (kArchVariant == kMips64r6) { + COMPARE(bitswap(a0, a1), "7c052020 bitswap a0, a1"); + COMPARE(bitswap(t8, s0), "7c10c020 bitswap t8, s0"); + COMPARE(dbitswap(a0, a1), "7c052024 dbitswap a0, a1"); + COMPARE(dbitswap(t8, s0), "7c10c024 dbitswap t8, s0"); + } + + COMPARE(abs_s(f6, f8), "46004185 abs.s f6, f8"); + COMPARE(abs_d(f10, f12), "46206285 abs.d f10, f12"); + + COMPARE(div_s(f2, f4, f6), "46062083 div.s f2, f4, f6"); + COMPARE(div_d(f2, f4, f6), "46262083 div.d f2, f4, f6"); + + if (kArchVariant == kMips64r6) { + COMPARE(align(v0, a0, a1, 0), "7c851220 align v0, a0, a1, 0"); + COMPARE(align(v0, a0, a1, 1), "7c851260 align v0, a0, a1, 1"); + COMPARE(align(v0, a0, a1, 2), "7c8512a0 align v0, a0, a1, 2"); + COMPARE(align(v0, a0, a1, 3), "7c8512e0 align v0, a0, a1, 3"); + } + + if (kArchVariant == kMips64r6) { + COMPARE(dalign(v0, a0, a1, 0), "7c851224 dalign v0, a0, a1, 0"); + COMPARE(dalign(v0, a0, a1, 1), "7c851264 dalign v0, a0, a1, 1"); + COMPARE(dalign(v0, a0, a1, 2), "7c8512a4 dalign v0, a0, a1, 2"); + COMPARE(dalign(v0, a0, a1, 3), "7c8512e4 dalign v0, a0, a1, 3"); + COMPARE(dalign(v0, a0, a1, 4), "7c851324 dalign v0, a0, a1, 4"); + COMPARE(dalign(v0, a0, a1, 5), "7c851364 dalign v0, a0, a1, 5"); + COMPARE(dalign(v0, a0, a1, 6), "7c8513a4 dalign v0, a0, a1, 6"); + COMPARE(dalign(v0, a0, a1, 7), "7c8513e4 dalign v0, a0, a1, 7"); + } + + if (kArchVariant == kMips64r6) { + COMPARE(aluipc(v0, 0), "ec5f0000 aluipc v0, 0"); + COMPARE(aluipc(v0, 1), "ec5f0001 aluipc v0, 1"); + COMPARE(aluipc(v0, 32767), "ec5f7fff aluipc v0, 32767"); + COMPARE(aluipc(v0, -32768), "ec5f8000 aluipc v0, -32768"); + COMPARE(aluipc(v0, -1), "ec5fffff aluipc v0, -1"); + } + + if (kArchVariant == kMips64r6) { + COMPARE(auipc(t8, 0), "ef1e0000 auipc t8, 0"); + COMPARE(auipc(t8, 1), "ef1e0001 auipc t8, 1"); + COMPARE(auipc(t8, 32767), "ef1e7fff auipc t8, 32767"); + COMPARE(auipc(t8, -32768), "ef1e8000 auipc t8, -32768"); + COMPARE(auipc(t8, -1), "ef1effff auipc t8, -1"); + } + + if (kArchVariant == kMips64r6) { + COMPARE(lwpc(a5, 0), "ed280000 lwpc a5, 0"); + COMPARE(lwpc(a5, 4), "ed280004 lwpc a5, 4"); + COMPARE(lwpc(a5, -4), "ed2ffffc lwpc a5, -4"); + } + + if (kArchVariant == kMips64r6) { + COMPARE(lwupc(a0, -262144), "ec940000 lwupc a0, -262144"); + COMPARE(lwupc(a0, -1), "ec97ffff lwupc a0, -1"); + COMPARE(lwupc(a0, 0), "ec900000 lwupc a0, 0"); + COMPARE(lwupc(a0, 1), "ec900001 lwupc a0, 1"); + COMPARE(lwupc(a0, 262143), "ec93ffff lwupc a0, 262143"); + } + + if (kArchVariant == kMips64r6) { + COMPARE(jic(t0, 16), "d80c0010 jic t0, 16"); + COMPARE(jic(t0, 4), "d80c0004 jic t0, 4"); + COMPARE(jic(t0, -32), "d80cffe0 jic t0, -32"); + } + + if (kArchVariant == kMips64r6) { + COMPARE_PC_REL_COMPACT(beqzc(a0, 16), "d8800010 beqzc a0, 0x10", + 16); + COMPARE_PC_REL_COMPACT(beqzc(a0, 4), "d8800004 beqzc a0, 0x4", 4); + COMPARE_PC_REL_COMPACT(beqzc(a0, -32), + "d89fffe0 beqzc a0, 0x1fffe0", -32); + } + + if (kArchVariant == kMips64r6) { + COMPARE(ldpc(v0, 256), "ec580100 ldpc v0, 256"); + COMPARE(ldpc(a0, -1), "ec9bffff ldpc a0, -1"); + COMPARE(ldpc(a1, 0), "ecb80000 ldpc a1, 0"); + } + + if (kArchVariant == kMips64r6) { + COMPARE(addiupc(a0, 262143), "ec83ffff addiupc a0, 262143"); + COMPARE(addiupc(a0, -1), "ec87ffff addiupc a0, -1"); + COMPARE(addiupc(v0, 0), "ec400000 addiupc v0, 0"); + COMPARE(addiupc(s1, 1), "ee200001 addiupc s1, 1"); + COMPARE(addiupc(a0, -262144), "ec840000 addiupc a0, -262144"); + } + + if (kArchVariant == kMips64r6) { + COMPARE(jialc(a0, -32768), "f8048000 jialc a0, 0x8000"); + COMPARE(jialc(a0, -1), "f804ffff jialc a0, 0xffff"); + COMPARE(jialc(v0, 0), "f8020000 jialc v0, 0x0"); + COMPARE(jialc(s1, 1), "f8110001 jialc s1, 0x1"); + COMPARE(jialc(a0, 32767), "f8047fff jialc a0, 0x7fff"); + } + VERIFY_RUN(); } TEST(Type1) { + SET_UP(); if (kArchVariant == kMips64r6) { - SET_UP(); COMPARE(seleqz(a0, a1, a2), "00a62035 seleqz a0, a1, a2"); COMPARE(selnez(a0, a1, a2), "00a62037 selnez a0, a1, a2"); COMPARE(seleqz(D, f3, f4, f5), "462520d4 seleqz.d f3, f4, f5"); COMPARE(selnez(D, f3, f4, f5), "462520d7 selnez.d f3, f4, f5"); + COMPARE(seleqz(S, f3, f4, f5), "460520d4 seleqz.s f3, f4, f5"); + COMPARE(selnez(S, f3, f4, f5), "460520d7 selnez.s f3, f4, f5"); COMPARE(min_d(f3, f4, f5), "462520dc min.d f3, f4, f5"); COMPARE(max_d(f3, f4, f5), "462520de max.d f3, f4, f5"); + + COMPARE(sel(S, f3, f4, f5), "460520d0 sel.s f3, f4, f5"); + COMPARE(sel(D, f3, f4, f5), "462520d0 sel.d f3, f4, f5"); + COMPARE(rint_d(f8, f6), "4620321a rint.d f8, f6"); + + COMPARE(min_s(f3, f4, f5), "460520dc min.s f3, f4, f5"); + COMPARE(max_s(f3, f4, f5), "460520de max.s f3, f4, f5"); + + COMPARE(rint(S, f8, f6), "4600321a rint.s f8, f6"); + + COMPARE(mina_d(f3, f4, f5), "462520dd mina.d f3, f4, f5"); + COMPARE(mina_s(f3, f4, f5), "460520dd mina.s f3, f4, f5"); + + COMPARE(maxa_d(f3, f4, f5), "462520df maxa.d f3, f4, f5"); + COMPARE(maxa_s(f3, f4, f5), "460520df maxa.s f3, f4, f5"); + } + COMPARE(trunc_w_d(f8, f6), "4620320d trunc.w.d f8, f6"); + COMPARE(trunc_w_s(f8, f6), "4600320d trunc.w.s f8, f6"); + + COMPARE(round_w_s(f8, f6), "4600320c round.w.s f8, f6"); + COMPARE(round_w_d(f8, f6), "4620320c round.w.d f8, f6"); + + COMPARE(round_l_s(f8, f6), "46003208 round.l.s f8, f6"); + COMPARE(round_l_d(f8, f6), "46203208 round.l.d f8, f6"); + + COMPARE(floor_w_s(f8, f6), "4600320f floor.w.s f8, f6"); + COMPARE(floor_w_d(f8, f6), "4620320f floor.w.d f8, f6"); + + COMPARE(floor_l_s(f8, f6), "4600320b floor.l.s f8, f6"); + COMPARE(floor_l_d(f8, f6), "4620320b floor.l.d f8, f6"); + + COMPARE(ceil_w_s(f8, f6), "4600320e ceil.w.s f8, f6"); + COMPARE(ceil_w_d(f8, f6), "4620320e ceil.w.d f8, f6"); + + COMPARE(ceil_l_s(f8, f6), "4600320a ceil.l.s f8, f6"); + COMPARE(ceil_l_d(f8, f6), "4620320a ceil.l.d f8, f6"); + + COMPARE(sub_s(f10, f8, f6), "46064281 sub.s f10, f8, f6"); + COMPARE(sub_d(f10, f8, f6), "46264281 sub.d f10, f8, f6"); + + COMPARE(sqrt_s(f8, f6), "46003204 sqrt.s f8, f6"); + COMPARE(sqrt_d(f8, f6), "46203204 sqrt.d f8, f6"); + + COMPARE(neg_s(f8, f6), "46003207 neg.s f8, f6"); + COMPARE(neg_d(f8, f6), "46203207 neg.d f8, f6"); + + COMPARE(mul_s(f8, f6, f4), "46043202 mul.s f8, f6, f4"); + COMPARE(mul_d(f8, f6, f4), "46243202 mul.d f8, f6, f4"); + + COMPARE(rsqrt_s(f8, f6), "46003216 rsqrt.s f8, f6"); + COMPARE(rsqrt_d(f8, f6), "46203216 rsqrt.d f8, f6"); + + COMPARE(recip_s(f8, f6), "46003215 recip.s f8, f6"); + COMPARE(recip_d(f8, f6), "46203215 recip.d f8, f6"); + + COMPARE(mov_s(f6, f4), "46002186 mov.s f6, f4"); + COMPARE(mov_d(f6, f4), "46202186 mov.d f6, f4"); + if (kArchVariant == kMips64r2) { + COMPARE(trunc_l_d(f8, f6), "46203209 trunc.l.d f8, f6"); + COMPARE(trunc_l_s(f8, f6), "46003209 trunc.l.s f8, f6"); + + COMPARE(movz_s(f6, f4, t0), "460c2192 movz.s f6, f4, t0"); + COMPARE(movz_d(f6, f4, t0), "462c2192 movz.d f6, f4, t0"); + + COMPARE(movt_s(f6, f4, 4), "46112191 movt.s f6, f4, cc(1)"); + COMPARE(movt_d(f6, f4, 4), "46312191 movt.d f6, f4, cc(1)"); + + COMPARE(movf_s(f6, f4, 4), "46102191 movf.s f6, f4, cc(1)"); + COMPARE(movf_d(f6, f4, 4), "46302191 movf.d f6, f4, cc(1)"); + + COMPARE(movn_s(f6, f4, t0), "460c2193 movn.s f6, f4, t0"); + COMPARE(movn_d(f6, f4, t0), "462c2193 movn.d f6, f4, t0"); + } + VERIFY_RUN(); +} + + +TEST(Type2) { + if (kArchVariant == kMips64r6) { + SET_UP(); + + COMPARE(class_s(f3, f4), "460020db class.s f3, f4"); + COMPARE(class_d(f2, f3), "4620189b class.d f2, f3"); + VERIFY_RUN(); } } + + +TEST(Type3) { + SET_UP(); + + if (kArchVariant == kMips64r6) { + COMPARE_PC_REL_COMPACT(bovc(a0, a0, static_cast<int16_t>(0)), + "20840000 bovc a0, a0, 0", 0); + COMPARE_PC_REL_COMPACT(bovc(a1, a0, static_cast<int16_t>(0)), + "20a40000 bovc a1, a0, 0", 0); + COMPARE_PC_REL_COMPACT(bovc(a1, a0, 32767), + "20a47fff bovc a1, a0, 32767", 32767); + COMPARE_PC_REL_COMPACT(bovc(a1, a0, -32768), + "20a48000 bovc a1, a0, -32768", -32768); + + COMPARE_PC_REL_COMPACT(bnvc(a0, a0, static_cast<int16_t>(0)), + "60840000 bnvc a0, a0, 0", 0); + COMPARE_PC_REL_COMPACT(bnvc(a1, a0, static_cast<int16_t>(0)), + "60a40000 bnvc a1, a0, 0", 0); + COMPARE_PC_REL_COMPACT(bnvc(a1, a0, 32767), + "60a47fff bnvc a1, a0, 32767", 32767); + COMPARE_PC_REL_COMPACT(bnvc(a1, a0, -32768), + "60a48000 bnvc a1, a0, -32768", -32768); + + COMPARE_PC_REL_COMPACT(beqzc(a0, 0), "d8800000 beqzc a0, 0x0", 0); + COMPARE_PC_REL_COMPACT(beqzc(a0, 0xfffff), // 0x0fffff == 1048575. + "d88fffff beqzc a0, 0xfffff", 1048575); + COMPARE_PC_REL_COMPACT(beqzc(a0, 0x100000), // 0x100000 == -1048576. + "d8900000 beqzc a0, 0x100000", -1048576); + + COMPARE_PC_REL_COMPACT(bnezc(a0, 0), "f8800000 bnezc a0, 0x0", 0); + COMPARE_PC_REL_COMPACT(bnezc(a0, 0xfffff), // 0x0fffff == 1048575. + "f88fffff bnezc a0, 0xfffff", 1048575); + COMPARE_PC_REL_COMPACT(bnezc(a0, 0x100000), // 0x100000 == -1048576. + "f8900000 bnezc a0, 0x100000", -1048576); + + COMPARE_PC_REL_COMPACT(bc(-33554432), "ca000000 bc -33554432", + -33554432); + COMPARE_PC_REL_COMPACT(bc(-1), "cbffffff bc -1", -1); + COMPARE_PC_REL_COMPACT(bc(0), "c8000000 bc 0", 0); + COMPARE_PC_REL_COMPACT(bc(1), "c8000001 bc 1", 1); + COMPARE_PC_REL_COMPACT(bc(33554431), "c9ffffff bc 33554431", + 33554431); + + COMPARE_PC_REL_COMPACT(balc(-33554432), "ea000000 balc -33554432", + -33554432); + COMPARE_PC_REL_COMPACT(balc(-1), "ebffffff balc -1", -1); + COMPARE_PC_REL_COMPACT(balc(0), "e8000000 balc 0", 0); + COMPARE_PC_REL_COMPACT(balc(1), "e8000001 balc 1", 1); + COMPARE_PC_REL_COMPACT(balc(33554431), "e9ffffff balc 33554431", + 33554431); + + COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, -32768), + "18858000 bgeuc a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, -1), + "1885ffff bgeuc a0, a1, -1", -1); + COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, 1), + "18850001 bgeuc a0, a1, 1", 1); + COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, 32767), + "18857fff bgeuc a0, a1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bgezalc(a0, -32768), + "18848000 bgezalc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(bgezalc(a0, -1), "1884ffff bgezalc a0, -1", + -1); + COMPARE_PC_REL_COMPACT(bgezalc(a0, 1), "18840001 bgezalc a0, 1", 1); + COMPARE_PC_REL_COMPACT(bgezalc(a0, 32767), + "18847fff bgezalc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(blezalc(a0, -32768), + "18048000 blezalc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(blezalc(a0, -1), "1804ffff blezalc a0, -1", + -1); + COMPARE_PC_REL_COMPACT(blezalc(a0, 1), "18040001 blezalc a0, 1", 1); + COMPARE_PC_REL_COMPACT(blezalc(a0, 32767), + "18047fff blezalc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bltuc(a0, a1, -32768), + "1c858000 bltuc a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bltuc(a0, a1, -1), + "1c85ffff bltuc a0, a1, -1", -1); + COMPARE_PC_REL_COMPACT(bltuc(a0, a1, 1), "1c850001 bltuc a0, a1, 1", + 1); + COMPARE_PC_REL_COMPACT(bltuc(a0, a1, 32767), + "1c857fff bltuc a0, a1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bltzalc(a0, -32768), + "1c848000 bltzalc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(bltzalc(a0, -1), "1c84ffff bltzalc a0, -1", + -1); + COMPARE_PC_REL_COMPACT(bltzalc(a0, 1), "1c840001 bltzalc a0, 1", 1); + COMPARE_PC_REL_COMPACT(bltzalc(a0, 32767), + "1c847fff bltzalc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bgtzalc(a0, -32768), + "1c048000 bgtzalc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(bgtzalc(a0, -1), "1c04ffff bgtzalc a0, -1", + -1); + COMPARE_PC_REL_COMPACT(bgtzalc(a0, 1), "1c040001 bgtzalc a0, 1", 1); + COMPARE_PC_REL_COMPACT(bgtzalc(a0, 32767), + "1c047fff bgtzalc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bgezc(a0, -32768), + "58848000 bgezc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(bgezc(a0, -1), "5884ffff bgezc a0, -1", -1); + COMPARE_PC_REL_COMPACT(bgezc(a0, 1), "58840001 bgezc a0, 1", 1); + COMPARE_PC_REL_COMPACT(bgezc(a0, 32767), + "58847fff bgezc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bgec(a0, a1, -32768), + "58858000 bgec a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bgec(a0, a1, -1), + "5885ffff bgec a0, a1, -1", -1); + COMPARE_PC_REL_COMPACT(bgec(a0, a1, 1), "58850001 bgec a0, a1, 1", + 1); + COMPARE_PC_REL_COMPACT(bgec(a0, a1, 32767), + "58857fff bgec a0, a1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(blezc(a0, -32768), + "58048000 blezc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(blezc(a0, -1), "5804ffff blezc a0, -1", -1); + COMPARE_PC_REL_COMPACT(blezc(a0, 1), "58040001 blezc a0, 1", 1); + COMPARE_PC_REL_COMPACT(blezc(a0, 32767), + "58047fff blezc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bltzc(a0, -32768), + "5c848000 bltzc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(bltzc(a0, -1), "5c84ffff bltzc a0, -1", -1); + COMPARE_PC_REL_COMPACT(bltzc(a0, 1), "5c840001 bltzc a0, 1", 1); + COMPARE_PC_REL_COMPACT(bltzc(a0, 32767), + "5c847fff bltzc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bltc(a0, a1, -32768), + "5c858000 bltc a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bltc(a0, a1, -1), + "5c85ffff bltc a0, a1, -1", -1); + COMPARE_PC_REL_COMPACT(bltc(a0, a1, 1), "5c850001 bltc a0, a1, 1", + 1); + COMPARE_PC_REL_COMPACT(bltc(a0, a1, 32767), + "5c857fff bltc a0, a1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bgtzc(a0, -32768), + "5c048000 bgtzc a0, -32768", -32768); + COMPARE_PC_REL_COMPACT(bgtzc(a0, -1), "5c04ffff bgtzc a0, -1", -1); + COMPARE_PC_REL_COMPACT(bgtzc(a0, 1), "5c040001 bgtzc a0, 1", 1); + COMPARE_PC_REL_COMPACT(bgtzc(a0, 32767), + "5c047fff bgtzc a0, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bc1eqz(-32768, f1), + "45218000 bc1eqz f1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bc1eqz(-1, f1), "4521ffff bc1eqz f1, -1", + -1); + COMPARE_PC_REL_COMPACT(bc1eqz(1, f1), "45210001 bc1eqz f1, 1", 1); + COMPARE_PC_REL_COMPACT(bc1eqz(32767, f1), + "45217fff bc1eqz f1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bc1nez(-32768, f1), + "45a18000 bc1nez f1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bc1nez(-1, f1), "45a1ffff bc1nez f1, -1", + -1); + COMPARE_PC_REL_COMPACT(bc1nez(1, f1), "45a10001 bc1nez f1, 1", 1); + COMPARE_PC_REL_COMPACT(bc1nez(32767, f1), + "45a17fff bc1nez f1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bovc(a1, a0, -1), "20a4ffff bovc a1, a0, -1", + -1); + COMPARE_PC_REL_COMPACT(bovc(a0, a0, 1), "20840001 bovc a0, a0, 1", + 1); + + COMPARE_PC_REL_COMPACT(beqc(a0, a1, -32768), + "20858000 beqc a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(beqc(a0, a1, -1), "2085ffff beqc a0, a1, -1", + -1); + COMPARE_PC_REL_COMPACT(beqc(a0, a1, 1), "20850001 beqc a0, a1, 1", + 1); + COMPARE_PC_REL_COMPACT(beqc(a0, a1, 32767), + "20857fff beqc a0, a1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bnec(a0, a1, -32768), + "60858000 bnec a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bnec(a0, a1, -1), "6085ffff bnec a0, a1, -1", + -1); + COMPARE_PC_REL_COMPACT(bnec(a0, a1, 1), "60850001 bnec a0, a1, 1", + 1); + COMPARE_PC_REL_COMPACT(bnec(a0, a1, 32767), + "60857fff bnec a0, a1, 32767", 32767); + } + + COMPARE_PC_REL_COMPACT(bne(a0, a1, -32768), + "14858000 bne a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(bne(a0, a1, -1), "1485ffff bne a0, a1, -1", + -1); + COMPARE_PC_REL_COMPACT(bne(a0, a1, 1), "14850001 bne a0, a1, 1", 1); + COMPARE_PC_REL_COMPACT(bne(a0, a1, 32767), + "14857fff bne a0, a1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(beq(a0, a1, -32768), + "10858000 beq a0, a1, -32768", -32768); + COMPARE_PC_REL_COMPACT(beq(a0, a1, -1), "1085ffff beq a0, a1, -1", + -1); + COMPARE_PC_REL_COMPACT(beq(a0, a1, 1), "10850001 beq a0, a1, 1", 1); + COMPARE_PC_REL_COMPACT(beq(a0, a1, 32767), + "10857fff beq a0, a1, 32767", 32767); + + COMPARE_PC_REL_COMPACT(bltz(a0, -32768), "04808000 bltz a0, -32768", + -32768); + COMPARE_PC_REL_COMPACT(bltz(a0, -1), "0480ffff bltz a0, -1", -1); + COMPARE_PC_REL_COMPACT(bltz(a0, 1), "04800001 bltz a0, 1", 1); + COMPARE_PC_REL_COMPACT(bltz(a0, 32767), "04807fff bltz a0, 32767", + 32767); + + COMPARE_PC_REL_COMPACT(bgez(a0, -32768), "04818000 bgez a0, -32768", + -32768); + COMPARE_PC_REL_COMPACT(bgez(a0, -1), "0481ffff bgez a0, -1", -1); + COMPARE_PC_REL_COMPACT(bgez(a0, 1), "04810001 bgez a0, 1", 1); + COMPARE_PC_REL_COMPACT(bgez(a0, 32767), "04817fff bgez a0, 32767", + 32767); + + COMPARE_PC_REL_COMPACT(blez(a0, -32768), "18808000 blez a0, -32768", + -32768); + COMPARE_PC_REL_COMPACT(blez(a0, -1), "1880ffff blez a0, -1", -1); + COMPARE_PC_REL_COMPACT(blez(a0, 1), "18800001 blez a0, 1", 1); + COMPARE_PC_REL_COMPACT(blez(a0, 32767), "18807fff blez a0, 32767", + 32767); + + COMPARE_PC_REL_COMPACT(bgtz(a0, -32768), "1c808000 bgtz a0, -32768", + -32768); + COMPARE_PC_REL_COMPACT(bgtz(a0, -1), "1c80ffff bgtz a0, -1", -1); + COMPARE_PC_REL_COMPACT(bgtz(a0, 1), "1c800001 bgtz a0, 1", 1); + COMPARE_PC_REL_COMPACT(bgtz(a0, 32767), "1c807fff bgtz a0, 32767", + 32767); + + COMPARE_PC_JUMP(j(0x4), "08000001 j 0x4", 0x4); + COMPARE_PC_JUMP(j(0xffffffc), "0bffffff j 0xffffffc", 0xffffffc); + + COMPARE_PC_JUMP(jal(0x4), "0c000001 jal 0x4", 0x4); + COMPARE_PC_JUMP(jal(0xffffffc), "0fffffff jal 0xffffffc", + 0xffffffc); + + VERIFY_RUN(); +} + + +TEST(C_FMT_DISASM) { + if (kArchVariant == kMips64r2) { + SET_UP(); + + COMPARE(c_s(F, f8, f10, 0), "460a4030 c.f.s f8, f10, cc(0)"); + COMPARE(c_d(F, f8, f10, 0), "462a4030 c.f.d f8, f10, cc(0)"); + + COMPARE(c_s(UN, f8, f10, 2), "460a4231 c.un.s f8, f10, cc(2)"); + COMPARE(c_d(UN, f8, f10, 2), "462a4231 c.un.d f8, f10, cc(2)"); + + COMPARE(c_s(EQ, f8, f10, 4), "460a4432 c.eq.s f8, f10, cc(4)"); + COMPARE(c_d(EQ, f8, f10, 4), "462a4432 c.eq.d f8, f10, cc(4)"); + + COMPARE(c_s(UEQ, f8, f10, 6), "460a4633 c.ueq.s f8, f10, cc(6)"); + COMPARE(c_d(UEQ, f8, f10, 6), "462a4633 c.ueq.d f8, f10, cc(6)"); + + COMPARE(c_s(OLT, f8, f10, 0), "460a4034 c.olt.s f8, f10, cc(0)"); + COMPARE(c_d(OLT, f8, f10, 0), "462a4034 c.olt.d f8, f10, cc(0)"); + + COMPARE(c_s(ULT, f8, f10, 2), "460a4235 c.ult.s f8, f10, cc(2)"); + COMPARE(c_d(ULT, f8, f10, 2), "462a4235 c.ult.d f8, f10, cc(2)"); + + COMPARE(c_s(OLE, f8, f10, 4), "460a4436 c.ole.s f8, f10, cc(4)"); + COMPARE(c_d(OLE, f8, f10, 4), "462a4436 c.ole.d f8, f10, cc(4)"); + + COMPARE(c_s(ULE, f8, f10, 6), "460a4637 c.ule.s f8, f10, cc(6)"); + COMPARE(c_d(ULE, f8, f10, 6), "462a4637 c.ule.d f8, f10, cc(6)"); + + VERIFY_RUN(); + } +} + + +TEST(COND_FMT_DISASM) { + if (kArchVariant == kMips64r6) { + SET_UP(); + + COMPARE(cmp_s(F, f6, f8, f10), "468a4180 cmp.af.s f6, f8, f10"); + COMPARE(cmp_d(F, f6, f8, f10), "46aa4180 cmp.af.d f6, f8, f10"); + + COMPARE(cmp_s(UN, f6, f8, f10), "468a4181 cmp.un.s f6, f8, f10"); + COMPARE(cmp_d(UN, f6, f8, f10), "46aa4181 cmp.un.d f6, f8, f10"); + + COMPARE(cmp_s(EQ, f6, f8, f10), "468a4182 cmp.eq.s f6, f8, f10"); + COMPARE(cmp_d(EQ, f6, f8, f10), "46aa4182 cmp.eq.d f6, f8, f10"); + + COMPARE(cmp_s(UEQ, f6, f8, f10), "468a4183 cmp.ueq.s f6, f8, f10"); + COMPARE(cmp_d(UEQ, f6, f8, f10), "46aa4183 cmp.ueq.d f6, f8, f10"); + + COMPARE(cmp_s(LT, f6, f8, f10), "468a4184 cmp.lt.s f6, f8, f10"); + COMPARE(cmp_d(LT, f6, f8, f10), "46aa4184 cmp.lt.d f6, f8, f10"); + + COMPARE(cmp_s(ULT, f6, f8, f10), "468a4185 cmp.ult.s f6, f8, f10"); + COMPARE(cmp_d(ULT, f6, f8, f10), "46aa4185 cmp.ult.d f6, f8, f10"); + + COMPARE(cmp_s(LE, f6, f8, f10), "468a4186 cmp.le.s f6, f8, f10"); + COMPARE(cmp_d(LE, f6, f8, f10), "46aa4186 cmp.le.d f6, f8, f10"); + + COMPARE(cmp_s(ULE, f6, f8, f10), "468a4187 cmp.ule.s f6, f8, f10"); + COMPARE(cmp_d(ULE, f6, f8, f10), "46aa4187 cmp.ule.d f6, f8, f10"); + + COMPARE(cmp_s(ORD, f6, f8, f10), "468a4191 cmp.or.s f6, f8, f10"); + COMPARE(cmp_d(ORD, f6, f8, f10), "46aa4191 cmp.or.d f6, f8, f10"); + + COMPARE(cmp_s(UNE, f6, f8, f10), "468a4192 cmp.une.s f6, f8, f10"); + COMPARE(cmp_d(UNE, f6, f8, f10), "46aa4192 cmp.une.d f6, f8, f10"); + + COMPARE(cmp_s(NE, f6, f8, f10), "468a4193 cmp.ne.s f6, f8, f10"); + COMPARE(cmp_d(NE, f6, f8, f10), "46aa4193 cmp.ne.d f6, f8, f10"); + + VERIFY_RUN(); + } +} + + +TEST(CVT_DISSASM) { + SET_UP(); + COMPARE(cvt_d_s(f22, f24), "4600c5a1 cvt.d.s f22, f24"); + COMPARE(cvt_d_w(f22, f24), "4680c5a1 cvt.d.w f22, f24"); + if (kArchVariant == kMips64r6 || kArchVariant == kMips64r2) { + COMPARE(cvt_d_l(f22, f24), "46a0c5a1 cvt.d.l f22, f24"); + } + + if (kArchVariant == kMips64r6 || kArchVariant == kMips64r2) { + COMPARE(cvt_l_s(f22, f24), "4600c5a5 cvt.l.s f22, f24"); + COMPARE(cvt_l_d(f22, f24), "4620c5a5 cvt.l.d f22, f24"); + } + + COMPARE(cvt_s_d(f22, f24), "4620c5a0 cvt.s.d f22, f24"); + COMPARE(cvt_s_w(f22, f24), "4680c5a0 cvt.s.w f22, f24"); + if (kArchVariant == kMips64r6 || kArchVariant == kMips64r2) { + COMPARE(cvt_s_l(f22, f24), "46a0c5a0 cvt.s.l f22, f24"); + } + + COMPARE(cvt_s_d(f22, f24), "4620c5a0 cvt.s.d f22, f24"); + COMPARE(cvt_s_w(f22, f24), "4680c5a0 cvt.s.w f22, f24"); + + VERIFY_RUN(); +} diff --git a/deps/v8/test/cctest/test-extra.js b/deps/v8/test/cctest/test-extra.js new file mode 100644 index 0000000000..829ddee01a --- /dev/null +++ b/deps/v8/test/cctest/test-extra.js @@ -0,0 +1,14 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(function (global, exports) { + 'use strict'; + exports.testExtraShouldReturnFive = function () { + return 5; + }; + + exports.testExtraShouldCallToRuntime = function() { + return exports.runtime(3); + }; +}) diff --git a/deps/v8/test/cctest/test-feedback-vector.cc b/deps/v8/test/cctest/test-feedback-vector.cc index e94de7b552..cf8a730fb7 100644 --- a/deps/v8/test/cctest/test-feedback-vector.cc +++ b/deps/v8/test/cctest/test-feedback-vector.cc @@ -46,19 +46,13 @@ TEST(VectorStructure) { CHECK_EQ(1, vector->ICSlots()); ZoneFeedbackVectorSpec spec(zone, 3, 5); - if (FLAG_vector_ics) { - for (int i = 0; i < 5; i++) spec.SetKind(i, Code::CALL_IC); - } + for (int i = 0; i < 5; i++) spec.SetKind(i, Code::CALL_IC); vector = factory->NewTypeFeedbackVector(&spec); CHECK_EQ(3, vector->Slots()); CHECK_EQ(5, vector->ICSlots()); int metadata_length = vector->ic_metadata_length(); - if (!FLAG_vector_ics) { - CHECK_EQ(0, metadata_length); - } else { - CHECK(metadata_length > 0); - } + CHECK(metadata_length > 0); int index = vector->GetIndex(FeedbackVectorSlot(0)); @@ -79,11 +73,6 @@ TEST(VectorStructure) { TEST(VectorICMetadata) { LocalContext context; v8::HandleScope scope(context->GetIsolate()); - if (!FLAG_vector_ics) { - // If FLAG_vector_ics is false, we only store CALL_ICs in the vector, so - // there is no need for metadata to describe the slots. - return; - } Isolate* isolate = CcTest::i_isolate(); Factory* factory = isolate->factory(); Zone* zone = isolate->runtime_zone(); @@ -259,7 +248,7 @@ TEST(VectorCallICStates) { TEST(VectorLoadICStates) { - if (i::FLAG_always_opt || !i::FLAG_vector_ics) return; + if (i::FLAG_always_opt) return; CcTest::InitializeVM(); LocalContext context; v8::HandleScope scope(context->GetIsolate()); @@ -313,7 +302,7 @@ TEST(VectorLoadICStates) { TEST(VectorLoadICSlotSharing) { - if (i::FLAG_always_opt || !i::FLAG_vector_ics) return; + if (i::FLAG_always_opt) return; CcTest::InitializeVM(); LocalContext context; v8::HandleScope scope(context->GetIsolate()); @@ -322,7 +311,7 @@ TEST(VectorLoadICSlotSharing) { // Function f has 3 LoadICs, one for each o, but the ICs share the same // feedback vector IC slot. CompileRun( - "var o = 10;" + "o = 10;" "function f() {" " var x = o + 10;" " return o + x + o;" @@ -341,7 +330,7 @@ TEST(VectorLoadICSlotSharing) { TEST(VectorLoadICOnSmi) { - if (i::FLAG_always_opt || !i::FLAG_vector_ics) return; + if (i::FLAG_always_opt) return; CcTest::InitializeVM(); LocalContext context; v8::HandleScope scope(context->GetIsolate()); diff --git a/deps/v8/test/cctest/test-fuzz-arm64.cc b/deps/v8/test/cctest/test-fuzz-arm64.cc index ada609fe78..8f6651a6a9 100644 --- a/deps/v8/test/cctest/test-fuzz-arm64.cc +++ b/deps/v8/test/cctest/test-fuzz-arm64.cc @@ -43,7 +43,7 @@ TEST(FUZZ_decoder) { Instruction buffer[kInstructionSize]; for (int i = 0; i < instruction_count; i++) { - uint32_t instr = mrand48(); + uint32_t instr = static_cast<uint32_t>(mrand48()); buffer->SetInstructionBits(instr); decoder.Decode(buffer); } @@ -64,7 +64,7 @@ TEST(FUZZ_disasm) { decoder.AppendVisitor(&disasm); for (int i = 0; i < instruction_count; i++) { - uint32_t instr = mrand48(); + uint32_t instr = static_cast<uint32_t>(mrand48()); buffer->SetInstructionBits(instr); decoder.Decode(buffer); } diff --git a/deps/v8/test/cctest/test-global-object.cc b/deps/v8/test/cctest/test-global-object.cc index b0ed29daf1..9cc755e4e1 100644 --- a/deps/v8/test/cctest/test-global-object.cc +++ b/deps/v8/test/cctest/test-global-object.cc @@ -29,15 +29,13 @@ #include "test/cctest/cctest.h" -using namespace v8; - // This test fails if properties on the prototype of the global object appear // as declared globals. TEST(StrictUndeclaredGlobalVariable) { - HandleScope scope(CcTest::isolate()); + v8::HandleScope scope(CcTest::isolate()); v8::Local<v8::String> var_name = v8_str("x"); LocalContext context; - v8::TryCatch try_catch; + v8::TryCatch try_catch(CcTest::isolate()); v8::Local<v8::Script> script = v8_compile("\"use strict\"; x = 42;"); v8::Handle<v8::Object> proto = v8::Object::New(CcTest::isolate()); v8::Handle<v8::Object> global = diff --git a/deps/v8/test/cctest/test-hashing.cc b/deps/v8/test/cctest/test-hashing.cc index c8ae4f30e5..9e5de2e05a 100644 --- a/deps/v8/test/cctest/test-hashing.cc +++ b/deps/v8/test/cctest/test-hashing.cc @@ -131,7 +131,7 @@ void check(uint32_t key) { #endif uint32_t runtime_hash = ComputeIntegerHash(key, isolate->heap()->HashSeed()); - CHECK(runtime_hash == codegen_hash); + CHECK_EQ(runtime_hash, codegen_hash); } diff --git a/deps/v8/test/cctest/test-hashmap.cc b/deps/v8/test/cctest/test-hashmap.cc index fb56225fb4..b45d6c7183 100644 --- a/deps/v8/test/cctest/test-hashmap.cc +++ b/deps/v8/test/cctest/test-hashmap.cc @@ -171,7 +171,7 @@ void TestSet(IntKeyHash hash, int size) { } -TEST(Set) { +TEST(HashSet) { TestSet(Hash, 100); TestSet(CollisionHash, 50); } diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc index f0a6ad5d26..d85310225a 100644 --- a/deps/v8/test/cctest/test-heap.cc +++ b/deps/v8/test/cctest/test-heap.cc @@ -59,6 +59,7 @@ TEST(HeapMaps) { Heap* heap = CcTest::heap(); CheckMap(heap->meta_map(), MAP_TYPE, Map::kSize); CheckMap(heap->heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize); + CheckMap(heap->float32x4_map(), FLOAT32X4_TYPE, Float32x4::kSize); CheckMap(heap->fixed_array_map(), FIXED_ARRAY_TYPE, kVariableSizeSentinel); CheckMap(heap->string_map(), STRING_TYPE, kVariableSizeSentinel); } @@ -213,6 +214,60 @@ TEST(HeapObjects) { } +template <typename T, typename LANE_TYPE, int LANES> +static void CheckSimdLanes(T* value) { + // Get the original values, and check that all lanes can be set to new values + // without disturbing the other lanes. + LANE_TYPE lane_values[LANES]; + for (int i = 0; i < LANES; i++) { + lane_values[i] = value->get_lane(i); + } + for (int i = 0; i < LANES; i++) { + lane_values[i] += 1; + value->set_lane(i, lane_values[i]); + for (int j = 0; j < LANES; j++) { + CHECK_EQ(lane_values[j], value->get_lane(j)); + } + } +} + + +TEST(SimdObjects) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + Factory* factory = isolate->factory(); + + HandleScope sc(isolate); + + Handle<Object> value = factory->NewFloat32x4(1, 2, 3, 4); + CHECK(value->IsFloat32x4()); + CHECK(value->BooleanValue()); // SIMD values map to true. + + Float32x4* float32x4 = *Handle<Float32x4>::cast(value); + CheckSimdLanes<Float32x4, float, 4>(float32x4); + + // Check ToString for SIMD values. + // TODO(bbudge): Switch to Check* style function to test ToString(). + value = factory->NewFloat32x4(1, 2, 3, 4); + float32x4 = *Handle<Float32x4>::cast(value); + std::ostringstream os; + float32x4->Float32x4Print(os); + CHECK_EQ("1, 2, 3, 4", os.str()); + + // Check unusual lane values. + float32x4->set_lane(0, 0); + CHECK_EQ(0, float32x4->get_lane(0)); + float32x4->set_lane(1, -0.0); + CHECK_EQ(-0.0, float32x4->get_lane(1)); + float quiet_NaN = std::numeric_limits<float>::quiet_NaN(); + float signaling_NaN = std::numeric_limits<float>::signaling_NaN(); + float32x4->set_lane(2, quiet_NaN); + CHECK(std::isnan(float32x4->get_lane(2))); + float32x4->set_lane(3, signaling_NaN); + CHECK(std::isnan(float32x4->get_lane(3))); +} + + TEST(Tagging) { CcTest::InitializeVM(); int request = 24; @@ -730,29 +785,27 @@ TEST(JSArray) { JSArray::Initialize(array, 0); // Set array length to 0. - JSArray::SetElementsLength(array, handle(Smi::FromInt(0), isolate)).Check(); + JSArray::SetLength(array, 0); CHECK_EQ(Smi::FromInt(0), array->length()); // Must be in fast mode. CHECK(array->HasFastSmiOrObjectElements()); // array[length] = name. - JSReceiver::SetElement(array, 0, name, NONE, SLOPPY).Check(); + JSReceiver::SetElement(array, 0, name, SLOPPY).Check(); CHECK_EQ(Smi::FromInt(1), array->length()); element = i::Object::GetElement(isolate, array, 0).ToHandleChecked(); CHECK_EQ(*element, *name); // Set array length with larger than smi value. - Handle<Object> length = - factory->NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1); - JSArray::SetElementsLength(array, length).Check(); + JSArray::SetLength(array, static_cast<uint32_t>(Smi::kMaxValue) + 1); uint32_t int_length = 0; - CHECK(length->ToArrayIndex(&int_length)); - CHECK_EQ(*length, array->length()); + CHECK(array->length()->ToArrayIndex(&int_length)); + CHECK_EQ(static_cast<uint32_t>(Smi::kMaxValue) + 1, int_length); CHECK(array->HasDictionaryElements()); // Must be in slow mode. // array[length] = name. - JSReceiver::SetElement(array, int_length, name, NONE, SLOPPY).Check(); + JSReceiver::SetElement(array, int_length, name, SLOPPY).Check(); uint32_t new_int_length = 0; CHECK(array->length()->ToArrayIndex(&new_int_length)); CHECK_EQ(static_cast<double>(int_length), new_int_length - 1); @@ -783,8 +836,8 @@ TEST(JSObjectCopy) { JSReceiver::SetProperty(obj, first, one, SLOPPY).Check(); JSReceiver::SetProperty(obj, second, two, SLOPPY).Check(); - JSReceiver::SetElement(obj, 0, first, NONE, SLOPPY).Check(); - JSReceiver::SetElement(obj, 1, second, NONE, SLOPPY).Check(); + JSReceiver::SetElement(obj, 0, first, SLOPPY).Check(); + JSReceiver::SetElement(obj, 1, second, SLOPPY).Check(); // Make the clone. Handle<Object> value1, value2; @@ -809,8 +862,8 @@ TEST(JSObjectCopy) { JSReceiver::SetProperty(clone, first, two, SLOPPY).Check(); JSReceiver::SetProperty(clone, second, one, SLOPPY).Check(); - JSReceiver::SetElement(clone, 0, second, NONE, SLOPPY).Check(); - JSReceiver::SetElement(clone, 1, first, NONE, SLOPPY).Check(); + JSReceiver::SetElement(clone, 0, second, SLOPPY).Check(); + JSReceiver::SetElement(clone, 1, first, SLOPPY).Check(); value1 = Object::GetElement(isolate, obj, 1).ToHandleChecked(); value2 = Object::GetElement(isolate, clone, 0).ToHandleChecked(); @@ -896,9 +949,8 @@ TEST(Iteration) { // Allocate a JS array to OLD_SPACE and NEW_SPACE objs[next_objs_index++] = factory->NewJSArray(10); - objs[next_objs_index++] = factory->NewJSArray(10, - FAST_HOLEY_ELEMENTS, - TENURED); + objs[next_objs_index++] = + factory->NewJSArray(10, FAST_HOLEY_ELEMENTS, Strength::WEAK, TENURED); // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE objs[next_objs_index++] = factory->NewStringFromStaticChars("abcdefghij"); @@ -1142,7 +1194,7 @@ TEST(TestCodeFlushingPreAged) { TEST(TestCodeFlushingIncremental) { // If we do not flush code this test is invalid. - if (!FLAG_flush_code || !FLAG_flush_code_incrementally) return; + if (!FLAG_flush_code) return; i::FLAG_allow_natives_syntax = true; i::FLAG_optimize_for_size = false; CcTest::InitializeVM(); @@ -1211,7 +1263,7 @@ TEST(TestCodeFlushingIncremental) { TEST(TestCodeFlushingIncrementalScavenge) { // If we do not flush code this test is invalid. - if (!FLAG_flush_code || !FLAG_flush_code_incrementally) return; + if (!FLAG_flush_code) return; i::FLAG_allow_natives_syntax = true; i::FLAG_optimize_for_size = false; CcTest::InitializeVM(); @@ -1280,7 +1332,7 @@ TEST(TestCodeFlushingIncrementalScavenge) { TEST(TestCodeFlushingIncrementalAbort) { // If we do not flush code this test is invalid. - if (!FLAG_flush_code || !FLAG_flush_code_incrementally) return; + if (!FLAG_flush_code) return; i::FLAG_allow_natives_syntax = true; i::FLAG_optimize_for_size = false; CcTest::InitializeVM(); @@ -1328,8 +1380,10 @@ TEST(TestCodeFlushingIncrementalAbort) { // disabled. int position = 0; Handle<Object> breakpoint_object(Smi::FromInt(0), isolate); + EnableDebugger(); isolate->debug()->SetBreakPoint(function, breakpoint_object, &position); isolate->debug()->ClearAllBreakPoints(); + DisableDebugger(); // Force optimization now that code flushing is disabled. { v8::HandleScope scope(CcTest::isolate()); @@ -1346,8 +1400,7 @@ TEST(TestCodeFlushingIncrementalAbort) { TEST(CompilationCacheCachingBehavior) { // If we do not flush code, or have the compilation cache turned off, this // test is invalid. - if (!FLAG_flush_code || !FLAG_flush_code_incrementally || - !FLAG_compilation_cache) { + if (!FLAG_flush_code || !FLAG_compilation_cache) { return; } CcTest::InitializeVM(); @@ -1377,7 +1430,8 @@ TEST(CompilationCacheCachingBehavior) { // On first compilation, only a hash is inserted in the code cache. We can't // find that value. MaybeHandle<SharedFunctionInfo> info = compilation_cache->LookupScript( - source, Handle<Object>(), 0, 0, false, true, native_context, + source, Handle<Object>(), 0, 0, + v8::ScriptOriginOptions(false, true, false), native_context, language_mode); CHECK(info.is_null()); @@ -1388,16 +1442,20 @@ TEST(CompilationCacheCachingBehavior) { // On second compilation, the hash is replaced by a real cache entry mapping // the source to the shared function info containing the code. - info = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, false, - true, native_context, language_mode); + info = compilation_cache->LookupScript( + source, Handle<Object>(), 0, 0, + v8::ScriptOriginOptions(false, true, false), native_context, + language_mode); CHECK(!info.is_null()); heap->CollectAllGarbage(); // On second compilation, the hash is replaced by a real cache entry mapping // the source to the shared function info containing the code. - info = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, false, - true, native_context, language_mode); + info = compilation_cache->LookupScript( + source, Handle<Object>(), 0, 0, + v8::ScriptOriginOptions(false, true, false), native_context, + language_mode); CHECK(!info.is_null()); while (!info.ToHandleChecked()->code()->IsOld()) { @@ -1406,8 +1464,10 @@ TEST(CompilationCacheCachingBehavior) { heap->CollectAllGarbage(); // Ensure code aging cleared the entry from the cache. - info = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, false, - true, native_context, language_mode); + info = compilation_cache->LookupScript( + source, Handle<Object>(), 0, 0, + v8::ScriptOriginOptions(false, true, false), native_context, + language_mode); CHECK(info.is_null()); { @@ -1417,8 +1477,10 @@ TEST(CompilationCacheCachingBehavior) { // On first compilation, only a hash is inserted in the code cache. We can't // find that value. - info = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, false, - true, native_context, language_mode); + info = compilation_cache->LookupScript( + source, Handle<Object>(), 0, 0, + v8::ScriptOriginOptions(false, true, false), native_context, + language_mode); CHECK(info.is_null()); for (int i = 0; i < CompilationCacheTable::kHashGenerations; i++) { @@ -1432,8 +1494,10 @@ TEST(CompilationCacheCachingBehavior) { // If we aged the cache before caching the script, ensure that we didn't cache // on next compilation. - info = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, false, - true, native_context, language_mode); + info = compilation_cache->LookupScript( + source, Handle<Object>(), 0, 0, + v8::ScriptOriginOptions(false, true, false), native_context, + language_mode); CHECK(info.is_null()); } @@ -1682,13 +1746,13 @@ TEST(TestSizeOfRegExpCode) { // Adjust source below and this check to match // RegExpImple::kRegExpTooLargeToOptimize. - DCHECK_EQ(i::RegExpImpl::kRegExpTooLargeToOptimize, 10 * KB); + DCHECK_EQ(i::RegExpImpl::kRegExpTooLargeToOptimize, 20 * KB); // Compile a regexp that is much larger if we are using regexp optimizations. CompileRun( "var reg_exp_source = '(?:a|bc|def|ghij|klmno|pqrstu)';" "var half_size_reg_exp;" - "while (reg_exp_source.length < 10 * 1024) {" + "while (reg_exp_source.length < 20 * 1024) {" " half_size_reg_exp = reg_exp_source;" " reg_exp_source = reg_exp_source + reg_exp_source;" "}" @@ -1719,7 +1783,11 @@ TEST(TestSizeOfRegExpCode) { int size_of_regexp_code = size_with_regexp - initial_size; - CHECK_LE(size_of_regexp_code, 1 * MB); + // On some platforms the debug-code flag causes huge amounts of regexp code + // to be emitted, breaking this test. + if (!FLAG_debug_code) { + CHECK_LE(size_of_regexp_code, 1 * MB); + } // Small regexp is half the size, but compiles to more than twice the code // due to the optimization steps. @@ -1773,6 +1841,271 @@ TEST(TestSizeOfObjects) { } +TEST(TestAlignmentCalculations) { + // Maximum fill amounts are consistent. + int maximum_double_misalignment = kDoubleSize - kPointerSize; + int maximum_simd128_misalignment = kSimd128Size - kPointerSize; + int max_word_fill = Heap::GetMaximumFillToAlign(kWordAligned); + CHECK_EQ(0, max_word_fill); + int max_double_fill = Heap::GetMaximumFillToAlign(kDoubleAligned); + CHECK_EQ(maximum_double_misalignment, max_double_fill); + int max_double_unaligned_fill = Heap::GetMaximumFillToAlign(kDoubleUnaligned); + CHECK_EQ(maximum_double_misalignment, max_double_unaligned_fill); + int max_simd128_unaligned_fill = + Heap::GetMaximumFillToAlign(kSimd128Unaligned); + CHECK_EQ(maximum_simd128_misalignment, max_simd128_unaligned_fill); + + Address base = reinterpret_cast<Address>(NULL); + int fill = 0; + + // Word alignment never requires fill. + fill = Heap::GetFillToAlign(base, kWordAligned); + CHECK_EQ(0, fill); + fill = Heap::GetFillToAlign(base + kPointerSize, kWordAligned); + CHECK_EQ(0, fill); + + // No fill is required when address is double aligned. + fill = Heap::GetFillToAlign(base, kDoubleAligned); + CHECK_EQ(0, fill); + // Fill is required if address is not double aligned. + fill = Heap::GetFillToAlign(base + kPointerSize, kDoubleAligned); + CHECK_EQ(maximum_double_misalignment, fill); + // kDoubleUnaligned has the opposite fill amounts. + fill = Heap::GetFillToAlign(base, kDoubleUnaligned); + CHECK_EQ(maximum_double_misalignment, fill); + fill = Heap::GetFillToAlign(base + kPointerSize, kDoubleUnaligned); + CHECK_EQ(0, fill); + + // 128 bit SIMD types have 2 or 4 possible alignments, depending on platform. + fill = Heap::GetFillToAlign(base, kSimd128Unaligned); + CHECK_EQ((3 * kPointerSize) & kSimd128AlignmentMask, fill); + fill = Heap::GetFillToAlign(base + kPointerSize, kSimd128Unaligned); + CHECK_EQ((2 * kPointerSize) & kSimd128AlignmentMask, fill); + fill = Heap::GetFillToAlign(base + 2 * kPointerSize, kSimd128Unaligned); + CHECK_EQ(kPointerSize, fill); + fill = Heap::GetFillToAlign(base + 3 * kPointerSize, kSimd128Unaligned); + CHECK_EQ(0, fill); +} + + +static HeapObject* NewSpaceAllocateAligned(int size, + AllocationAlignment alignment) { + Heap* heap = CcTest::heap(); + AllocationResult allocation = + heap->new_space()->AllocateRawAligned(size, alignment); + HeapObject* obj = NULL; + allocation.To(&obj); + heap->CreateFillerObjectAt(obj->address(), size); + return obj; +} + + +// Get new space allocation into the desired alignment. +static Address AlignNewSpace(AllocationAlignment alignment, int offset) { + Address* top_addr = CcTest::heap()->new_space()->allocation_top_address(); + int fill = Heap::GetFillToAlign(*top_addr, alignment); + if (fill) { + NewSpaceAllocateAligned(fill + offset, kWordAligned); + } + return *top_addr; +} + + +TEST(TestAlignedAllocation) { + // Double misalignment is 4 on 32-bit platforms, 0 on 64-bit ones. + const intptr_t double_misalignment = kDoubleSize - kPointerSize; + Address* top_addr = CcTest::heap()->new_space()->allocation_top_address(); + Address start; + HeapObject* obj; + HeapObject* filler; + if (double_misalignment) { + // Allocate a pointer sized object that must be double aligned at an + // aligned address. + start = AlignNewSpace(kDoubleAligned, 0); + obj = NewSpaceAllocateAligned(kPointerSize, kDoubleAligned); + CHECK(IsAddressAligned(obj->address(), kDoubleAlignment)); + // There is no filler. + CHECK_EQ(kPointerSize, *top_addr - start); + + // Allocate a second pointer sized object that must be double aligned at an + // unaligned address. + start = AlignNewSpace(kDoubleAligned, kPointerSize); + obj = NewSpaceAllocateAligned(kPointerSize, kDoubleAligned); + CHECK(IsAddressAligned(obj->address(), kDoubleAlignment)); + // There is a filler object before the object. + filler = HeapObject::FromAddress(start); + CHECK(obj != filler && filler->IsFiller() && + filler->Size() == kPointerSize); + CHECK_EQ(kPointerSize + double_misalignment, *top_addr - start); + + // Similarly for kDoubleUnaligned. + start = AlignNewSpace(kDoubleUnaligned, 0); + obj = NewSpaceAllocateAligned(kPointerSize, kDoubleUnaligned); + CHECK(IsAddressAligned(obj->address(), kDoubleAlignment, kPointerSize)); + CHECK_EQ(kPointerSize, *top_addr - start); + start = AlignNewSpace(kDoubleUnaligned, kPointerSize); + obj = NewSpaceAllocateAligned(kPointerSize, kDoubleUnaligned); + CHECK(IsAddressAligned(obj->address(), kDoubleAlignment, kPointerSize)); + // There is a filler object before the object. + filler = HeapObject::FromAddress(start); + CHECK(obj != filler && filler->IsFiller() && + filler->Size() == kPointerSize); + CHECK_EQ(kPointerSize + double_misalignment, *top_addr - start); + } + + // Now test SIMD alignment. There are 2 or 4 possible alignments, depending + // on platform. + start = AlignNewSpace(kSimd128Unaligned, 0); + obj = NewSpaceAllocateAligned(kPointerSize, kSimd128Unaligned); + CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize)); + // There is no filler. + CHECK_EQ(kPointerSize, *top_addr - start); + start = AlignNewSpace(kSimd128Unaligned, kPointerSize); + obj = NewSpaceAllocateAligned(kPointerSize, kSimd128Unaligned); + CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize)); + // There is a filler object before the object. + filler = HeapObject::FromAddress(start); + CHECK(obj != filler && filler->IsFiller() && + filler->Size() == kSimd128Size - kPointerSize); + CHECK_EQ(kPointerSize + kSimd128Size - kPointerSize, *top_addr - start); + + if (double_misalignment) { + // Test the 2 other alignments possible on 32 bit platforms. + start = AlignNewSpace(kSimd128Unaligned, 2 * kPointerSize); + obj = NewSpaceAllocateAligned(kPointerSize, kSimd128Unaligned); + CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize)); + // There is a filler object before the object. + filler = HeapObject::FromAddress(start); + CHECK(obj != filler && filler->IsFiller() && + filler->Size() == 2 * kPointerSize); + CHECK_EQ(kPointerSize + 2 * kPointerSize, *top_addr - start); + start = AlignNewSpace(kSimd128Unaligned, 3 * kPointerSize); + obj = NewSpaceAllocateAligned(kPointerSize, kSimd128Unaligned); + CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize)); + // There is a filler object before the object. + filler = HeapObject::FromAddress(start); + CHECK(obj != filler && filler->IsFiller() && + filler->Size() == kPointerSize); + CHECK_EQ(kPointerSize + kPointerSize, *top_addr - start); + } +} + + +static HeapObject* OldSpaceAllocateAligned(int size, + AllocationAlignment alignment) { + Heap* heap = CcTest::heap(); + AllocationResult allocation = + heap->old_space()->AllocateRawAligned(size, alignment); + HeapObject* obj = NULL; + allocation.To(&obj); + heap->CreateFillerObjectAt(obj->address(), size); + return obj; +} + + +// Get old space allocation into the desired alignment. +static Address AlignOldSpace(AllocationAlignment alignment, int offset) { + Address* top_addr = CcTest::heap()->old_space()->allocation_top_address(); + int fill = Heap::GetFillToAlign(*top_addr, alignment); + int allocation = fill + offset; + if (allocation) { + OldSpaceAllocateAligned(allocation, kWordAligned); + } + Address top = *top_addr; + // Now force the remaining allocation onto the free list. + CcTest::heap()->old_space()->EmptyAllocationInfo(); + return top; +} + + +// Test the case where allocation must be done from the free list, so filler +// may precede or follow the object. +TEST(TestAlignedOverAllocation) { + // Double misalignment is 4 on 32-bit platforms, 0 on 64-bit ones. + const intptr_t double_misalignment = kDoubleSize - kPointerSize; + Address start; + HeapObject* obj; + HeapObject* filler1; + HeapObject* filler2; + if (double_misalignment) { + start = AlignOldSpace(kDoubleAligned, 0); + obj = OldSpaceAllocateAligned(kPointerSize, kDoubleAligned); + // The object is aligned, and a filler object is created after. + CHECK(IsAddressAligned(obj->address(), kDoubleAlignment)); + filler1 = HeapObject::FromAddress(start + kPointerSize); + CHECK(obj != filler1 && filler1->IsFiller() && + filler1->Size() == kPointerSize); + // Try the opposite alignment case. + start = AlignOldSpace(kDoubleAligned, kPointerSize); + obj = OldSpaceAllocateAligned(kPointerSize, kDoubleAligned); + CHECK(IsAddressAligned(obj->address(), kDoubleAlignment)); + filler1 = HeapObject::FromAddress(start); + CHECK(obj != filler1); + CHECK(filler1->IsFiller()); + CHECK(filler1->Size() == kPointerSize); + CHECK(obj != filler1 && filler1->IsFiller() && + filler1->Size() == kPointerSize); + + // Similarly for kDoubleUnaligned. + start = AlignOldSpace(kDoubleUnaligned, 0); + obj = OldSpaceAllocateAligned(kPointerSize, kDoubleUnaligned); + // The object is aligned, and a filler object is created after. + CHECK(IsAddressAligned(obj->address(), kDoubleAlignment, kPointerSize)); + filler1 = HeapObject::FromAddress(start + kPointerSize); + CHECK(obj != filler1 && filler1->IsFiller() && + filler1->Size() == kPointerSize); + // Try the opposite alignment case. + start = AlignOldSpace(kDoubleUnaligned, kPointerSize); + obj = OldSpaceAllocateAligned(kPointerSize, kDoubleUnaligned); + CHECK(IsAddressAligned(obj->address(), kDoubleAlignment, kPointerSize)); + filler1 = HeapObject::FromAddress(start); + CHECK(obj != filler1 && filler1->IsFiller() && + filler1->Size() == kPointerSize); + } + + // Now test SIMD alignment. There are 2 or 4 possible alignments, depending + // on platform. + start = AlignOldSpace(kSimd128Unaligned, 0); + obj = OldSpaceAllocateAligned(kPointerSize, kSimd128Unaligned); + CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize)); + // There is a filler object after the object. + filler1 = HeapObject::FromAddress(start + kPointerSize); + CHECK(obj != filler1 && filler1->IsFiller() && + filler1->Size() == kSimd128Size - kPointerSize); + start = AlignOldSpace(kSimd128Unaligned, kPointerSize); + obj = OldSpaceAllocateAligned(kPointerSize, kSimd128Unaligned); + CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize)); + // There is a filler object before the object. + filler1 = HeapObject::FromAddress(start); + CHECK(obj != filler1 && filler1->IsFiller() && + filler1->Size() == kSimd128Size - kPointerSize); + + if (double_misalignment) { + // Test the 2 other alignments possible on 32 bit platforms. + start = AlignOldSpace(kSimd128Unaligned, 2 * kPointerSize); + obj = OldSpaceAllocateAligned(kPointerSize, kSimd128Unaligned); + CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize)); + // There are filler objects before and after the object. + filler1 = HeapObject::FromAddress(start); + CHECK(obj != filler1 && filler1->IsFiller() && + filler1->Size() == 2 * kPointerSize); + filler2 = HeapObject::FromAddress(start + 3 * kPointerSize); + CHECK(obj != filler2 && filler2->IsFiller() && + filler2->Size() == kPointerSize); + start = AlignOldSpace(kSimd128Unaligned, 3 * kPointerSize); + obj = OldSpaceAllocateAligned(kPointerSize, kSimd128Unaligned); + CHECK(IsAddressAligned(obj->address(), kSimd128Alignment, kPointerSize)); + // There are filler objects before and after the object. + filler1 = HeapObject::FromAddress(start); + CHECK(obj != filler1 && filler1->IsFiller() && + filler1->Size() == kPointerSize); + filler2 = HeapObject::FromAddress(start + 2 * kPointerSize); + CHECK(obj != filler2 && filler2->IsFiller() && + filler2->Size() == 2 * kPointerSize); + } +} + + TEST(TestSizeOfObjectsVsHeapIteratorPrecision) { CcTest::InitializeVM(); HeapIterator iterator(CcTest::heap()); @@ -2118,7 +2451,7 @@ TEST(InstanceOfStubWriteBarrier) { IncrementalMarking* marking = CcTest::heap()->incremental_marking(); marking->Abort(); - marking->Start(); + marking->Start(Heap::kNoGCFlags); Handle<JSFunction> f = v8::Utils::OpenHandle( @@ -2191,7 +2524,8 @@ TEST(PrototypeTransitionClearing) { TransitionArray::GetPrototypeTransitions(baseObject->map()); for (int i = initialTransitions; i < initialTransitions + transitions; i++) { int j = TransitionArray::kProtoTransitionHeaderSize + i; - CHECK(trans->get(j)->IsMap()); + CHECK(trans->get(j)->IsWeakCell()); + CHECK(WeakCell::cast(trans->get(j))->value()->IsMap()); } // Make sure next prototype is placed on an old-space evacuation candidate. @@ -2200,7 +2534,8 @@ TEST(PrototypeTransitionClearing) { { AlwaysAllocateScope always_allocate(isolate); SimulateFullSpace(space); - prototype = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, TENURED); + prototype = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, + Strength::WEAK, TENURED); } // Add a prototype on an evacuation candidate and verify that transition @@ -2244,7 +2579,7 @@ TEST(ResetSharedFunctionInfoCountersDuringIncrementalMarking) { IncrementalMarking* marking = CcTest::heap()->incremental_marking(); marking->Abort(); - marking->Start(); + marking->Start(Heap::kNoGCFlags); // The following calls will increment CcTest::heap()->global_ic_age(). CcTest::isolate()->ContextDisposedNotification(); SimulateIncrementalMarking(CcTest::heap()); @@ -2302,7 +2637,7 @@ TEST(IdleNotificationFinishMarking) { SimulateFullSpace(CcTest::heap()->old_space()); IncrementalMarking* marking = CcTest::heap()->incremental_marking(); marking->Abort(); - marking->Start(); + marking->Start(Heap::kNoGCFlags); CHECK_EQ(CcTest::heap()->gc_count(), 0); @@ -3071,7 +3406,6 @@ TEST(TransitionArraySimpleToFull) { TEST(Regress2143a) { - i::FLAG_collect_maps = true; i::FLAG_incremental_marking = true; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -3111,7 +3445,6 @@ TEST(Regress2143a) { TEST(Regress2143b) { - i::FLAG_collect_maps = true; i::FLAG_incremental_marking = true; i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); @@ -3203,6 +3536,31 @@ TEST(ReleaseOverReservedPages) { CHECK_EQ(1, old_space->CountTotalPages()); } +static int forced_gc_counter = 0; + +void MockUseCounterCallback(v8::Isolate* isolate, + v8::Isolate::UseCounterFeature feature) { + isolate->GetCallingContext(); + if (feature == v8::Isolate::kForcedGC) { + forced_gc_counter++; + } +} + + +TEST(CountForcedGC) { + i::FLAG_expose_gc = true; + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + v8::HandleScope scope(CcTest::isolate()); + + isolate->SetUseCounterCallback(MockUseCounterCallback); + + forced_gc_counter = 0; + const char* source = "gc();"; + CompileRun(source); + CHECK_GT(forced_gc_counter, 0); +} + TEST(Regress2237) { i::FLAG_stress_compaction = false; @@ -3255,41 +3613,6 @@ TEST(PrintSharedFunctionInfo) { #endif // OBJECT_PRINT -TEST(Regress2211) { - CcTest::InitializeVM(); - v8::HandleScope scope(CcTest::isolate()); - - v8::Handle<v8::String> value = v8_str("val string"); - Smi* hash = Smi::FromInt(321); - Factory* factory = CcTest::i_isolate()->factory(); - - for (int i = 0; i < 2; i++) { - // Store identity hash first and common hidden property second. - v8::Handle<v8::Object> obj = v8::Object::New(CcTest::isolate()); - Handle<JSObject> internal_obj = v8::Utils::OpenHandle(*obj); - CHECK(internal_obj->HasFastProperties()); - - // In the first iteration, set hidden value first and identity hash second. - // In the second iteration, reverse the order. - if (i == 0) obj->SetHiddenValue(v8_str("key string"), value); - JSObject::SetIdentityHash(internal_obj, handle(hash, CcTest::i_isolate())); - if (i == 1) obj->SetHiddenValue(v8_str("key string"), value); - - // Check values. - CHECK_EQ(hash, - internal_obj->GetHiddenProperty(factory->identity_hash_string())); - CHECK(value->Equals(obj->GetHiddenValue(v8_str("key string")))); - - // Check size. - FieldIndex index = FieldIndex::ForDescriptor(internal_obj->map(), 0); - ObjectHashTable* hashtable = ObjectHashTable::cast( - internal_obj->RawFastPropertyAt(index)); - // HashTable header (5) and 4 initial entries (8). - CHECK_LE(hashtable->SizeFor(hashtable->length()), 13 * kPointerSize); - } -} - - TEST(IncrementalMarkingPreservesMonomorphicCallIC) { if (i::FLAG_always_opt) return; CcTest::InitializeVM(); @@ -3447,23 +3770,15 @@ TEST(IncrementalMarkingPreservesMonomorphicIC) { CcTest::global()->Get(v8_str("f")))); Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); - if (FLAG_vector_ics) { - CheckVectorIC(f, 0, MONOMORPHIC); - CHECK(ic_before->ic_state() == DEFAULT); - } else { - CHECK(ic_before->ic_state() == MONOMORPHIC); - } + CheckVectorIC(f, 0, MONOMORPHIC); + CHECK(ic_before->ic_state() == DEFAULT); SimulateIncrementalMarking(CcTest::heap()); CcTest::heap()->CollectAllGarbage(); Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC); - if (FLAG_vector_ics) { - CheckVectorIC(f, 0, MONOMORPHIC); - CHECK(ic_after->ic_state() == DEFAULT); - } else { - CHECK(ic_after->ic_state() == MONOMORPHIC); - } + CheckVectorIC(f, 0, MONOMORPHIC); + CHECK(ic_after->ic_state() == DEFAULT); } @@ -3487,12 +3802,8 @@ TEST(IncrementalMarkingClearsMonomorphicIC) { *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f")))); Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); - if (FLAG_vector_ics) { - CheckVectorIC(f, 0, MONOMORPHIC); - CHECK(ic_before->ic_state() == DEFAULT); - } else { - CHECK(ic_before->ic_state() == MONOMORPHIC); - } + CheckVectorIC(f, 0, MONOMORPHIC); + CHECK(ic_before->ic_state() == DEFAULT); // Fire context dispose notification. CcTest::isolate()->ContextDisposedNotification(); @@ -3500,12 +3811,8 @@ TEST(IncrementalMarkingClearsMonomorphicIC) { CcTest::heap()->CollectAllGarbage(); Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC); - if (FLAG_vector_ics) { - CheckVectorICCleared(f, 0); - CHECK(ic_after->ic_state() == DEFAULT); - } else { - CHECK(IC::IsCleared(ic_after)); - } + CheckVectorICCleared(f, 0); + CHECK(ic_after->ic_state() == DEFAULT); } @@ -3536,24 +3843,16 @@ TEST(IncrementalMarkingPreservesPolymorphicIC) { *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f")))); Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); - if (FLAG_vector_ics) { - CheckVectorIC(f, 0, POLYMORPHIC); - CHECK(ic_before->ic_state() == DEFAULT); - } else { - CHECK(ic_before->ic_state() == POLYMORPHIC); - } + CheckVectorIC(f, 0, POLYMORPHIC); + CHECK(ic_before->ic_state() == DEFAULT); // Fire context dispose notification. SimulateIncrementalMarking(CcTest::heap()); CcTest::heap()->CollectAllGarbage(); Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC); - if (FLAG_vector_ics) { - CheckVectorIC(f, 0, POLYMORPHIC); - CHECK(ic_after->ic_state() == DEFAULT); - } else { - CHECK(ic_after->ic_state() == POLYMORPHIC); - } + CheckVectorIC(f, 0, POLYMORPHIC); + CHECK(ic_after->ic_state() == DEFAULT); } @@ -3584,25 +3883,16 @@ TEST(IncrementalMarkingClearsPolymorphicIC) { *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f")))); Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); - if (FLAG_vector_ics) { - CheckVectorIC(f, 0, POLYMORPHIC); - CHECK(ic_before->ic_state() == DEFAULT); - } else { - CHECK(ic_before->ic_state() == POLYMORPHIC); - } + CheckVectorIC(f, 0, POLYMORPHIC); + CHECK(ic_before->ic_state() == DEFAULT); // Fire context dispose notification. CcTest::isolate()->ContextDisposedNotification(); SimulateIncrementalMarking(CcTest::heap()); CcTest::heap()->CollectAllGarbage(); - Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC); - if (FLAG_vector_ics) { - CheckVectorICCleared(f, 0); - CHECK(ic_before->ic_state() == DEFAULT); - } else { - CHECK(IC::IsCleared(ic_after)); - } + CheckVectorICCleared(f, 0); + CHECK(ic_before->ic_state() == DEFAULT); } @@ -3718,7 +4008,6 @@ UNINITIALIZED_TEST(ReleaseStackTraceData) { TEST(Regress159140) { i::FLAG_allow_natives_syntax = true; - i::FLAG_flush_code_incrementally = true; CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); Heap* heap = isolate->heap(); @@ -3780,7 +4069,6 @@ TEST(Regress159140) { TEST(Regress165495) { i::FLAG_allow_natives_syntax = true; - i::FLAG_flush_code_incrementally = true; CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); Heap* heap = isolate->heap(); @@ -3828,7 +4116,6 @@ TEST(Regress165495) { TEST(Regress169209) { i::FLAG_stress_compaction = false; i::FLAG_allow_natives_syntax = true; - i::FLAG_flush_code_incrementally = true; CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); @@ -3944,9 +4231,8 @@ TEST(Regress169928) { JSArray::kSize + AllocationMemento::kSize + kPointerSize); - Handle<JSArray> array = factory->NewJSArrayWithElements(array_data, - FAST_SMI_ELEMENTS, - NOT_TENURED); + Handle<JSArray> array = + factory->NewJSArrayWithElements(array_data, FAST_SMI_ELEMENTS); CHECK_EQ(Smi::FromInt(2), array->length()); CHECK(array->HasFastSmiOrObjectElements()); @@ -3954,8 +4240,9 @@ TEST(Regress169928) { // We need filler the size of AllocationMemento object, plus an extra // fill pointer value. HeapObject* obj = NULL; - AllocationResult allocation = CcTest::heap()->new_space()->AllocateRaw( - AllocationMemento::kSize + kPointerSize); + AllocationResult allocation = + CcTest::heap()->new_space()->AllocateRawUnaligned( + AllocationMemento::kSize + kPointerSize); CHECK(allocation.To(&obj)); Address addr_obj = obj->address(); CcTest::heap()->CreateFillerObjectAt( @@ -3977,7 +4264,6 @@ TEST(Regress168801) { i::FLAG_always_compact = true; i::FLAG_cache_optimized_code = false; i::FLAG_allow_natives_syntax = true; - i::FLAG_flush_code_incrementally = true; CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); Heap* heap = isolate->heap(); @@ -4034,7 +4320,6 @@ TEST(Regress173458) { i::FLAG_always_compact = true; i::FLAG_cache_optimized_code = false; i::FLAG_allow_natives_syntax = true; - i::FLAG_flush_code_incrementally = true; CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); Heap* heap = isolate->heap(); @@ -4119,7 +4404,7 @@ TEST(IncrementalMarkingStepMakesBigProgressWithLargeObjects) { "};" "f(10 * 1024 * 1024);"); IncrementalMarking* marking = CcTest::heap()->incremental_marking(); - if (marking->IsStopped()) marking->Start(); + if (marking->IsStopped()) marking->Start(Heap::kNoGCFlags); // This big step should be sufficient to mark the whole array. marking->Step(100 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD); DCHECK(marking->IsComplete() || @@ -4390,7 +4675,6 @@ static int GetCodeChainLength(Code* code) { TEST(NextCodeLinkIsWeak) { i::FLAG_always_opt = false; i::FLAG_allow_natives_syntax = true; - i::FLAG_turbo_deoptimization = true; CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); v8::internal::Heap* heap = CcTest::heap(); @@ -4705,9 +4989,8 @@ Handle<JSFunction> GetFunctionByName(Isolate* isolate, const char* name) { void CheckIC(Code* code, Code::Kind kind, SharedFunctionInfo* shared, int ic_slot, InlineCacheState state) { - if (FLAG_vector_ics && - (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC || - kind == Code::CALL_IC)) { + if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC || + kind == Code::CALL_IC) { TypeFeedbackVector* vector = shared->feedback_vector(); FeedbackVectorICSlot slot(ic_slot); if (kind == Code::LOAD_IC) { @@ -4849,7 +5132,7 @@ TEST(WeakCellsWithIncrementalMarking) { Handle<WeakCell> weak_cell = factory->NewWeakCell(value); CHECK(weak_cell->value()->IsFixedArray()); IncrementalMarking* marking = heap->incremental_marking(); - if (marking->IsStopped()) marking->Start(); + if (marking->IsStopped()) marking->Start(Heap::kNoGCFlags); marking->Step(128, IncrementalMarking::NO_GC_VIA_STACK_GUARD); heap->CollectGarbage(NEW_SPACE); CHECK(weak_cell->value()->IsFixedArray()); @@ -5117,7 +5400,7 @@ TEST(Regress388880) { // that would cause crash. IncrementalMarking* marking = CcTest::heap()->incremental_marking(); marking->Abort(); - marking->Start(); + marking->Start(Heap::kNoGCFlags); CHECK(marking->IsMarking()); // Now everything is set up for crashing in JSObject::MigrateFastToFast() @@ -5143,7 +5426,7 @@ TEST(Regress3631) { "}" "weak_map"); if (marking->IsStopped()) { - marking->Start(); + marking->Start(Heap::kNoGCFlags); } // Incrementally mark the backing store. Handle<JSObject> obj = @@ -5319,7 +5602,7 @@ static void TestRightTrimFixedTypedArray(i::ExternalArrayType type, Heap* heap = isolate->heap(); Handle<FixedTypedArrayBase> array = - factory->NewFixedTypedArray(initial_length, type); + factory->NewFixedTypedArray(initial_length, type, true); int old_size = array->size(); heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(*array, elements_to_trim); @@ -5369,7 +5652,7 @@ TEST(WeakFixedArray) { Handle<HeapNumber> number = CcTest::i_isolate()->factory()->NewHeapNumber(1); Handle<WeakFixedArray> array = WeakFixedArray::Add(Handle<Object>(), number); array->Remove(number); - array->Compact(); + array->Compact<WeakFixedArray::NullCallback>(); WeakFixedArray::Add(array, number); } @@ -5379,7 +5662,7 @@ TEST(PreprocessStackTrace) { FLAG_gc_interval = -1; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(CcTest::isolate()); CompileRun("throw new Error();"); CHECK(try_catch.HasCaught()); Isolate* isolate = CcTest::i_isolate(); @@ -5405,3 +5688,370 @@ TEST(PreprocessStackTrace) { CHECK(!element->IsCode()); } } + + +static bool utils_has_been_collected = false; + +static void UtilsHasBeenCollected( + const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) { + utils_has_been_collected = true; + data.GetParameter()->Reset(); +} + + +TEST(BootstrappingExports) { + FLAG_expose_natives_as = "natives"; + CcTest::InitializeVM(); + v8::Isolate* isolate = CcTest::isolate(); + + if (Snapshot::HaveASnapshotToStartFrom(CcTest::i_isolate())) return; + + utils_has_been_collected = false; + + v8::Persistent<v8::Object> utils; + + { + v8::HandleScope scope(isolate); + v8::Handle<v8::Object> natives = + CcTest::global()->Get(v8_str("natives"))->ToObject(isolate); + utils.Reset(isolate, natives->Get(v8_str("utils"))->ToObject(isolate)); + natives->Delete(v8_str("utils")); + } + + utils.SetWeak(&utils, UtilsHasBeenCollected, + v8::WeakCallbackType::kParameter); + + CcTest::heap()->CollectAllAvailableGarbage("fire weak callbacks"); + + CHECK(utils_has_been_collected); +} + + +TEST(Regress1878) { + FLAG_allow_natives_syntax = true; + CcTest::InitializeVM(); + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + v8::Local<v8::Function> constructor = + v8::Utils::ToLocal(CcTest::i_isolate()->internal_array_function()); + CcTest::global()->Set(v8_str("InternalArray"), constructor); + + v8::TryCatch try_catch(isolate); + + CompileRun( + "var a = Array();" + "for (var i = 0; i < 1000; i++) {" + " var ai = new InternalArray(10000);" + " if (%HaveSameMap(ai, a)) throw Error();" + " if (!%HasFastObjectElements(ai)) throw Error();" + "}" + "for (var i = 0; i < 1000; i++) {" + " var ai = new InternalArray(10000);" + " if (%HaveSameMap(ai, a)) throw Error();" + " if (!%HasFastObjectElements(ai)) throw Error();" + "}"); + + CHECK(!try_catch.HasCaught()); +} + + +void AllocateInSpace(Isolate* isolate, size_t bytes, AllocationSpace space) { + CHECK(bytes >= FixedArray::kHeaderSize); + CHECK(bytes % kPointerSize == 0); + Factory* factory = isolate->factory(); + HandleScope scope(isolate); + AlwaysAllocateScope always_allocate(isolate); + int elements = + static_cast<int>((bytes - FixedArray::kHeaderSize) / kPointerSize); + Handle<FixedArray> array = factory->NewFixedArray( + elements, space == NEW_SPACE ? NOT_TENURED : TENURED); + CHECK((space == NEW_SPACE) == isolate->heap()->InNewSpace(*array)); + CHECK_EQ(bytes, static_cast<size_t>(array->Size())); +} + + +TEST(NewSpaceAllocationCounter) { + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + Isolate* isolate = CcTest::i_isolate(); + Heap* heap = isolate->heap(); + size_t counter1 = heap->NewSpaceAllocationCounter(); + heap->CollectGarbage(NEW_SPACE); + const size_t kSize = 1024; + AllocateInSpace(isolate, kSize, NEW_SPACE); + size_t counter2 = heap->NewSpaceAllocationCounter(); + CHECK_EQ(kSize, counter2 - counter1); + heap->CollectGarbage(NEW_SPACE); + size_t counter3 = heap->NewSpaceAllocationCounter(); + CHECK_EQ(0U, counter3 - counter2); + // Test counter overflow. + size_t max_counter = -1; + heap->set_new_space_allocation_counter(max_counter - 10 * kSize); + size_t start = heap->NewSpaceAllocationCounter(); + for (int i = 0; i < 20; i++) { + AllocateInSpace(isolate, kSize, NEW_SPACE); + size_t counter = heap->NewSpaceAllocationCounter(); + CHECK_EQ(kSize, counter - start); + start = counter; + } +} + + +TEST(OldSpaceAllocationCounter) { + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + Isolate* isolate = CcTest::i_isolate(); + Heap* heap = isolate->heap(); + size_t counter1 = heap->OldGenerationAllocationCounter(); + heap->CollectGarbage(NEW_SPACE); + heap->CollectGarbage(NEW_SPACE); + const size_t kSize = 1024; + AllocateInSpace(isolate, kSize, OLD_SPACE); + size_t counter2 = heap->OldGenerationAllocationCounter(); + // TODO(ulan): replace all CHECK_LE with CHECK_EQ after v8:4148 is fixed. + CHECK_LE(kSize, counter2 - counter1); + heap->CollectGarbage(NEW_SPACE); + size_t counter3 = heap->OldGenerationAllocationCounter(); + CHECK_EQ(0u, counter3 - counter2); + AllocateInSpace(isolate, kSize, OLD_SPACE); + heap->CollectGarbage(OLD_SPACE); + size_t counter4 = heap->OldGenerationAllocationCounter(); + CHECK_LE(kSize, counter4 - counter3); + // Test counter overflow. + size_t max_counter = -1; + heap->set_old_generation_allocation_counter(max_counter - 10 * kSize); + size_t start = heap->OldGenerationAllocationCounter(); + for (int i = 0; i < 20; i++) { + AllocateInSpace(isolate, kSize, OLD_SPACE); + size_t counter = heap->OldGenerationAllocationCounter(); + CHECK_LE(kSize, counter - start); + start = counter; + } +} + + +TEST(NewSpaceAllocationThroughput) { + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + Isolate* isolate = CcTest::i_isolate(); + Heap* heap = isolate->heap(); + GCTracer* tracer = heap->tracer(); + int time1 = 100; + size_t counter1 = 1000; + tracer->SampleAllocation(time1, counter1, 0); + int time2 = 200; + size_t counter2 = 2000; + tracer->SampleAllocation(time2, counter2, 0); + size_t throughput = + tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(); + CHECK_EQ((counter2 - counter1) / (time2 - time1), throughput); + int time3 = 1000; + size_t counter3 = 30000; + tracer->SampleAllocation(time3, counter3, 0); + throughput = tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(); + CHECK_EQ((counter3 - counter1) / (time3 - time1), throughput); +} + + +TEST(NewSpaceAllocationThroughput2) { + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + Isolate* isolate = CcTest::i_isolate(); + Heap* heap = isolate->heap(); + GCTracer* tracer = heap->tracer(); + int time1 = 100; + size_t counter1 = 1000; + tracer->SampleAllocation(time1, counter1, 0); + int time2 = 200; + size_t counter2 = 2000; + tracer->SampleAllocation(time2, counter2, 0); + size_t throughput = + tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(100); + CHECK_EQ((counter2 - counter1) / (time2 - time1), throughput); + int time3 = 1000; + size_t counter3 = 30000; + tracer->SampleAllocation(time3, counter3, 0); + throughput = tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(100); + CHECK_EQ((counter3 - counter1) / (time3 - time1), throughput); +} + + +static void CheckLeak(const v8::FunctionCallbackInfo<v8::Value>& args) { + Isolate* isolate = CcTest::i_isolate(); + Object* message = + *reinterpret_cast<Object**>(isolate->pending_message_obj_address()); + CHECK(message->IsTheHole()); +} + + +TEST(MessageObjectLeak) { + CcTest::InitializeVM(); + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate); + global->Set(v8::String::NewFromUtf8(isolate, "check"), + v8::FunctionTemplate::New(isolate, CheckLeak)); + v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global); + v8::Context::Scope cscope(context); + + const char* test = + "try {" + " throw 'message 1';" + "} catch (e) {" + "}" + "check();" + "L: try {" + " throw 'message 2';" + "} finally {" + " break L;" + "}" + "check();"; + CompileRun(test); + + const char* flag = "--turbo-filter=*"; + FlagList::SetFlagsFromString(flag, StrLength(flag)); + FLAG_always_opt = true; + FLAG_turbo_try_catch = true; + FLAG_turbo_try_finally = true; + + CompileRun(test); +} + + +static void CheckEqualSharedFunctionInfos( + const v8::FunctionCallbackInfo<v8::Value>& args) { + Handle<Object> obj1 = v8::Utils::OpenHandle(*args[0]); + Handle<Object> obj2 = v8::Utils::OpenHandle(*args[1]); + Handle<JSFunction> fun1 = Handle<JSFunction>::cast(obj1); + Handle<JSFunction> fun2 = Handle<JSFunction>::cast(obj2); + CHECK(fun1->shared() == fun2->shared()); +} + + +static void RemoveCodeAndGC(const v8::FunctionCallbackInfo<v8::Value>& args) { + Isolate* isolate = CcTest::i_isolate(); + Handle<Object> obj = v8::Utils::OpenHandle(*args[0]); + Handle<JSFunction> fun = Handle<JSFunction>::cast(obj); + fun->ReplaceCode(*isolate->builtins()->CompileLazy()); + fun->shared()->ReplaceCode(*isolate->builtins()->CompileLazy()); + isolate->heap()->CollectAllAvailableGarbage("remove code and gc"); +} + + +TEST(CanonicalSharedFunctionInfo) { + CcTest::InitializeVM(); + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate); + global->Set(isolate, "check", v8::FunctionTemplate::New( + isolate, CheckEqualSharedFunctionInfos)); + global->Set(isolate, "remove", + v8::FunctionTemplate::New(isolate, RemoveCodeAndGC)); + v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global); + v8::Context::Scope cscope(context); + CompileRun( + "function f() { return function g() {}; }" + "var g1 = f();" + "remove(f);" + "var g2 = f();" + "check(g1, g2);"); + + CompileRun( + "function f() { return (function() { return function g() {}; })(); }" + "var g1 = f();" + "remove(f);" + "var g2 = f();" + "check(g1, g2);"); +} + + +TEST(OldGenerationAllocationThroughput) { + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + Isolate* isolate = CcTest::i_isolate(); + Heap* heap = isolate->heap(); + GCTracer* tracer = heap->tracer(); + int time1 = 100; + size_t counter1 = 1000; + tracer->SampleAllocation(time1, 0, counter1); + int time2 = 200; + size_t counter2 = 2000; + tracer->SampleAllocation(time2, 0, counter2); + size_t throughput = + tracer->OldGenerationAllocationThroughputInBytesPerMillisecond(100); + CHECK_EQ((counter2 - counter1) / (time2 - time1), throughput); + int time3 = 1000; + size_t counter3 = 30000; + tracer->SampleAllocation(time3, 0, counter3); + throughput = + tracer->OldGenerationAllocationThroughputInBytesPerMillisecond(100); + CHECK_EQ((counter3 - counter1) / (time3 - time1), throughput); +} + + +TEST(AllocationThroughput) { + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + Isolate* isolate = CcTest::i_isolate(); + Heap* heap = isolate->heap(); + GCTracer* tracer = heap->tracer(); + int time1 = 100; + size_t counter1 = 1000; + tracer->SampleAllocation(time1, counter1, counter1); + int time2 = 200; + size_t counter2 = 2000; + tracer->SampleAllocation(time2, counter2, counter2); + size_t throughput = tracer->AllocationThroughputInBytesPerMillisecond(100); + CHECK_EQ(2 * (counter2 - counter1) / (time2 - time1), throughput); + int time3 = 1000; + size_t counter3 = 30000; + tracer->SampleAllocation(time3, counter3, counter3); + throughput = tracer->AllocationThroughputInBytesPerMillisecond(100); + CHECK_EQ(2 * (counter3 - counter1) / (time3 - time1), throughput); +} + + +TEST(SlotsBufferObjectSlotsRemoval) { + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + Isolate* isolate = CcTest::i_isolate(); + Heap* heap = isolate->heap(); + Factory* factory = isolate->factory(); + + SlotsBuffer* buffer = new SlotsBuffer(NULL); + void* fake_object[1]; + + Handle<FixedArray> array = factory->NewFixedArray(2, TENURED); + CHECK(heap->old_space()->Contains(*array)); + array->set(0, reinterpret_cast<Object*>(fake_object), SKIP_WRITE_BARRIER); + + // Firstly, let's test the regular slots buffer entry. + buffer->Add(HeapObject::RawField(*array, FixedArray::kHeaderSize)); + DCHECK(reinterpret_cast<void*>(buffer->Get(0)) == + HeapObject::RawField(*array, FixedArray::kHeaderSize)); + SlotsBuffer::RemoveObjectSlots(CcTest::i_isolate()->heap(), buffer, + array->address(), + array->address() + array->Size()); + DCHECK(reinterpret_cast<void*>(buffer->Get(0)) == + HeapObject::RawField(heap->empty_fixed_array(), + FixedArrayBase::kLengthOffset)); + + // Secondly, let's test the typed slots buffer entry. + SlotsBuffer::AddTo(NULL, &buffer, SlotsBuffer::EMBEDDED_OBJECT_SLOT, + array->address() + FixedArray::kHeaderSize, + SlotsBuffer::FAIL_ON_OVERFLOW); + DCHECK(reinterpret_cast<void*>(buffer->Get(1)) == + reinterpret_cast<Object**>(SlotsBuffer::EMBEDDED_OBJECT_SLOT)); + DCHECK(reinterpret_cast<void*>(buffer->Get(2)) == + HeapObject::RawField(*array, FixedArray::kHeaderSize)); + SlotsBuffer::RemoveObjectSlots(CcTest::i_isolate()->heap(), buffer, + array->address(), + array->address() + array->Size()); + DCHECK(reinterpret_cast<void*>(buffer->Get(1)) == + HeapObject::RawField(heap->empty_fixed_array(), + FixedArrayBase::kLengthOffset)); + DCHECK(reinterpret_cast<void*>(buffer->Get(2)) == + HeapObject::RawField(heap->empty_fixed_array(), + FixedArrayBase::kLengthOffset)); + delete buffer; +} diff --git a/deps/v8/test/cctest/test-hydrogen-types.cc b/deps/v8/test/cctest/test-hydrogen-types.cc index 0ac53bde09..93fdf7b32d 100644 --- a/deps/v8/test/cctest/test-hydrogen-types.cc +++ b/deps/v8/test/cctest/test-hydrogen-types.cc @@ -8,7 +8,6 @@ using namespace v8::internal; - static const HType kTypes[] = { #define DECLARE_TYPE(Name, mask) HType::Name(), HTYPE_LIST(DECLARE_TYPE) diff --git a/deps/v8/test/cctest/test-log.cc b/deps/v8/test/cctest/test-log.cc index 90245b7882..0938a9ede2 100644 --- a/deps/v8/test/cctest/test-log.cc +++ b/deps/v8/test/cctest/test-log.cc @@ -482,7 +482,7 @@ TEST(EquivalenceOfLoggingAndTraversal) { i::Vector<const char> source = TestSources::GetScriptsSource(); v8::Handle<v8::String> source_str = v8::String::NewFromUtf8( isolate, source.start(), v8::String::kNormalString, source.length()); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); v8::Handle<v8::Script> script = CompileWithOrigin(source_str, ""); if (script.IsEmpty()) { v8::String::Utf8Value exception(try_catch.Exception()); diff --git a/deps/v8/test/cctest/test-microtask-delivery.cc b/deps/v8/test/cctest/test-microtask-delivery.cc index 601290cf3a..5befdfba9f 100644 --- a/deps/v8/test/cctest/test-microtask-delivery.cc +++ b/deps/v8/test/cctest/test-microtask-delivery.cc @@ -29,7 +29,6 @@ #include "test/cctest/cctest.h" -using namespace v8; namespace i = v8::internal; namespace { @@ -38,7 +37,7 @@ class HarmonyIsolate { HarmonyIsolate() { v8::Isolate::CreateParams create_params; create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); - isolate_ = Isolate::New(create_params); + isolate_ = v8::Isolate::New(create_params); isolate_->Enter(); } @@ -47,17 +46,17 @@ class HarmonyIsolate { isolate_->Dispose(); } - Isolate* GetIsolate() const { return isolate_; } + v8::Isolate* GetIsolate() const { return isolate_; } private: - Isolate* isolate_; + v8::Isolate* isolate_; }; } TEST(MicrotaskDeliverySimple) { HarmonyIsolate isolate; - HandleScope scope(isolate.GetIsolate()); + v8::HandleScope scope(isolate.GetIsolate()); LocalContext context(isolate.GetIsolate()); CompileRun( "var ordering = [];" @@ -95,16 +94,16 @@ TEST(MicrotaskDeliverySimple) { TEST(MicrotaskPerIsolateState) { HarmonyIsolate isolate; - HandleScope scope(isolate.GetIsolate()); + v8::HandleScope scope(isolate.GetIsolate()); LocalContext context1(isolate.GetIsolate()); isolate.GetIsolate()->SetAutorunMicrotasks(false); CompileRun( "var obj = { calls: 0 };"); - Handle<Value> obj = CompileRun("obj"); + v8::Handle<v8::Value> obj = CompileRun("obj"); { LocalContext context2(isolate.GetIsolate()); - context2->Global()->Set(String::NewFromUtf8(isolate.GetIsolate(), "obj"), - obj); + context2->Global()->Set( + v8::String::NewFromUtf8(isolate.GetIsolate(), "obj"), obj); CompileRun( "var resolver = {};" "new Promise(function(resolve) {" @@ -118,8 +117,8 @@ TEST(MicrotaskPerIsolateState) { } { LocalContext context3(isolate.GetIsolate()); - context3->Global()->Set(String::NewFromUtf8(isolate.GetIsolate(), "obj"), - obj); + context3->Global()->Set( + v8::String::NewFromUtf8(isolate.GetIsolate(), "obj"), obj); CompileRun( "var foo = { id: 1 };" "Object.observe(foo, function() {" @@ -129,8 +128,8 @@ TEST(MicrotaskPerIsolateState) { } { LocalContext context4(isolate.GetIsolate()); - context4->Global()->Set(String::NewFromUtf8(isolate.GetIsolate(), "obj"), - obj); + context4->Global()->Set( + v8::String::NewFromUtf8(isolate.GetIsolate(), "obj"), obj); isolate.GetIsolate()->RunMicrotasks(); CHECK_EQ(2, CompileRun("obj.calls")->Int32Value()); } diff --git a/deps/v8/test/cctest/test-migrations.cc b/deps/v8/test/cctest/test-migrations.cc index 14bdcea3c6..0cefd54ceb 100644 --- a/deps/v8/test/cctest/test-migrations.cc +++ b/deps/v8/test/cctest/test-migrations.cc @@ -503,8 +503,7 @@ TEST(ReconfigureAccessorToNonExistingDataFieldHeavy) { CHECK(obj->map()->instance_descriptors()->GetValue(0)->IsAccessorPair()); Handle<Object> value(Smi::FromInt(42), isolate); - JSObject::SetOwnPropertyIgnoreAttributes( - obj, foo_str, value, NONE, JSObject::DONT_FORCE_FIELD).ToHandleChecked(); + JSObject::SetOwnPropertyIgnoreAttributes(obj, foo_str, value, NONE).Check(); // Check that the property contains |value|. CHECK_EQ(1, obj->map()->NumberOfOwnDescriptors()); diff --git a/deps/v8/test/cctest/test-parsing.cc b/deps/v8/test/cctest/test-parsing.cc index 58a5955685..cbb79b16da 100644 --- a/deps/v8/test/cctest/test-parsing.cc +++ b/deps/v8/test/cctest/test-parsing.cc @@ -73,7 +73,6 @@ TEST(ScanKeywords) { i::Scanner scanner(&unicode_cache); // The scanner should parse Harmony keywords for this test. scanner.SetHarmonyModules(true); - scanner.SetHarmonyClasses(true); scanner.Initialize(&stream); CHECK_EQ(key_token.token, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next()); @@ -277,7 +276,7 @@ TEST(PreparseFunctionDataIsUsed) { for (unsigned i = 0; i < arraysize(good_code); i++) { v8::ScriptCompiler::Source good_source(v8_str(good_code[i])); v8::ScriptCompiler::Compile(isolate, &good_source, - v8::ScriptCompiler::kProduceDataToCache); + v8::ScriptCompiler::kProduceParserCache); const v8::ScriptCompiler::CachedData* cached_data = good_source.GetCachedData(); @@ -291,7 +290,9 @@ TEST(PreparseFunctionDataIsUsed) { v8_str(bad_code[i]), new v8::ScriptCompiler::CachedData( cached_data->data, cached_data->length)); v8::Local<v8::Value> result = - v8::ScriptCompiler::Compile(isolate, &bad_source)->Run(); + v8::ScriptCompiler::Compile(isolate, &bad_source, + v8::ScriptCompiler::kConsumeParserCache) + ->Run(); CHECK(result->IsInt32()); CHECK_EQ(25, result->Int32Value()); } @@ -976,10 +977,10 @@ TEST(ScopeUsesArgumentsSuperThis) { SUPER_PROPERTY = 1 << 1, THIS = 1 << 2, INNER_ARGUMENTS = 1 << 3, - INNER_SUPER_PROPERTY = 1 << 4, - INNER_THIS = 1 << 5 + EVAL = 1 << 4 }; + // clang-format off static const struct { const char* body; int expected; @@ -992,8 +993,8 @@ TEST(ScopeUsesArgumentsSuperThis) { {"return this + arguments[0]", ARGUMENTS | THIS}, {"return this + arguments[0] + super.x", ARGUMENTS | SUPER_PROPERTY | THIS}, - {"return x => this + x", INNER_THIS}, - {"return x => super.f() + x", INNER_SUPER_PROPERTY}, + {"return x => this + x", THIS}, + {"return x => super.f() + x", SUPER_PROPERTY}, {"this.foo = 42;", THIS}, {"this.foo();", THIS}, {"if (foo()) { this.f() }", THIS}, @@ -1006,9 +1007,7 @@ TEST(ScopeUsesArgumentsSuperThis) { {"while (true) { while (true) { while (true) return this } }", THIS}, {"while (true) { while (true) { while (true) return super.f() } }", SUPER_PROPERTY}, - {"if (1) { return () => { while (true) new this() } }", INNER_THIS}, - // Note that propagation of the inner_uses_this() value does not - // cross boundaries of normal functions onto parent scopes. + {"if (1) { return () => { while (true) new this() } }", THIS}, {"return function (x) { return this + x }", NONE}, {"return { m(x) { return super.m() + x } }", NONE}, {"var x = function () { this.foo = 42 };", NONE}, @@ -1019,17 +1018,22 @@ TEST(ScopeUsesArgumentsSuperThis) { {"return { m(x) { return () => super.m() } }", NONE}, // Flags must be correctly set when using block scoping. {"\"use strict\"; while (true) { let x; this, arguments; }", - INNER_ARGUMENTS | INNER_THIS}, + INNER_ARGUMENTS | THIS}, {"\"use strict\"; while (true) { let x; this, super.f(), arguments; }", - INNER_ARGUMENTS | INNER_SUPER_PROPERTY | INNER_THIS}, - {"\"use strict\"; if (foo()) { let x; this.f() }", INNER_THIS}, - {"\"use strict\"; if (foo()) { let x; super.f() }", - INNER_SUPER_PROPERTY}, + INNER_ARGUMENTS | SUPER_PROPERTY | THIS}, + {"\"use strict\"; if (foo()) { let x; this.f() }", THIS}, + {"\"use strict\"; if (foo()) { let x; super.f() }", SUPER_PROPERTY}, {"\"use strict\"; if (1) {" " let x; return { m() { return this + super.m() + arguments } }" "}", NONE}, + {"eval(42)", EVAL}, + {"if (1) { eval(42) }", EVAL}, + {"eval('super.x')", EVAL}, + {"eval('this.x')", EVAL}, + {"eval('arguments')", EVAL}, }; + // clang-format on i::Isolate* isolate = CcTest::i_isolate(); i::Factory* factory = isolate->factory(); @@ -1045,7 +1049,6 @@ TEST(ScopeUsesArgumentsSuperThis) { for (unsigned i = 0; i < arraysize(source_data); ++i) { // Super property is only allowed in constructor and method. if (((source_data[i].expected & SUPER_PROPERTY) || - (source_data[i].expected & INNER_SUPER_PROPERTY) || (source_data[i].expected == NONE)) && j != 2) { continue; } @@ -1063,8 +1066,6 @@ TEST(ScopeUsesArgumentsSuperThis) { i::ParseInfo info(&zone, script); i::Parser parser(&info); parser.set_allow_harmony_arrow_functions(true); - parser.set_allow_harmony_classes(true); - parser.set_allow_harmony_object_literals(true); parser.set_allow_harmony_sloppy(true); info.set_global(); CHECK(parser.Parse(&info)); @@ -1086,18 +1087,71 @@ TEST(ScopeUsesArgumentsSuperThis) { scope->uses_arguments()); CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0, scope->uses_super_property()); - CHECK_EQ((source_data[i].expected & THIS) != 0, scope->uses_this()); + if ((source_data[i].expected & THIS) != 0) { + // Currently the is_used() flag is conservative; all variables in a + // script scope are marked as used. + CHECK(scope->LookupThis()->is_used()); + } CHECK_EQ((source_data[i].expected & INNER_ARGUMENTS) != 0, scope->inner_uses_arguments()); - CHECK_EQ((source_data[i].expected & INNER_SUPER_PROPERTY) != 0, - scope->inner_uses_super_property()); - CHECK_EQ((source_data[i].expected & INNER_THIS) != 0, - scope->inner_uses_this()); + CHECK_EQ((source_data[i].expected & EVAL) != 0, scope->calls_eval()); } } } +static void CheckParsesToNumber(const char* source, bool with_dot) { + v8::V8::Initialize(); + HandleAndZoneScope handles; + + i::Isolate* isolate = CcTest::i_isolate(); + i::Factory* factory = isolate->factory(); + + std::string full_source = "function f() { return "; + full_source += source; + full_source += "; }"; + + i::Handle<i::String> source_code = + factory->NewStringFromUtf8(i::CStrVector(full_source.c_str())) + .ToHandleChecked(); + + i::Handle<i::Script> script = factory->NewScript(source_code); + + i::ParseInfo info(handles.main_zone(), script); + i::Parser parser(&info); + parser.set_allow_harmony_arrow_functions(true); + parser.set_allow_harmony_sloppy(true); + info.set_global(); + info.set_lazy(false); + info.set_allow_lazy_parsing(false); + info.set_toplevel(true); + + i::CompilationInfo compilation_info(&info); + CHECK(i::Compiler::ParseAndAnalyze(&info)); + + CHECK(info.scope()->declarations()->length() == 1); + i::FunctionLiteral* fun = + info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun(); + CHECK(fun->body()->length() == 1); + CHECK(fun->body()->at(0)->IsReturnStatement()); + i::ReturnStatement* ret = fun->body()->at(0)->AsReturnStatement(); + CHECK(ret->expression()->IsLiteral()); + i::Literal* lit = ret->expression()->AsLiteral(); + const i::AstValue* val = lit->raw_value(); + CHECK(with_dot == val->ContainsDot()); +} + + +TEST(ParseNumbers) { + CheckParsesToNumber("1.34", true); + CheckParsesToNumber("134", false); + CheckParsesToNumber("134e44", false); + CheckParsesToNumber("134.e44", true); + CheckParsesToNumber("134.44e44", true); + CheckParsesToNumber(".44", true); +} + + TEST(ScopePositions) { // Test the parser for correctly setting the start and end positions // of a scope. We check the scope positions of exactly one scope @@ -1348,40 +1402,24 @@ const char* ReadString(unsigned* start) { i::Handle<i::String> FormatMessage(i::Vector<unsigned> data) { i::Isolate* isolate = CcTest::i_isolate(); - i::Factory* factory = isolate->factory(); - const char* message = - ReadString(&data[i::PreparseDataConstants::kMessageTextPos]); - i::Handle<i::String> format = v8::Utils::OpenHandle( - *v8::String::NewFromUtf8(CcTest::isolate(), message)); + int message = data[i::PreparseDataConstants::kMessageTemplatePos]; int arg_count = data[i::PreparseDataConstants::kMessageArgCountPos]; - const char* arg = NULL; - i::Handle<i::JSArray> args_array; + i::Handle<i::Object> arg_object; if (arg_count == 1) { // Position after text found by skipping past length field and // length field content words. - int pos = i::PreparseDataConstants::kMessageTextPos + 1 + - data[i::PreparseDataConstants::kMessageTextPos]; - arg = ReadString(&data[pos]); - args_array = factory->NewJSArray(1); - i::JSArray::SetElement(args_array, 0, v8::Utils::OpenHandle(*v8_str(arg)), - NONE, i::SLOPPY).Check(); + const char* arg = + ReadString(&data[i::PreparseDataConstants::kMessageArgPos]); + arg_object = + v8::Utils::OpenHandle(*v8::String::NewFromUtf8(CcTest::isolate(), arg)); + i::DeleteArray(arg); } else { CHECK_EQ(0, arg_count); - args_array = factory->NewJSArray(0); + arg_object = isolate->factory()->undefined_value(); } - i::Handle<i::JSObject> builtins(isolate->js_builtins_object()); - i::Handle<i::Object> format_fun = - i::Object::GetProperty(isolate, builtins, "$formatMessage") - .ToHandleChecked(); - i::Handle<i::Object> arg_handles[] = { format, args_array }; - i::Handle<i::Object> result = i::Execution::Call( - isolate, format_fun, builtins, 2, arg_handles).ToHandleChecked(); - CHECK(result->IsString()); - i::DeleteArray(message); - i::DeleteArray(arg); data.Dispose(); - return i::Handle<i::String>::cast(result); + return i::MessageTemplate::FormatMessage(isolate, message, arg_object); } @@ -1390,15 +1428,16 @@ enum ParserFlag { kAllowNatives, kAllowHarmonyModules, kAllowHarmonyArrowFunctions, - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, kAllowHarmonyRestParameters, kAllowHarmonySloppy, kAllowHarmonyUnicode, kAllowHarmonyComputedPropertyNames, kAllowHarmonySpreadCalls, kAllowHarmonyDestructuring, - kAllowStrongMode + kAllowHarmonySpreadArrays, + kAllowHarmonyNewTarget, + kAllowStrongMode, + kNoLegacyConst }; @@ -1414,11 +1453,8 @@ void SetParserFlags(i::ParserBase<Traits>* parser, parser->set_allow_lazy(flags.Contains(kAllowLazy)); parser->set_allow_natives(flags.Contains(kAllowNatives)); parser->set_allow_harmony_modules(flags.Contains(kAllowHarmonyModules)); - parser->set_allow_harmony_object_literals( - flags.Contains(kAllowHarmonyObjectLiterals)); parser->set_allow_harmony_arrow_functions( flags.Contains(kAllowHarmonyArrowFunctions)); - parser->set_allow_harmony_classes(flags.Contains(kAllowHarmonyClasses)); parser->set_allow_harmony_rest_params( flags.Contains(kAllowHarmonyRestParameters)); parser->set_allow_harmony_spreadcalls( @@ -1429,7 +1465,11 @@ void SetParserFlags(i::ParserBase<Traits>* parser, flags.Contains(kAllowHarmonyComputedPropertyNames)); parser->set_allow_harmony_destructuring( flags.Contains(kAllowHarmonyDestructuring)); + parser->set_allow_harmony_spread_arrays( + flags.Contains(kAllowHarmonySpreadArrays)); + parser->set_allow_harmony_new_target(flags.Contains(kAllowHarmonyNewTarget)); parser->set_allow_strong_mode(flags.Contains(kAllowStrongMode)); + parser->set_allow_legacy_const(!flags.Contains(kNoLegacyConst)); } @@ -1702,7 +1742,7 @@ TEST(StrictOctal) { v8::HandleScope scope(CcTest::isolate()); v8::Context::Scope context_scope( v8::Context::New(CcTest::isolate())); - v8::TryCatch try_catch; + v8::TryCatch try_catch(CcTest::isolate()); const char* script = "\"use strict\"; \n" "a = function() { \n" @@ -1982,8 +2022,7 @@ TEST(NoErrorsFutureStrictReservedWords) { RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0, always_flags, arraysize(always_flags)); - static const ParserFlag classes_flags[] = {kAllowHarmonyArrowFunctions, - kAllowHarmonyClasses}; + static const ParserFlag classes_flags[] = {kAllowHarmonyArrowFunctions}; RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0, classes_flags, arraysize(classes_flags)); } @@ -2996,10 +3035,7 @@ TEST(NoErrorsDeclsInCase) { nullptr }; - static const ParserFlag always_flags[] = {kAllowHarmonyClasses}; - - RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); + RunParserSyncTest(context_data, statement_data, kSuccess); } @@ -3579,6 +3615,10 @@ TEST(ErrorsArrowFunctions) { "(foo ? bar : baz) => {}", "(a, foo ? bar : baz) => {}", "(foo ? bar : baz, a) => {}", + "(a.b, c) => {}", + "(c, a.b) => {}", + "(a['b'], c) => {}", + "(c, a['b']) => {}", NULL }; @@ -3727,8 +3767,6 @@ TEST(SuperNoErrors) { static const ParserFlag always_flags[] = { kAllowHarmonyArrowFunctions, - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy }; RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0, @@ -3759,11 +3797,7 @@ TEST(SuperErrors) { NULL }; - static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, - kAllowHarmonySloppy - }; + static const ParserFlag always_flags[] = {kAllowHarmonySloppy}; RunParserSyncTest(context_data, expression_data, kError, NULL, 0, always_flags, arraysize(always_flags)); } @@ -3779,12 +3813,8 @@ TEST(SuperCall) { NULL }; - static const ParserFlag always_flags[] = { - kAllowHarmonyArrowFunctions, - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, - kAllowHarmonySloppy - }; + static const ParserFlag always_flags[] = {kAllowHarmonyArrowFunctions, + kAllowHarmonySloppy}; RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0, always_flags, arraysize(always_flags)); @@ -3834,12 +3864,8 @@ TEST(SuperNewNoErrors) { NULL }; - static const ParserFlag always_flags[] = { - kAllowHarmonyArrowFunctions, - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, - kAllowHarmonySloppy - }; + static const ParserFlag always_flags[] = {kAllowHarmonyArrowFunctions, + kAllowHarmonySloppy}; RunParserSyncTest(context_data, expression_data, kSuccess, NULL, 0, always_flags, arraysize(always_flags)); } @@ -3872,12 +3898,8 @@ TEST(SuperNewErrors) { NULL }; - static const ParserFlag always_flags[] = { - kAllowHarmonyArrowFunctions, - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, - kAllowHarmonySloppy - }; + static const ParserFlag always_flags[] = {kAllowHarmonyArrowFunctions, + kAllowHarmonySloppy}; RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags, arraysize(always_flags)); } @@ -3918,8 +3940,6 @@ TEST(SuperErrorsNonMethods) { }; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy }; RunParserSyncTest(context_data, statement_data, kError, NULL, 0, @@ -3943,9 +3963,7 @@ TEST(NoErrorsMethodDefinition) { NULL }; - static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals}; - RunParserSyncTest(context_data, object_literal_body_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); + RunParserSyncTest(context_data, object_literal_body_data, kSuccess); } @@ -4019,9 +4037,7 @@ TEST(MethodDefinitionNames) { NULL }; - static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals}; - RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); + RunParserSyncTest(context_data, name_data, kSuccess); } @@ -4040,9 +4056,7 @@ TEST(MethodDefinitionStrictFormalParamereters) { NULL }; - static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals}; - RunParserSyncTest(context_data, params_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); + RunParserSyncTest(context_data, params_data, kError); } @@ -4061,15 +4075,11 @@ TEST(MethodDefinitionEvalArguments) { "arguments", NULL}; - static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals}; - // Fail in strict mode - RunParserSyncTest(strict_context_data, data, kError, NULL, 0, always_flags, - arraysize(always_flags)); + RunParserSyncTest(strict_context_data, data, kError); // OK in sloppy mode - RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, always_flags, - arraysize(always_flags)); + RunParserSyncTest(sloppy_context_data, data, kSuccess); } @@ -4088,12 +4098,9 @@ TEST(MethodDefinitionDuplicateEvalArguments) { "arguments, a, arguments", NULL}; - static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals}; - // In strict mode, the error is using "eval" or "arguments" as parameter names // In sloppy mode, the error is that eval / arguments are duplicated - RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags, - arraysize(always_flags)); + RunParserSyncTest(context_data, data, kError); } @@ -4127,9 +4134,7 @@ TEST(MethodDefinitionDuplicateProperty) { NULL }; - static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals}; - RunParserSyncTest(context_data, params_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); + RunParserSyncTest(context_data, params_data, kSuccess); } @@ -4151,8 +4156,7 @@ TEST(ClassExpressionNoErrors) { "class name extends class base {} {}", NULL}; - static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, kAllowHarmonySloppy}; + static const ParserFlag always_flags[] = {kAllowHarmonySloppy}; RunParserSyncTest(context_data, class_data, kSuccess, NULL, 0, always_flags, arraysize(always_flags)); } @@ -4171,9 +4175,7 @@ TEST(ClassDeclarationNoErrors) { "class name extends class base {} {}", NULL}; - static const ParserFlag always_flags[] = {kAllowHarmonyClasses}; - RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); + RunParserSyncTest(context_data, statement_data, kSuccess); } @@ -4215,8 +4217,6 @@ TEST(ClassBodyNoErrors) { NULL}; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy }; RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0, @@ -4274,8 +4274,6 @@ TEST(ClassPropertyNameNoErrors) { NULL}; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy }; RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0, @@ -4306,8 +4304,6 @@ TEST(ClassExpressionErrors) { NULL}; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy }; RunParserSyncTest(context_data, class_data, kError, NULL, 0, @@ -4344,7 +4340,6 @@ TEST(ClassDeclarationErrors) { NULL}; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, kAllowHarmonySloppy }; RunParserSyncTest(context_data, class_data, kError, NULL, 0, @@ -4374,8 +4369,6 @@ TEST(ClassNameErrors) { NULL}; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy }; RunParserSyncTest(context_data, class_name, kError, NULL, 0, @@ -4408,8 +4401,6 @@ TEST(ClassGetterParamNameErrors) { NULL}; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy }; RunParserSyncTest(context_data, class_name, kError, NULL, 0, @@ -4437,8 +4428,6 @@ TEST(ClassStaticPrototypeErrors) { NULL}; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy }; RunParserSyncTest(context_data, class_body_data, kError, NULL, 0, @@ -4465,8 +4454,6 @@ TEST(ClassSpecialConstructorErrors) { NULL}; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy }; RunParserSyncTest(context_data, class_body_data, kError, NULL, 0, @@ -4488,8 +4475,6 @@ TEST(ClassConstructorNoErrors) { NULL}; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy }; RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0, @@ -4507,8 +4492,6 @@ TEST(ClassMultipleConstructorErrors) { NULL}; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy }; RunParserSyncTest(context_data, class_body_data, kError, NULL, 0, @@ -4530,8 +4513,6 @@ TEST(ClassMultiplePropertyNamesNoErrors) { NULL}; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy }; RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0, @@ -4551,8 +4532,6 @@ TEST(ClassesAreStrictErrors) { NULL}; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy }; RunParserSyncTest(context_data, class_body_data, kError, NULL, 0, @@ -4605,9 +4584,7 @@ TEST(ObjectLiteralPropertyShorthandKeywordsError) { NULL }; - static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals}; - RunParserSyncTest(context_data, name_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); + RunParserSyncTest(context_data, name_data, kError); } @@ -4628,14 +4605,11 @@ TEST(ObjectLiteralPropertyShorthandStrictKeywords) { NULL }; - static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals}; - RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); + RunParserSyncTest(context_data, name_data, kSuccess); const char* context_strict_data[][2] = {{"'use strict'; ({", "});"}, {NULL, NULL}}; - RunParserSyncTest(context_strict_data, name_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); + RunParserSyncTest(context_strict_data, name_data, kError); } @@ -4657,9 +4631,7 @@ TEST(ObjectLiteralPropertyShorthandError) { NULL }; - static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals}; - RunParserSyncTest(context_data, name_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); + RunParserSyncTest(context_data, name_data, kError); } @@ -4672,9 +4644,7 @@ TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) { NULL }; - static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals}; - RunParserSyncTest(context_data, name_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); + RunParserSyncTest(context_data, name_data, kError); } @@ -5136,6 +5106,24 @@ TEST(ParseRestParametersErrors) { } +TEST(RestParameterInSetterMethodError) { + const char* context_data[][2] = { + {"'use strict';({ set prop(", ") {} }).prop = 1;"}, + {"'use strict';(class { static set prop(", ") {} }).prop = 1;"}, + {"'use strict';(new (class { set prop(", ") {} })).prop = 1;"}, + {"({ set prop(", ") {} }).prop = 1;"}, + {"(class { static set prop(", ") {} }).prop = 1;"}, + {"(new (class { set prop(", ") {} })).prop = 1;"}, + {nullptr, nullptr}}; + const char* data[] = {"...a", "...arguments", "...eval", nullptr}; + + static const ParserFlag always_flags[] = {kAllowHarmonyRestParameters, + kAllowHarmonySloppy}; + RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags, + arraysize(always_flags)); +} + + TEST(RestParametersEvalArguments) { const char* strict_context_data[][2] = {{"'use strict';(function(", @@ -5253,18 +5241,15 @@ TEST(LexicalScopingSloppyMode) { "(class C {})", "(class C extends D {})", NULL}; - static const ParserFlag always_true_flags[] = {kAllowHarmonyClasses}; static const ParserFlag always_false_flags[] = {kAllowHarmonySloppy}; - RunParserSyncTest(context_data, bad_data, kError, NULL, 0, - always_true_flags, arraysize(always_true_flags), + RunParserSyncTest(context_data, bad_data, kError, NULL, 0, NULL, 0, always_false_flags, arraysize(always_false_flags)); const char* good_data[] = { "let = 1;", "for(let = 1;;){}", NULL}; - RunParserSyncTest(context_data, good_data, kSuccess, NULL, 0, - always_true_flags, arraysize(always_true_flags), + RunParserSyncTest(context_data, good_data, kSuccess, NULL, 0, NULL, 0, always_false_flags, arraysize(always_false_flags)); } @@ -5286,9 +5271,7 @@ TEST(ComputedPropertyName) { NULL}; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, kAllowHarmonyComputedPropertyNames, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy, }; RunParserSyncTest(context_data, error_data, kError, NULL, 0, @@ -5317,9 +5300,7 @@ TEST(ComputedPropertyNameShorthandError) { NULL}; static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, kAllowHarmonyComputedPropertyNames, - kAllowHarmonyObjectLiterals, kAllowHarmonySloppy, }; RunParserSyncTest(context_data, error_data, kError, NULL, 0, @@ -5387,7 +5368,6 @@ TEST(BasicImportExportParsing) { i::Zone zone; i::ParseInfo info(&zone, script); i::Parser parser(&info); - parser.set_allow_harmony_classes(true); parser.set_allow_harmony_modules(true); info.set_module(); if (!parser.Parse(&info)) { @@ -5414,7 +5394,6 @@ TEST(BasicImportExportParsing) { i::Zone zone; i::ParseInfo info(&zone, script); i::Parser parser(&info); - parser.set_allow_harmony_classes(true); parser.set_allow_harmony_modules(true); info.set_global(); CHECK(!parser.Parse(&info)); @@ -5504,7 +5483,6 @@ TEST(ImportExportParsingErrors) { i::Zone zone; i::ParseInfo info(&zone, script); i::Parser parser(&info); - parser.set_allow_harmony_classes(true); parser.set_allow_harmony_modules(true); info.set_module(); CHECK(!parser.Parse(&info)); @@ -5617,7 +5595,6 @@ TEST(DuplicateProtoNoError) { static const ParserFlag always_flags[] = { kAllowHarmonyComputedPropertyNames, - kAllowHarmonyObjectLiterals, }; RunParserSyncTest(context_data, error_data, kSuccess, NULL, 0, always_flags, arraysize(always_flags)); @@ -5645,8 +5622,7 @@ TEST(DeclarationsError) { "class C {}", NULL}; - static const ParserFlag always_flags[] = {kAllowHarmonyClasses, - kAllowStrongMode}; + static const ParserFlag always_flags[] = {kAllowStrongMode}; RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags, arraysize(always_flags)); } @@ -5730,8 +5706,7 @@ TEST(PropertyNameEvalArguments) { NULL}; - static const ParserFlag always_flags[] = { - kAllowHarmonyClasses, kAllowHarmonyObjectLiterals, kAllowStrongMode}; + static const ParserFlag always_flags[] = {kAllowStrongMode}; RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0, always_flags, arraysize(always_flags)); } @@ -5915,10 +5890,8 @@ TEST(StrongConstructorThis) { "class C { constructor() { label: 0; this.a = 0; this.b = 6; } }", NULL}; - static const ParserFlag always_flags[] = { - kAllowStrongMode, kAllowHarmonyClasses, kAllowHarmonyObjectLiterals, - kAllowHarmonyArrowFunctions - }; + static const ParserFlag always_flags[] = {kAllowStrongMode, + kAllowHarmonyArrowFunctions}; RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0, always_flags, arraysize(always_flags)); RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0, @@ -5971,10 +5944,8 @@ TEST(StrongConstructorSuper) { "class C extends Object { constructor() { 3; super(3); this.x = 0; } }", NULL}; - static const ParserFlag always_flags[] = { - kAllowStrongMode, kAllowHarmonyClasses, kAllowHarmonyObjectLiterals, - kAllowHarmonyArrowFunctions - }; + static const ParserFlag always_flags[] = {kAllowStrongMode, + kAllowHarmonyArrowFunctions}; RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0, always_flags, arraysize(always_flags)); RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0, @@ -6019,9 +5990,7 @@ TEST(StrongConstructorReturns) { "class C extends Array { constructor() { super(); this.a = 9; return } }", NULL}; - static const ParserFlag always_flags[] = { - kAllowStrongMode, kAllowHarmonyClasses, kAllowHarmonyObjectLiterals - }; + static const ParserFlag always_flags[] = {kAllowStrongMode}; RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0, always_flags, arraysize(always_flags)); RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0, @@ -6219,7 +6188,7 @@ TEST(StrongModeFreeVariablesDeclaredByPreviousScript) { v8::V8::Initialize(); v8::HandleScope scope(CcTest::isolate()); v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate())); - v8::TryCatch try_catch; + v8::TryCatch try_catch(CcTest::isolate()); // Introduce a bunch of variables, in all language modes. const char* script1 = @@ -6278,7 +6247,7 @@ TEST(StrongModeFreeVariablesDeclaredByLanguage) { v8::V8::Initialize(); v8::HandleScope scope(CcTest::isolate()); v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate())); - v8::TryCatch try_catch; + v8::TryCatch try_catch(CcTest::isolate()); const char* script1 = "\"use strong\"; \n" @@ -6294,7 +6263,7 @@ TEST(StrongModeFreeVariablesDeclaredInGlobalPrototype) { v8::V8::Initialize(); v8::HandleScope scope(CcTest::isolate()); v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate())); - v8::TryCatch try_catch; + v8::TryCatch try_catch(CcTest::isolate()); const char* script1 = "this.__proto__.my_var = 0;\n"; CompileRun(v8_str(script1)); @@ -6313,7 +6282,7 @@ TEST(StrongModeFreeVariablesNotDeclared) { v8::V8::Initialize(); v8::HandleScope scope(CcTest::isolate()); v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate())); - v8::TryCatch try_catch; + v8::TryCatch try_catch(CcTest::isolate()); // Test that referencing unintroduced variables in sloppy mode is ok. const char* script1 = @@ -6330,7 +6299,7 @@ TEST(StrongModeFreeVariablesNotDeclared) { "if (false) { \n" " not_there2; \n" "} \n"; - v8::TryCatch try_catch2; + v8::TryCatch try_catch2(CcTest::isolate()); v8::Script::Compile(v8_str(script2)); CHECK(try_catch2.HasCaught()); v8::String::Utf8Value exception(try_catch2.Exception()); @@ -6351,7 +6320,7 @@ TEST(StrongModeFreeVariablesNotDeclared) { " not_there3; \n" " } \n" "})(); \n"; - v8::TryCatch try_catch2; + v8::TryCatch try_catch2(CcTest::isolate()); v8::Script::Compile(v8_str(script3)); CHECK(try_catch2.HasCaught()); v8::String::Utf8Value exception(try_catch2.Exception()); @@ -6366,30 +6335,59 @@ TEST(StrongModeFreeVariablesNotDeclared) { TEST(DestructuringPositiveTests) { i::FLAG_harmony_destructuring = true; + i::FLAG_harmony_arrow_functions = true; + i::FLAG_harmony_computed_property_names = true; const char* context_data[][2] = {{"'use strict'; let ", " = {};"}, {"var ", " = {};"}, {"'use strict'; const ", " = {};"}, + {"function f(", ") {}"}, + {"function f(argument1, ", ") {}"}, + {"var f = (", ") => {};"}, + {"var f = (argument1,", ") => {};"}, {NULL, NULL}}; // clang-format off const char* data[] = { "a", "{ x : y }", + "{ x : y = 1 }", "[a]", + "[a = 1]", "[a,b,c]", + "[a, b = 42, c]", "{ x : x, y : y }", + "{ x : x = 1, y : y }", + "{ x : x, y : y = 42 }", "[]", "{}", "[{x:x, y:y}, [a,b,c]]", + "[{x:x = 1, y:y = 2}, [a = 3, b = 4, c = 5]]", + "{x}", + "{x, y}", + "{x = 42, y = 15}", "[a,,b]", "{42 : x}", + "{42 : x = 42}", "{42e-2 : x}", + "{42e-2 : x = 42}", + "{x : y, x : z}", "{'hi' : x}", + "{'hi' : x = 42}", "{var: x}", + "{var: x = 42}", + "{[x] : z}", + "{[1+1] : z}", + "{[foo()] : z}", + "{}", + "[...rest]", + "[a,b,...rest]", + "[a,,...rest]", NULL}; // clang-format on - static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring}; + static const ParserFlag always_flags[] = {kAllowHarmonyComputedPropertyNames, + kAllowHarmonyArrowFunctions, + kAllowHarmonyDestructuring}; RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags, arraysize(always_flags)); } @@ -6397,12 +6395,21 @@ TEST(DestructuringPositiveTests) { TEST(DestructuringNegativeTests) { i::FLAG_harmony_destructuring = true; - static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring}; + i::FLAG_harmony_arrow_functions = true; + i::FLAG_harmony_computed_property_names = true; + static const ParserFlag always_flags[] = {kAllowHarmonyComputedPropertyNames, + kAllowHarmonyArrowFunctions, + kAllowHarmonyDestructuring}; { // All modes. const char* context_data[][2] = {{"'use strict'; let ", " = {};"}, {"var ", " = {};"}, {"'use strict'; const ", " = {};"}, + {"function f(", ") {}"}, + {"function f(argument1, ", ") {}"}, + {"var f = (", ") => {};"}, + {"var f = ", " => {};"}, + {"var f = (argument1,", ") => {};"}, {NULL, NULL}}; // clang-format off @@ -6435,7 +6442,6 @@ TEST(DestructuringNegativeTests) { "a >>> a", "function a() {}", "a`bcd`", - "x => x", "this", "null", "true", @@ -6443,25 +6449,61 @@ TEST(DestructuringNegativeTests) { "1", "'abc'", "class {}", - "() => x", "{+2 : x}", "{-2 : x}", "var", "[var]", "{x : {y : var}}", + "{x : x = a+}", + "{x : x = (a+)}", + "{x : x += a}", + "{m() {} = 0}", + "{[1+1]}", + "[...rest, x]", + "[a,b,...rest, x]", + "[a,,...rest, x]", + "[...rest,]", + "[a,b,...rest,]", + "[a,,...rest,]", + "[...rest,...rest1]", + "[a,b,...rest,...rest1]", + "[a,,..rest,...rest1]", NULL}; // clang-format on RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags, arraysize(always_flags)); } - { // Strict mode. + { // All modes. const char* context_data[][2] = {{"'use strict'; let ", " = {};"}, + {"var ", " = {};"}, {"'use strict'; const ", " = {};"}, + {"function f(", ") {}"}, + {"function f(argument1, ", ") {}"}, + {"var f = (", ") => {};"}, + {"var f = (argument1,", ") => {};"}, {NULL, NULL}}; // clang-format off const char* data[] = { + "x => x", + "() => x", + NULL}; + // clang-format on + RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags, + arraysize(always_flags)); + } + + { // Strict mode. + const char* context_data[][2] = { + {"'use strict'; let ", " = {};"}, + {"'use strict'; const ", " = {};"}, + {"'use strict'; function f(", ") {}"}, + {"'use strict'; function f(argument1, ", ") {}"}, + {NULL, NULL}}; + + // clang-format off + const char* data[] = { "[eval]", "{ a : arguments }", "[public]", @@ -6490,3 +6532,261 @@ TEST(DestructuringNegativeTests) { arraysize(always_flags)); } } + + +TEST(DestructuringDisallowPatternsInForVarIn) { + i::FLAG_harmony_destructuring = true; + static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring}; + const char* context_data[][2] = { + {"", ""}, {"function f() {", "}"}, {NULL, NULL}}; + // clang-format off + const char* error_data[] = { + "for (let x = {} in null);", + "for (let x = {} of null);", + NULL}; + // clang-format on + RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags, + arraysize(always_flags)); + + // clang-format off + const char* success_data[] = { + "for (var x = {} in null);", + NULL}; + // clang-format on + RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0, always_flags, + arraysize(always_flags)); +} + + +TEST(DestructuringDuplicateParams) { + i::FLAG_harmony_destructuring = true; + i::FLAG_harmony_arrow_functions = true; + i::FLAG_harmony_computed_property_names = true; + static const ParserFlag always_flags[] = {kAllowHarmonyComputedPropertyNames, + kAllowHarmonyArrowFunctions, + kAllowHarmonyDestructuring}; + const char* context_data[][2] = {{"'use strict';", ""}, + {"function outer() { 'use strict';", "}"}, + {nullptr, nullptr}}; + + + // clang-format off + const char* error_data[] = { + "function f(x,x){}", + "function f(x, {x : x}){}", + "function f(x, {x}){}", + "function f({x,x}) {}", + "function f([x,x]) {}", + "function f(x, [y,{z:x}]) {}", + "function f([x,{y:x}]) {}", + // non-simple parameter list causes duplicates to be errors in sloppy mode. + "function f(x, x, {a}) {}", + nullptr}; + // clang-format on + RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags, + arraysize(always_flags)); +} + + +TEST(DestructuringDuplicateParamsSloppy) { + i::FLAG_harmony_destructuring = true; + i::FLAG_harmony_arrow_functions = true; + i::FLAG_harmony_computed_property_names = true; + static const ParserFlag always_flags[] = {kAllowHarmonyComputedPropertyNames, + kAllowHarmonyArrowFunctions, + kAllowHarmonyDestructuring}; + const char* context_data[][2] = { + {"", ""}, {"function outer() {", "}"}, {nullptr, nullptr}}; + + + // clang-format off + const char* error_data[] = { + // non-simple parameter list causes duplicates to be errors in sloppy mode. + "function f(x, {x : x}){}", + "function f(x, {x}){}", + "function f({x,x}) {}", + "function f(x, x, {a}) {}", + nullptr}; + // clang-format on + RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags, + arraysize(always_flags)); +} + + +TEST(DestructuringDisallowPatternsInSingleParamArrows) { + i::FLAG_harmony_destructuring = true; + i::FLAG_harmony_arrow_functions = true; + i::FLAG_harmony_computed_property_names = true; + static const ParserFlag always_flags[] = {kAllowHarmonyComputedPropertyNames, + kAllowHarmonyArrowFunctions, + kAllowHarmonyDestructuring}; + const char* context_data[][2] = {{"'use strict';", ""}, + {"function outer() { 'use strict';", "}"}, + {"", ""}, + {"function outer() { ", "}"}, + {nullptr, nullptr}}; + + // clang-format off + const char* error_data[] = { + "var f = {x} => {};", + "var f = {x,y} => {};", + nullptr}; + // clang-format on + RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags, + arraysize(always_flags)); +} + + +TEST(DestructuringDisallowPatternsInRestParams) { + i::FLAG_harmony_destructuring = true; + i::FLAG_harmony_arrow_functions = true; + i::FLAG_harmony_rest_parameters = true; + i::FLAG_harmony_computed_property_names = true; + static const ParserFlag always_flags[] = { + kAllowHarmonyComputedPropertyNames, kAllowHarmonyArrowFunctions, + kAllowHarmonyRestParameters, kAllowHarmonyDestructuring}; + const char* context_data[][2] = {{"'use strict';", ""}, + {"function outer() { 'use strict';", "}"}, + {"", ""}, + {"function outer() { ", "}"}, + {nullptr, nullptr}}; + + // clang-format off + const char* error_data[] = { + "function(...{}) {}", + "function(...{x}) {}", + "function(...[x]) {}", + "(...{}) => {}", + "(...{x}) => {}", + "(...[x]) => {}", + nullptr}; + // clang-format on + RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags, + arraysize(always_flags)); +} + + +TEST(SpreadArray) { + i::FLAG_harmony_spread_arrays = true; + + const char* context_data[][2] = { + {"'use strict';", ""}, {"", ""}, {NULL, NULL}}; + + // clang-format off + const char* data[] = { + "[...a]", + "[a, ...b]", + "[...a,]", + "[...a, ,]", + "[, ...a]", + "[...a, ...b]", + "[...a, , ...b]", + "[...[...a]]", + "[, ...a]", + "[, , ...a]", + NULL}; + // clang-format on + static const ParserFlag always_flags[] = {kAllowHarmonySpreadArrays}; + RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags, + arraysize(always_flags)); +} + + +TEST(SpreadArrayError) { + i::FLAG_harmony_spread_arrays = true; + + const char* context_data[][2] = { + {"'use strict';", ""}, {"", ""}, {NULL, NULL}}; + + // clang-format off + const char* data[] = { + "[...]", + "[a, ...]", + "[..., ]", + "[..., ...]", + "[ (...a)]", + NULL}; + // clang-format on + static const ParserFlag always_flags[] = {kAllowHarmonySpreadArrays}; + RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags, + arraysize(always_flags)); +} + + +TEST(NewTarget) { + // clang-format off + const char* good_context_data[][2] = { + {"function f() {", "}"}, + {"'use strict'; function f() {", "}"}, + {"var f = function() {", "}"}, + {"'use strict'; var f = function() {", "}"}, + {"({m: function() {", "}})"}, + {"'use strict'; ({m: function() {", "}})"}, + {"({m() {", "}})"}, + {"'use strict'; ({m() {", "}})"}, + {"({get x() {", "}})"}, + {"'use strict'; ({get x() {", "}})"}, + {"({set x(_) {", "}})"}, + {"'use strict'; ({set x(_) {", "}})"}, + {"class C {m() {", "}}"}, + {"class C {get x() {", "}}"}, + {"class C {set x(_) {", "}}"}, + {NULL} + }; + + const char* bad_context_data[][2] = { + {"", ""}, + {"'use strict';", ""}, + {NULL} + }; + + const char* data[] = { + "new.target", + "{ new.target }", + "() => { new.target }", + "() => new.target", + "if (1) { new.target }", + "if (1) {} else { new.target }", + "while (0) { new.target }", + "do { new.target } while (0)", + NULL + }; + + static const ParserFlag always_flags[] = { + kAllowHarmonyArrowFunctions, + kAllowHarmonyNewTarget, + kAllowHarmonySloppy, + }; + // clang-format on + + RunParserSyncTest(good_context_data, data, kSuccess, NULL, 0, always_flags, + arraysize(always_flags)); + RunParserSyncTest(bad_context_data, data, kError, NULL, 0, always_flags, + arraysize(always_flags)); +} + + +TEST(LegacyConst) { + // clang-format off + const char* context_data[][2] = { + {"", ""}, + {"{", "}"}, + {NULL, NULL} + }; + + const char* data[] = { + "const x", + "const x = 1", + "for (const x = 1; x < 1; x++) {}", + "for (const x in {}) {}", + "for (const x of []) {}", + NULL + }; + // clang-format on + + static const ParserFlag always_flags[] = {kNoLegacyConst}; + + RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags, + arraysize(always_flags)); + RunParserSyncTest(context_data, data, kSuccess); +} diff --git a/deps/v8/test/cctest/test-profile-generator.cc b/deps/v8/test/cctest/test-profile-generator.cc index 0a2c7a5625..221761487c 100644 --- a/deps/v8/test/cctest/test-profile-generator.cc +++ b/deps/v8/test/cctest/test-profile-generator.cc @@ -681,14 +681,13 @@ TEST(BailoutReason) { CHECK_EQ(0, iprofiler->GetProfilesCount()); v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), - "function TryCatch() {\n" - " try {\n" - " startProfiling();\n" - " } catch (e) { };\n" + "function Debugger() {\n" + " debugger;\n" + " startProfiling();\n" "}\n" "function TryFinally() {\n" " try {\n" - " TryCatch();\n" + " Debugger();\n" " } finally { };\n" "}\n" "TryFinally();\n" @@ -703,8 +702,8 @@ TEST(BailoutReason) { // The tree should look like this: // (root) // "" - // kTryFinally - // kTryCatch + // kTryFinallyStatement + // kDebuggerStatement current = PickChild(current, ""); CHECK(const_cast<v8::CpuProfileNode*>(current)); @@ -712,7 +711,7 @@ TEST(BailoutReason) { CHECK(const_cast<v8::CpuProfileNode*>(current)); CHECK(!strcmp("TryFinallyStatement", current->GetBailoutReason())); - current = PickChild(current, "TryCatch"); + current = PickChild(current, "Debugger"); CHECK(const_cast<v8::CpuProfileNode*>(current)); - CHECK(!strcmp("TryCatchStatement", current->GetBailoutReason())); + CHECK(!strcmp("DebuggerStatement", current->GetBailoutReason())); } diff --git a/deps/v8/test/cctest/test-reloc-info.cc b/deps/v8/test/cctest/test-reloc-info.cc index a238c3a7d8..829fd24f4d 100644 --- a/deps/v8/test/cctest/test-reloc-info.cc +++ b/deps/v8/test/cctest/test-reloc-info.cc @@ -66,8 +66,8 @@ TEST(Positions) { writer.Finish(); relocation_info_size = static_cast<int>(buffer_end - writer.pos()); - CodeDesc desc = { buffer.get(), buffer_size, code_size, - relocation_info_size, NULL }; + CodeDesc desc = {buffer.get(), buffer_size, code_size, relocation_info_size, + 0, NULL}; // Read only (non-statement) positions. { @@ -120,4 +120,5 @@ TEST(Positions) { } } -} } // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/cctest/test-serialize.cc b/deps/v8/test/cctest/test-serialize.cc index 938178efb9..0bae94e219 100644 --- a/deps/v8/test/cctest/test-serialize.cc +++ b/deps/v8/test/cctest/test-serialize.cc @@ -493,7 +493,7 @@ UNINITIALIZED_DEPENDENT_TEST(ContextDeserialization, ContextSerialization) { &outdated_contexts).ToHandleChecked(); CHECK(root->IsContext()); CHECK(Handle<Context>::cast(root)->global_proxy() == *global_proxy); - CHECK_EQ(1, outdated_contexts->length()); + CHECK_EQ(2, outdated_contexts->length()); } Handle<Object> root2; @@ -628,13 +628,13 @@ UNINITIALIZED_DEPENDENT_TEST(CustomContextDeserialization, root = deserializer.DeserializePartial(isolate, global_proxy, &outdated_contexts).ToHandleChecked(); - CHECK_EQ(2, outdated_contexts->length()); + CHECK_EQ(3, outdated_contexts->length()); CHECK(root->IsContext()); Handle<Context> context = Handle<Context>::cast(root); CHECK(context->global_proxy() == *global_proxy); Handle<String> o = isolate->factory()->NewStringFromAsciiChecked("o"); Handle<JSObject> global_object(context->global_object(), isolate); - Handle<Object> property = JSObject::GetDataProperty(global_object, o); + Handle<Object> property = JSReceiver::GetDataProperty(global_object, o); CHECK(property.is_identical_to(global_proxy)); v8::Handle<v8::Context> v8_context = v8::Utils::ToLocal(context); @@ -859,7 +859,7 @@ static Handle<SharedFunctionInfo> CompileScript( Isolate* isolate, Handle<String> source, Handle<String> name, ScriptData** cached_data, v8::ScriptCompiler::CompileOptions options) { return Compiler::CompileScript( - source, name, 0, 0, false, false, Handle<Object>(), + source, name, 0, 0, v8::ScriptOriginOptions(), Handle<Object>(), Handle<Context>(isolate->native_context()), NULL, cached_data, options, NOT_NATIVES_CODE, false); } @@ -938,7 +938,7 @@ TEST(CodeCachePromotedToCompilationCache) { isolate, src, src, &cache, v8::ScriptCompiler::kConsumeCodeCache); CHECK(isolate->compilation_cache() - ->LookupScript(src, src, 0, 0, false, false, + ->LookupScript(src, src, 0, 0, v8::ScriptOriginOptions(), isolate->native_context(), SLOPPY) .ToHandleChecked() .is_identical_to(copy)); @@ -1098,11 +1098,11 @@ TEST(SerializeToplevelLargeStrings) { Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked(); CHECK_EQ(6 * 1999999, Handle<String>::cast(copy_result)->length()); - Handle<Object> property = JSObject::GetDataProperty( + Handle<Object> property = JSReceiver::GetDataProperty( isolate->global_object(), f->NewStringFromAsciiChecked("s")); CHECK(isolate->heap()->InSpace(HeapObject::cast(*property), LO_SPACE)); - property = JSObject::GetDataProperty(isolate->global_object(), - f->NewStringFromAsciiChecked("t")); + property = JSReceiver::GetDataProperty(isolate->global_object(), + f->NewStringFromAsciiChecked("t")); CHECK(isolate->heap()->InSpace(HeapObject::cast(*property), LO_SPACE)); // Make sure we do not serialize too much, e.g. include the source string. CHECK_LT(cache->length(), 13000000); @@ -1595,7 +1595,6 @@ TEST(SerializeInternalReference) { return; #endif // Disable experimental natives that are loaded after deserialization. - FLAG_turbo_deoptimization = false; FLAG_context_specialization = false; FLAG_always_opt = true; const char* flag = "--turbo-filter=foo"; @@ -1659,6 +1658,31 @@ TEST(SerializeInternalReference) { } +TEST(Regress503552) { + // Test that the code serializer can deal with weak cells that form a linked + // list during incremental marking. + + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + + HandleScope scope(isolate); + Handle<String> source = isolate->factory()->NewStringFromAsciiChecked( + "function f() {} function g() {}"); + ScriptData* script_data = NULL; + Handle<SharedFunctionInfo> shared = Compiler::CompileScript( + source, Handle<String>(), 0, 0, v8::ScriptOriginOptions(), + Handle<Object>(), Handle<Context>(isolate->native_context()), NULL, + &script_data, v8::ScriptCompiler::kProduceCodeCache, NOT_NATIVES_CODE, + false); + delete script_data; + + SimulateIncrementalMarking(isolate->heap()); + + script_data = CodeSerializer::Serialize(isolate, shared, source); + delete script_data; +} + + TEST(SerializationMemoryStats) { FLAG_profile_deserialization = true; FLAG_always_opt = false; diff --git a/deps/v8/test/cctest/test-spaces.cc b/deps/v8/test/cctest/test-spaces.cc index 9d22327831..3f5e437223 100644 --- a/deps/v8/test/cctest/test-spaces.cc +++ b/deps/v8/test/cctest/test-spaces.cc @@ -145,7 +145,8 @@ class TestCodeRangeScope { DISALLOW_COPY_AND_ASSIGN(TestCodeRangeScope); }; -} } // namespace v8::internal +} // namespace internal +} // namespace v8 static void VerifyMemoryChunk(Isolate* isolate, @@ -358,8 +359,9 @@ TEST(NewSpace) { CHECK(new_space.HasBeenSetUp()); while (new_space.Available() >= Page::kMaxRegularHeapObjectSize) { - Object* obj = new_space.AllocateRaw( - Page::kMaxRegularHeapObjectSize).ToObjectChecked(); + Object* obj = + new_space.AllocateRawUnaligned(Page::kMaxRegularHeapObjectSize) + .ToObjectChecked(); CHECK(new_space.Contains(HeapObject::cast(obj))); } @@ -384,7 +386,7 @@ TEST(OldSpace) { CHECK(s->SetUp()); while (s->Available() > 0) { - s->AllocateRaw(Page::kMaxRegularHeapObjectSize).ToObjectChecked(); + s->AllocateRawUnaligned(Page::kMaxRegularHeapObjectSize).ToObjectChecked(); } s->TearDown(); @@ -437,6 +439,9 @@ TEST(SizeOfFirstPageIsLargeEnough) { if (!isolate->snapshot_available()) return; if (Snapshot::EmbedsScript(isolate)) return; + // If this test fails due to enabling experimental natives that are not part + // of the snapshot, we may need to adjust CalculateFirstPageSizes. + // Freshly initialized VM gets by with one page per space. for (int i = FIRST_PAGED_SPACE; i <= LAST_PAGED_SPACE; i++) { // Debug code can be very large, so skip CODE_SPACE if we are generating it. @@ -485,7 +490,8 @@ UNINITIALIZED_TEST(NewSpaceGrowsToTargetCapacity) { // Try to allocate out of the new space. A new page should be added and // the // allocation should succeed. - v8::internal::AllocationResult allocation = new_space->AllocateRaw(80); + v8::internal::AllocationResult allocation = + new_space->AllocateRawUnaligned(80); CHECK(!allocation.IsRetry()); CHECK(new_space->CommittedMemory() == 2 * Page::kPageSize); diff --git a/deps/v8/test/cctest/test-strings.cc b/deps/v8/test/cctest/test-strings.cc index 1713e91662..d8d7c96871 100644 --- a/deps/v8/test/cctest/test-strings.cc +++ b/deps/v8/test/cctest/test-strings.cc @@ -1222,7 +1222,7 @@ UNINITIALIZED_TEST(OneByteArrayJoin) { // summing the lengths of the strings (as Smis) overflows and wraps. LocalContext context(isolate); v8::HandleScope scope(isolate); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CHECK(CompileRun( "var two_14 = Math.pow(2, 14);" "var two_17 = Math.pow(2, 17);" diff --git a/deps/v8/test/cctest/test-thread-termination.cc b/deps/v8/test/cctest/test-thread-termination.cc index 250e9a344a..c0cc1cb8d1 100644 --- a/deps/v8/test/cctest/test-thread-termination.cc +++ b/deps/v8/test/cctest/test-thread-termination.cc @@ -61,7 +61,7 @@ void Loop(const v8::FunctionCallbackInfo<v8::Value>& args) { void DoLoop(const v8::FunctionCallbackInfo<v8::Value>& args) { - v8::TryCatch try_catch; + v8::TryCatch try_catch(args.GetIsolate()); CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate())); v8::Script::Compile(v8::String::NewFromUtf8(args.GetIsolate(), "function f() {" @@ -86,7 +86,7 @@ void DoLoop(const v8::FunctionCallbackInfo<v8::Value>& args) { void DoLoopNoCall(const v8::FunctionCallbackInfo<v8::Value>& args) { - v8::TryCatch try_catch; + v8::TryCatch try_catch(args.GetIsolate()); CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate())); v8::Script::Compile(v8::String::NewFromUtf8(args.GetIsolate(), "var term = true;" @@ -217,7 +217,7 @@ void TerminateOrReturnObject(const v8::FunctionCallbackInfo<v8::Value>& args) { void LoopGetProperty(const v8::FunctionCallbackInfo<v8::Value>& args) { - v8::TryCatch try_catch; + v8::TryCatch try_catch(args.GetIsolate()); CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate())); v8::Script::Compile( v8::String::NewFromUtf8(args.GetIsolate(), @@ -275,7 +275,7 @@ v8::Persistent<v8::String> reenter_script_1; v8::Persistent<v8::String> reenter_script_2; void ReenterAfterTermination(const v8::FunctionCallbackInfo<v8::Value>& args) { - v8::TryCatch try_catch; + v8::TryCatch try_catch(args.GetIsolate()); v8::Isolate* isolate = args.GetIsolate(); CHECK(!v8::V8::IsExecutionTerminating(isolate)); v8::Local<v8::String> script = @@ -328,7 +328,7 @@ TEST(TerminateAndReenterFromThreadItself) { void DoLoopCancelTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) { - v8::TryCatch try_catch; + v8::TryCatch try_catch(args.GetIsolate()); CHECK(!v8::V8::IsExecutionTerminating()); v8::Script::Compile(v8::String::NewFromUtf8(args.GetIsolate(), "var term = true;" @@ -426,7 +426,7 @@ TEST(PostponeTerminateException) { v8::Context::New(CcTest::isolate(), NULL, global); v8::Context::Scope context_scope(context); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); static const char* terminate_and_loop = "terminate(); for (var i = 0; i < 10000; i++);"; @@ -504,7 +504,7 @@ TEST(TerminationInInnerTryCall) { v8::Context::New(CcTest::isolate(), NULL, global_template); v8::Context::Scope context_scope(context); { - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CompileRun("inner_try_call_terminate()"); CHECK(try_catch.HasTerminated()); } @@ -522,7 +522,7 @@ TEST(TerminateAndTryCall) { v8::Handle<v8::Context> context = v8::Context::New(isolate, NULL, global); v8::Context::Scope context_scope(context); CHECK(!v8::V8::IsExecutionTerminating(isolate)); - v8::TryCatch try_catch; + v8::TryCatch try_catch(isolate); CHECK(!v8::V8::IsExecutionTerminating(isolate)); // Terminate execution has been triggered inside TryCall, but re-requested // to trigger later. diff --git a/deps/v8/test/cctest/test-threads.cc b/deps/v8/test/cctest/test-threads.cc index e192bc1559..5f2cdae2a2 100644 --- a/deps/v8/test/cctest/test-threads.cc +++ b/deps/v8/test/cctest/test-threads.cc @@ -32,12 +32,7 @@ #include "src/isolate.h" -enum Turn { - FILL_CACHE, - CLEAN_CACHE, - SECOND_TIME_FILL_CACHE, - DONE -}; +enum Turn { FILL_CACHE, CLEAN_CACHE, SECOND_TIME_FILL_CACHE, CACHE_DONE }; static Turn turn = FILL_CACHE; @@ -76,7 +71,7 @@ class ThreadA : public v8::base::Thread { // Rerun the script. CHECK(script->Run()->IsTrue()); - turn = DONE; + turn = CACHE_DONE; } }; @@ -116,7 +111,7 @@ TEST(JSFunctionResultCachesInTwoThreads) { threadA.Join(); threadB.Join(); - CHECK_EQ(DONE, turn); + CHECK_EQ(CACHE_DONE, turn); } class ThreadIdValidationThread : public v8::base::Thread { diff --git a/deps/v8/test/cctest/test-typedarrays.cc b/deps/v8/test/cctest/test-typedarrays.cc index d371673b9e..394f6194fd 100644 --- a/deps/v8/test/cctest/test-typedarrays.cc +++ b/deps/v8/test/cctest/test-typedarrays.cc @@ -48,7 +48,7 @@ TEST(CopyContentsArray) { LocalContext env; v8::HandleScope scope(env->GetIsolate()); CompileRun("var a = new Uint8Array([0, 1, 2, 3]);"); - TestArrayBufferViewContents(env, true); + TestArrayBufferViewContents(env, false); } diff --git a/deps/v8/test/cctest/test-types.cc b/deps/v8/test/cctest/test-types.cc index 295cef6d36..fe07093077 100644 --- a/deps/v8/test/cctest/test-types.cc +++ b/deps/v8/test/cctest/test-types.cc @@ -1020,15 +1020,10 @@ struct Tests : Rep { CheckSub(T.Proxy, T.Receiver); CheckSub(T.OtherObject, T.Object); CheckSub(T.Undetectable, T.Object); - CheckSub(T.DetectableObject, T.Object); - CheckSub(T.GlobalObject, T.DetectableObject); - CheckSub(T.OtherObject, T.DetectableObject); - CheckSub(T.GlobalObject, T.Object); - CheckSub(T.GlobalObject, T.Receiver); + CheckSub(T.OtherObject, T.Object); CheckUnordered(T.Object, T.Proxy); - CheckUnordered(T.GlobalObject, T.OtherObject); - CheckUnordered(T.DetectableObject, T.Undetectable); + CheckUnordered(T.OtherObject, T.Undetectable); // Subtyping between concrete structural types @@ -1350,7 +1345,6 @@ struct Tests : Rep { CheckDisjoint(T.InternalizedString, T.Symbol); CheckOverlap(T.Object, T.Receiver); CheckOverlap(T.OtherObject, T.Object); - CheckOverlap(T.GlobalObject, T.Object); CheckOverlap(T.Proxy, T.Receiver); CheckDisjoint(T.Object, T.Proxy); @@ -1505,6 +1499,7 @@ struct Tests : Rep { void Union3() { // Monotonicity: T1->Is(T2) or T1->Is(T3) implies T1->Is(Union(T2, T3)) for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) { + HandleScope scope(isolate); for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) { for (TypeIterator it3 = it2; it3 != T.types.end(); ++it3) { TypeHandle type1 = *it1; @@ -1757,6 +1752,7 @@ struct Tests : Rep { // Monotonicity: T1->Is(T2) and T1->Is(T3) implies T1->Is(Intersect(T2, T3)) for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) { + HandleScope scope(isolate); for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) { for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) { TypeHandle type1 = *it1; @@ -1963,66 +1959,6 @@ struct Tests : Rep { } } } - - void GlobalObjectType() { - i::Handle<i::Context> context1 = v8::Utils::OpenHandle( - *v8::Context::New(reinterpret_cast<v8::Isolate*>(isolate))); - Handle<i::GlobalObject> global_object1(context1->global_object()); - TypeHandle GlobalObjectConstant1 = - Type::Constant(global_object1, Rep::ToRegion(&zone, isolate)); - - i::Handle<i::Context> context2 = v8::Utils::OpenHandle( - *v8::Context::New(reinterpret_cast<v8::Isolate*>(isolate))); - Handle<i::GlobalObject> global_object2(context2->global_object()); - TypeHandle GlobalObjectConstant2 = - Type::Constant(global_object2, Rep::ToRegion(&zone, isolate)); - - CheckSub(GlobalObjectConstant1, T.DetectableObject); - CheckSub(GlobalObjectConstant2, T.DetectableObject); - CheckSub(GlobalObjectConstant1, T.GlobalObject); - CheckSub(GlobalObjectConstant2, T.GlobalObject); - CheckSub(GlobalObjectConstant1, T.Object); - CheckSub(GlobalObjectConstant2, T.Object); - - CheckUnordered(T.GlobalObject, T.OtherObject); - CheckUnordered(GlobalObjectConstant1, T.OtherObject); - CheckUnordered(GlobalObjectConstant2, T.OtherObject); - CheckUnordered(GlobalObjectConstant1, GlobalObjectConstant2); - - CheckDisjoint(T.GlobalObject, T.ObjectClass); - CheckDisjoint(GlobalObjectConstant1, T.ObjectClass); - CheckDisjoint(GlobalObjectConstant2, T.ArrayClass); - - CheckUnordered(T.Union(T.ObjectClass, T.ArrayClass), T.GlobalObject); - CheckUnordered(T.Union(T.ObjectClass, T.ArrayClass), GlobalObjectConstant1); - CheckUnordered(T.Union(T.ObjectClass, T.ArrayClass), GlobalObjectConstant2); - - CheckUnordered(T.Union(T.ObjectConstant1, T.ArrayClass), T.GlobalObject); - CheckUnordered(T.Union(T.ObjectConstant1, T.ArrayClass), - GlobalObjectConstant1); - CheckUnordered(T.Union(T.ObjectConstant1, T.ArrayClass), - GlobalObjectConstant2); - - CheckUnordered(T.Union(T.ObjectClass, T.String), T.GlobalObject); - - CheckSub(T.Union(T.ObjectConstant1, T.ArrayClass), - T.Union(T.GlobalObject, T.Object)); - - CheckDisjoint(T.Union(GlobalObjectConstant1, T.ArrayClass), - GlobalObjectConstant2); - - CheckEqual(T.Union(T.Union(T.Number, GlobalObjectConstant1), - T.Union(T.SignedSmall, T.GlobalObject)), - T.Union(T.Number, T.GlobalObject)); - - CheckEqual(T.Semantic(T.Intersect(T.ObjectClass, T.GlobalObject)), T.None); - - CHECK(!T.Intersect(T.ArrayClass, GlobalObjectConstant2)->IsInhabited()); - - CheckEqual(T.Intersect(T.Union(T.Number, T.OtherObject), - T.Union(T.Signed32, T.GlobalObject)), - T.Signed32); - } }; typedef Tests<Type, Type*, Zone, ZoneRep> ZoneTests; @@ -2197,9 +2133,3 @@ TEST(HTypeFromType_zone) { ZoneTests().HTypeFromType(); } TEST(HTypeFromType_heap) { HeapTests().HTypeFromType(); } - - -TEST(GlobalObjectType_zone) { ZoneTests().GlobalObjectType(); } - - -TEST(GlobalObjectType_heap) { HeapTests().GlobalObjectType(); } diff --git a/deps/v8/test/cctest/test-unboxed-doubles.cc b/deps/v8/test/cctest/test-unboxed-doubles.cc index 89f58a62e4..4746e47322 100644 --- a/deps/v8/test/cctest/test-unboxed-doubles.cc +++ b/deps/v8/test/cctest/test-unboxed-doubles.cc @@ -1035,7 +1035,7 @@ TEST(DoScavenge) { CcTest::heap()->CollectGarbage(i::NEW_SPACE); // Create temp object in the new space. - Handle<JSArray> temp = factory->NewJSArray(FAST_ELEMENTS, NOT_TENURED); + Handle<JSArray> temp = factory->NewJSArray(FAST_ELEMENTS); CHECK(isolate->heap()->new_space()->Contains(*temp)); // Construct a double value that looks like a pointer to the new space object @@ -1088,7 +1088,8 @@ TEST(DoScavengeWithIncrementalWriteBarrier) { AlwaysAllocateScope always_allocate(isolate); // Make sure |obj_value| is placed on an old-space evacuation candidate. SimulateFullSpace(old_space); - obj_value = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, TENURED); + obj_value = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, + Strength::WEAK, TENURED); ec_page = Page::FromAddress(obj_value->address()); } @@ -1373,7 +1374,7 @@ TEST(StoreBufferScanOnScavenge) { CHECK(isolate->heap()->old_space()->Contains(*obj)); // Create temp object in the new space. - Handle<JSArray> temp = factory->NewJSArray(FAST_ELEMENTS, NOT_TENURED); + Handle<JSArray> temp = factory->NewJSArray(FAST_ELEMENTS); CHECK(isolate->heap()->new_space()->Contains(*temp)); // Construct a double value that looks like a pointer to the new space object @@ -1572,7 +1573,8 @@ static void TestIncrementalWriteBarrier(Handle<Map> map, Handle<Map> new_map, // Make sure |obj_value| is placed on an old-space evacuation candidate. SimulateFullSpace(old_space); - obj_value = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, TENURED); + obj_value = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, + Strength::WEAK, TENURED); ec_page = Page::FromAddress(obj_value->address()); CHECK_NE(ec_page, Page::FromAddress(obj->address())); } diff --git a/deps/v8/test/cctest/test-utils-arm64.h b/deps/v8/test/cctest/test-utils-arm64.h index d00ad5e78c..a091bf3932 100644 --- a/deps/v8/test/cctest/test-utils-arm64.h +++ b/deps/v8/test/cctest/test-utils-arm64.h @@ -96,13 +96,13 @@ class RegisterDump { return dump_.sp_; } - inline int64_t wspreg() const { + inline int32_t wspreg() const { DCHECK(SPRegAliasesMatch()); - return dump_.wsp_; + return static_cast<int32_t>(dump_.wsp_); } // Flags accessors. - inline uint64_t flags_nzcv() const { + inline uint32_t flags_nzcv() const { DCHECK(IsComplete()); DCHECK((dump_.flags_ & ~Flags_mask) == 0); return dump_.flags_ & Flags_mask; diff --git a/deps/v8/test/cctest/test-version.cc b/deps/v8/test/cctest/test-version.cc index 7de4467d6b..50fca16871 100644 --- a/deps/v8/test/cctest/test-version.cc +++ b/deps/v8/test/cctest/test-version.cc @@ -46,7 +46,8 @@ void SetVersion(int major, int minor, int build, int patch, Version::soname_ = soname; } -} } // namespace v8::internal +} // namespace internal +} // namespace v8 static void CheckVersion(int major, int minor, int build, diff --git a/deps/v8/test/cctest/test-weakmaps.cc b/deps/v8/test/cctest/test-weakmaps.cc index 64d2876887..31b812e287 100644 --- a/deps/v8/test/cctest/test-weakmaps.cc +++ b/deps/v8/test/cctest/test-weakmaps.cc @@ -34,7 +34,6 @@ using namespace v8::internal; - static Isolate* GetIsolateFrom(LocalContext* context) { return reinterpret_cast<Isolate*>((*context)->GetIsolate()); } @@ -89,8 +88,10 @@ TEST(Weakness) { Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); Handle<JSObject> object = factory->NewJSObjectFromMap(map); Handle<Smi> smi(Smi::FromInt(23), isolate); - Runtime::WeakCollectionSet(weakmap, key, object); - Runtime::WeakCollectionSet(weakmap, object, smi); + int32_t hash = Object::GetOrCreateHash(isolate, key)->value(); + Runtime::WeakCollectionSet(weakmap, key, object, hash); + int32_t object_hash = Object::GetOrCreateHash(isolate, object)->value(); + Runtime::WeakCollectionSet(weakmap, object, smi, object_hash); } CHECK_EQ(2, ObjectHashTable::cast(weakmap->table())->NumberOfElements()); @@ -145,7 +146,8 @@ TEST(Shrinking) { for (int i = 0; i < 32; i++) { Handle<JSObject> object = factory->NewJSObjectFromMap(map); Handle<Smi> smi(Smi::FromInt(i), isolate); - Runtime::WeakCollectionSet(weakmap, object, smi); + int32_t object_hash = Object::GetOrCreateHash(isolate, object)->value(); + Runtime::WeakCollectionSet(weakmap, object, smi, object_hash); } } @@ -193,7 +195,8 @@ TEST(Regress2060a) { Handle<JSObject> object = factory->NewJSObject(function, TENURED); CHECK(!heap->InNewSpace(object->address())); CHECK(!first_page->Contains(object->address())); - Runtime::WeakCollectionSet(weakmap, key, object); + int32_t hash = Object::GetOrCreateHash(isolate, key)->value(); + Runtime::WeakCollectionSet(weakmap, key, object, hash); } } @@ -235,7 +238,8 @@ TEST(Regress2060b) { Handle<JSWeakMap> weakmap = AllocateJSWeakMap(isolate); for (int i = 0; i < 32; i++) { Handle<Smi> smi(Smi::FromInt(i), isolate); - Runtime::WeakCollectionSet(weakmap, keys[i], smi); + int32_t hash = Object::GetOrCreateHash(isolate, keys[i])->value(); + Runtime::WeakCollectionSet(weakmap, keys[i], smi, hash); } // Force compacting garbage collection. The subsequent collections are used diff --git a/deps/v8/test/cctest/test-weaksets.cc b/deps/v8/test/cctest/test-weaksets.cc index dbb7311e83..3595af288f 100644 --- a/deps/v8/test/cctest/test-weaksets.cc +++ b/deps/v8/test/cctest/test-weaksets.cc @@ -34,7 +34,6 @@ using namespace v8::internal; - static Isolate* GetIsolateFrom(LocalContext* context) { return reinterpret_cast<Isolate*>((*context)->GetIsolate()); } @@ -90,7 +89,8 @@ TEST(WeakSet_Weakness) { { HandleScope scope(isolate); Handle<Smi> smi(Smi::FromInt(23), isolate); - Runtime::WeakCollectionSet(weakset, key, smi); + int32_t hash = Object::GetOrCreateHash(isolate, key)->value(); + Runtime::WeakCollectionSet(weakset, key, smi, hash); } CHECK_EQ(1, ObjectHashTable::cast(weakset->table())->NumberOfElements()); @@ -145,7 +145,8 @@ TEST(WeakSet_Shrinking) { for (int i = 0; i < 32; i++) { Handle<JSObject> object = factory->NewJSObjectFromMap(map); Handle<Smi> smi(Smi::FromInt(i), isolate); - Runtime::WeakCollectionSet(weakset, object, smi); + int32_t hash = Object::GetOrCreateHash(isolate, object)->value(); + Runtime::WeakCollectionSet(weakset, object, smi, hash); } } @@ -193,7 +194,8 @@ TEST(WeakSet_Regress2060a) { Handle<JSObject> object = factory->NewJSObject(function, TENURED); CHECK(!heap->InNewSpace(object->address())); CHECK(!first_page->Contains(object->address())); - Runtime::WeakCollectionSet(weakset, key, object); + int32_t hash = Object::GetOrCreateHash(isolate, key)->value(); + Runtime::WeakCollectionSet(weakset, key, object, hash); } } @@ -235,7 +237,8 @@ TEST(WeakSet_Regress2060b) { Handle<JSWeakSet> weakset = AllocateJSWeakSet(isolate); for (int i = 0; i < 32; i++) { Handle<Smi> smi(Smi::FromInt(i), isolate); - Runtime::WeakCollectionSet(weakset, keys[i], smi); + int32_t hash = Object::GetOrCreateHash(isolate, keys[i])->value(); + Runtime::WeakCollectionSet(weakset, keys[i], smi, hash); } // Force compacting garbage collection. The subsequent collections are used diff --git a/deps/v8/test/cctest/trace-extension.cc b/deps/v8/test/cctest/trace-extension.cc index a95532f931..e7f097f86f 100644 --- a/deps/v8/test/cctest/trace-extension.cc +++ b/deps/v8/test/cctest/trace-extension.cc @@ -151,4 +151,5 @@ void TraceExtension::JSEntrySPLevel2( } -} } // namespace v8::internal +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/js-perf-test/Exceptions/run.js b/deps/v8/test/js-perf-test/Exceptions/run.js new file mode 100644 index 0000000000..31153b5047 --- /dev/null +++ b/deps/v8/test/js-perf-test/Exceptions/run.js @@ -0,0 +1,26 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +load('../base.js'); +load('try-catch.js'); + +var success = true; + +function PrintResult(name, result) { + print(name + '-Exceptions(Score): ' + result); +} + + +function PrintError(name, error) { + PrintResult(name, error); + success = false; +} + + +BenchmarkSuite.config.doWarmup = undefined; +BenchmarkSuite.config.doDeterministic = undefined; + +BenchmarkSuite.RunSuites({ NotifyResult: PrintResult, + NotifyError: PrintError }); diff --git a/deps/v8/test/js-perf-test/Exceptions/try-catch.js b/deps/v8/test/js-perf-test/Exceptions/try-catch.js new file mode 100644 index 0000000000..0a4a0c0a64 --- /dev/null +++ b/deps/v8/test/js-perf-test/Exceptions/try-catch.js @@ -0,0 +1,110 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +new BenchmarkSuite('Try-Catch', [1000], [ + new Benchmark('OnSuccess', false, false, 0, + OnSuccess, OnSuccessSetup, + OnSuccessTearDown), + new Benchmark('OnException', false, false, 0, + OnException, OnExceptionSetup, + OnExceptionTearDown), + new Benchmark('OnSuccessFinallyOnly', false, false, 0, + OnSuccessFinallyOnly, OnSuccessFinallyOnlySetup, + OnSuccessFinallyOnlyTearDown), + new Benchmark('WithFinallyOnException', false, false, 0, + WithFinallyOnException, WithFinallyOnExceptionSetup, + WithFinallyOnExceptionTearDown) +]); + +var a; +var b; +var c; + +// ---------------------------------------------------------------------------- + +function OnSuccessSetup() { + a = 4; + b = 6; + c = 0; +} + +function OnSuccess() { + try { + c = a + b; + } + catch (e) { + c++; + } +} + +function OnSuccessTearDown() { + return c === 10; +} + +// ---------------------------------------------------------------------------- + +function OnExceptionSetup() { + a = 4; + b = 6; + c = 0; +} + +function OnException() { + try { + throw 'Test exception'; + } + catch (e) { + c = a + b; + } +} + +function OnExceptionTearDown() { + return c === 10; +} + +// ---------------------------------------------------------------------------- + +function OnSuccessFinallyOnlySetup() { + a = 4; + b = 6; + c = 0; +} + +function OnSuccessFinallyOnly() { + try { + c = a + b; + } + finally { + c++; + } +} + +function OnSuccessFinallyOnlyTearDown() { + return c === 11; +} + +// ---------------------------------------------------------------------------- + +function WithFinallyOnExceptionSetup() { + a = 4; + b = 6; + c = 0; +} + +function WithFinallyOnException() { + try { + throw 'Test exception'; + } + catch (e) { + c = a + b; + } + finally { + c++; + } +} + +function WithFinallyOnExceptionTearDown() { + return c === 11; +} +// ---------------------------------------------------------------------------- diff --git a/deps/v8/test/js-perf-test/JSTests.json b/deps/v8/test/js-perf-test/JSTests.json index ce7e5bb320..bff5b6536f 100644 --- a/deps/v8/test/js-perf-test/JSTests.json +++ b/deps/v8/test/js-perf-test/JSTests.json @@ -3,6 +3,7 @@ "run_count": 5, "run_count_android_arm": 3, "run_count_android_arm64": 3, + "timeout": 120, "units": "score", "total": true, "resources": ["base.js"], @@ -27,7 +28,6 @@ "path": ["Classes"], "main": "run.js", "resources": ["super.js", "default-constructor.js"], - "flags": ["--harmony-classes"], "results_regexp": "^%s\\-Classes\\(Score\\): (.+)$", "tests": [ {"name": "Super"}, @@ -105,6 +105,26 @@ "tests": [ {"name": "Assign"} ] + }, + { + "name": "Scope", + "path": ["Scope"], + "main": "run.js", + "resources": ["with.js"], + "results_regexp": "^%s\\-Scope\\(Score\\): (.+)$", + "tests": [ + {"name": "With"} + ] + }, + { + "name": "Exceptions", + "path": ["Exceptions"], + "main": "run.js", + "resources": ["try-catch.js"], + "results_regexp": "^%s\\-Exceptions\\(Score\\): (.+)$", + "tests": [ + {"name": "Try-Catch"} + ] } ] } diff --git a/deps/v8/test/js-perf-test/Scope/run.js b/deps/v8/test/js-perf-test/Scope/run.js new file mode 100644 index 0000000000..9ce00a15a5 --- /dev/null +++ b/deps/v8/test/js-perf-test/Scope/run.js @@ -0,0 +1,26 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +load('../base.js'); +load('with.js'); + +var success = true; + +function PrintResult(name, result) { + print(name + '-Scope(Score): ' + result); +} + + +function PrintError(name, error) { + PrintResult(name, error); + success = false; +} + + +BenchmarkSuite.config.doWarmup = undefined; +BenchmarkSuite.config.doDeterministic = undefined; + +BenchmarkSuite.RunSuites({ NotifyResult: PrintResult, + NotifyError: PrintError }); diff --git a/deps/v8/test/js-perf-test/Scope/with.js b/deps/v8/test/js-perf-test/Scope/with.js new file mode 100644 index 0000000000..8ec2d30cf0 --- /dev/null +++ b/deps/v8/test/js-perf-test/Scope/with.js @@ -0,0 +1,90 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +new BenchmarkSuite( 'With', [1000], [ + new Benchmark('AccessOnSameLevel', false, false, 0, + AccessOnSameLevel, AccessOnSameLevelSetup, + AccessOnSameLevelTearDown), + new Benchmark('SetOnSameLevel', false, false, 0, + SetOnSameLevel, SetOnSameLevelSetup, + SetOnSameLevelTearDown), + new Benchmark('AccessOverPrototypeChain', false, false, 0, + AccessOverPrototypeChainSetup, AccessOverPrototypeChainSetup, + AccessOverPrototypeChainTearDown), + new Benchmark('CompetingScope', false, false, 0, + CompetingScope, CompetingScopeSetup, CompetingScopeTearDown) +]); + +var objectUnderTest; +var objectUnderTestExtended; +var resultStore; +var VALUE_OF_PROPERTY = 'Simply a string'; +var SOME_OTHER_VALUE = 'Another value'; + +// ---------------------------------------------------------------------------- + +function AccessOnSameLevelSetup() { + objectUnderTest = {first: VALUE_OF_PROPERTY}; +} + +function AccessOnSameLevel() { + with (objectUnderTest) { + resultStore = first; + } +} + +function AccessOnSameLevelTearDown() { + return objectUnderTest.first === resultStore; +} + +// ---------------------------------------------------------------------------- + +function AccessOverPrototypeChainSetup() { + objectUnderTest = {first: VALUE_OF_PROPERTY}; + objectUnderTestExtended = Object.create(objectUnderTest); + objectUnderTestExtended.second = 'Another string'; +} + +function AccessOverPrototypeChain() { + with (objectUnderTestExtended) { + resultStore = first; + } +} + +function AccessOverPrototypeChainTearDown() { + return objectUnderTest.first === resultStore; +} + +// ---------------------------------------------------------------------------- + +function CompetingScopeSetup() { + objectUnderTest = {first: VALUE_OF_PROPERTY}; +} + +function CompetingScope() { + var first = 'Not correct'; + with (objectUnderTest) { + resultStore = first; + } +} + +function CompetingScopeTearDown() { + return objectUnderTest.first === resultStore; +} + +// ---------------------------------------------------------------------------- + +function SetOnSameLevelSetup() { + objectUnderTest = {first: VALUE_OF_PROPERTY}; +} + +function SetOnSameLevel() { + with (objectUnderTest) { + first = SOME_OTHER_VALUE; + } +} + +function SetOnSameLevelTearDown() { + return objectUnderTest.first === SOME_OTHER_VALUE; +} diff --git a/deps/v8/test/js-perf-test/base.js b/deps/v8/test/js-perf-test/base.js index b0ce40b888..cef2867f2b 100644 --- a/deps/v8/test/js-perf-test/base.js +++ b/deps/v8/test/js-perf-test/base.js @@ -281,28 +281,28 @@ BenchmarkSuite.prototype.RunSingleBenchmark = function(benchmark, data) { // by minIterations, depending on the config flag doDeterministic. for (var i = 0; (doDeterministic ? i<benchmark.deterministicIterations : elapsed < 1000); i++) { - benchmark.run(); + for (var j = 0; j < 100; j++) benchmark.run(); elapsed = new Date() - start; } if (data != null) { - data.runs += i; + data.hectoruns += i; data.elapsed += elapsed; } } // Sets up data in order to skip or not the warmup phase. if (!doWarmup && data == null) { - data = { runs: 0, elapsed: 0 }; + data = { hectoruns: 0, elapsed: 0 }; } if (data == null) { Measure(null); - return { runs: 0, elapsed: 0 }; + return { hectoruns: 0, elapsed: 0 }; } else { Measure(data); // If we've run too few iterations, we continue for another second. - if (data.runs < benchmark.minIterations) return data; - var usec = (data.elapsed * 1000) / data.runs; + if (data.hectoruns * 100 < benchmark.minIterations) return data; + var usec = (data.elapsed * 10) / data.hectoruns; var rms = (benchmark.rmsResult != null) ? benchmark.rmsResult() : 0; this.NotifyStep(new BenchmarkResult(benchmark, usec, rms)); return null; diff --git a/deps/v8/test/message/arrow-bare-rest-param.js b/deps/v8/test/message/arrow-bare-rest-param.js new file mode 100644 index 0000000000..9b3916d959 --- /dev/null +++ b/deps/v8/test/message/arrow-bare-rest-param.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-rest-parameters --harmony-arrow-functions + +...x => 10 diff --git a/deps/v8/test/message/arrow-bare-rest-param.out b/deps/v8/test/message/arrow-bare-rest-param.out new file mode 100644 index 0000000000..76a25a455d --- /dev/null +++ b/deps/v8/test/message/arrow-bare-rest-param.out @@ -0,0 +1,4 @@ +*%(basename)s:7: SyntaxError: Unexpected token ... +...x => 10 +^^^ +SyntaxError: Unexpected token ... diff --git a/deps/v8/test/message/arrow-missing.js b/deps/v8/test/message/arrow-missing.js new file mode 100644 index 0000000000..566345a460 --- /dev/null +++ b/deps/v8/test/message/arrow-missing.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-rest-parameters --harmony-arrow-functions + +function foo() { return(); } diff --git a/deps/v8/test/message/arrow-missing.out b/deps/v8/test/message/arrow-missing.out new file mode 100644 index 0000000000..f042a20fad --- /dev/null +++ b/deps/v8/test/message/arrow-missing.out @@ -0,0 +1,4 @@ +*%(basename)s:7: SyntaxError: Expected () to start arrow function, but got ';' instead of '=>' +function foo() { return(); } + ^ +SyntaxError: Expected () to start arrow function, but got ';' instead of '=>' diff --git a/deps/v8/test/message/arrow-param-after-rest-2.js b/deps/v8/test/message/arrow-param-after-rest-2.js new file mode 100644 index 0000000000..3b42f19247 --- /dev/null +++ b/deps/v8/test/message/arrow-param-after-rest-2.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-rest-parameters --harmony-arrow-functions + +(w, ...x, y) => 10 diff --git a/deps/v8/test/message/arrow-param-after-rest-2.out b/deps/v8/test/message/arrow-param-after-rest-2.out new file mode 100644 index 0000000000..27785cfb02 --- /dev/null +++ b/deps/v8/test/message/arrow-param-after-rest-2.out @@ -0,0 +1,4 @@ +*%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter +(w, ...x, y) => 10 + ^ +SyntaxError: Rest parameter must be last formal parameter diff --git a/deps/v8/test/message/arrow-param-after-rest.js b/deps/v8/test/message/arrow-param-after-rest.js new file mode 100644 index 0000000000..0fade6c31d --- /dev/null +++ b/deps/v8/test/message/arrow-param-after-rest.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-rest-parameters --harmony-arrow-functions + +(...x, y) => 10 diff --git a/deps/v8/test/message/arrow-param-after-rest.out b/deps/v8/test/message/arrow-param-after-rest.out new file mode 100644 index 0000000000..5b36e43584 --- /dev/null +++ b/deps/v8/test/message/arrow-param-after-rest.out @@ -0,0 +1,4 @@ +*%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter +(...x, y) => 10 + ^ +SyntaxError: Rest parameter must be last formal parameter diff --git a/deps/v8/test/message/arrow-strict-eval-bare-parameter.js b/deps/v8/test/message/arrow-strict-eval-bare-parameter.js new file mode 100644 index 0000000000..d5692517dd --- /dev/null +++ b/deps/v8/test/message/arrow-strict-eval-bare-parameter.js @@ -0,0 +1,8 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-arrow-functions + +"use strict"; +eval => 42 diff --git a/deps/v8/test/message/arrow-strict-eval-bare-parameter.out b/deps/v8/test/message/arrow-strict-eval-bare-parameter.out new file mode 100644 index 0000000000..0eb8f8841f --- /dev/null +++ b/deps/v8/test/message/arrow-strict-eval-bare-parameter.out @@ -0,0 +1,4 @@ +*%(basename)s:8: SyntaxError: Unexpected eval or arguments in strict mode +eval => 42 +^^^^ +SyntaxError: Unexpected eval or arguments in strict mode diff --git a/deps/v8/test/message/arrow-two-rest-params.js b/deps/v8/test/message/arrow-two-rest-params.js new file mode 100644 index 0000000000..345545ccdf --- /dev/null +++ b/deps/v8/test/message/arrow-two-rest-params.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-rest-parameters --harmony-arrow-functions + +(w, ...x, ...y) => 10 diff --git a/deps/v8/test/message/arrow-two-rest-params.out b/deps/v8/test/message/arrow-two-rest-params.out new file mode 100644 index 0000000000..7147ebcf11 --- /dev/null +++ b/deps/v8/test/message/arrow-two-rest-params.out @@ -0,0 +1,4 @@ +*%(basename)s:7: SyntaxError: Rest parameter must be last formal parameter +(w, ...x, ...y) => 10 + ^ +SyntaxError: Rest parameter must be last formal parameter diff --git a/deps/v8/test/message/class-constructor-accessor.js b/deps/v8/test/message/class-constructor-accessor.js index edc3c13169..fcc9868b14 100644 --- a/deps/v8/test/message/class-constructor-accessor.js +++ b/deps/v8/test/message/class-constructor-accessor.js @@ -1,8 +1,8 @@ // 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. -// -// Flags: --harmony-classes + + 'use strict'; class C { diff --git a/deps/v8/test/message/class-constructor-generator.js b/deps/v8/test/message/class-constructor-generator.js index 5d370f865e..a9a0ef862d 100644 --- a/deps/v8/test/message/class-constructor-generator.js +++ b/deps/v8/test/message/class-constructor-generator.js @@ -1,8 +1,8 @@ // 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. -// -// Flags: --harmony-classes + + 'use strict'; class C { diff --git a/deps/v8/test/message/destructuring-modify-const.js b/deps/v8/test/message/destructuring-modify-const.js new file mode 100644 index 0000000000..cabd924b37 --- /dev/null +++ b/deps/v8/test/message/destructuring-modify-const.js @@ -0,0 +1,9 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-destructuring +'use strict'; + +const { x : x, y : y } = { x : 1, y : 2 }; +x++; diff --git a/deps/v8/test/message/destructuring-modify-const.out b/deps/v8/test/message/destructuring-modify-const.out new file mode 100644 index 0000000000..19bffa6d3d --- /dev/null +++ b/deps/v8/test/message/destructuring-modify-const.out @@ -0,0 +1,5 @@ +*%(basename)s:9: TypeError: Assignment to constant variable. +x++; + ^ +TypeError: Assignment to constant variable. + at *%(basename)s:9:2 diff --git a/deps/v8/test/message/invalid-spread-2.js b/deps/v8/test/message/invalid-spread-2.js new file mode 100644 index 0000000000..67e0f7d7c0 --- /dev/null +++ b/deps/v8/test/message/invalid-spread-2.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-rest-parameters --harmony-arrow-functions + +(x, ...y, z) diff --git a/deps/v8/test/message/invalid-spread-2.out b/deps/v8/test/message/invalid-spread-2.out new file mode 100644 index 0000000000..287390a74a --- /dev/null +++ b/deps/v8/test/message/invalid-spread-2.out @@ -0,0 +1,4 @@ +*%(basename)s:7: SyntaxError: Unexpected token ... +(x, ...y, z) + ^^^ +SyntaxError: Unexpected token ... diff --git a/deps/v8/test/message/invalid-spread.js b/deps/v8/test/message/invalid-spread.js new file mode 100644 index 0000000000..e58334e993 --- /dev/null +++ b/deps/v8/test/message/invalid-spread.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-rest-parameters --harmony-arrow-functions + +(x, ...y) diff --git a/deps/v8/test/message/invalid-spread.out b/deps/v8/test/message/invalid-spread.out new file mode 100644 index 0000000000..5694ad6e88 --- /dev/null +++ b/deps/v8/test/message/invalid-spread.out @@ -0,0 +1,4 @@ +*%(basename)s:7: SyntaxError: Unexpected token ... +(x, ...y) + ^^^ +SyntaxError: Unexpected token ... diff --git a/deps/v8/test/message/message.status b/deps/v8/test/message/message.status index f28aa2a8d3..234bf0f35c 100644 --- a/deps/v8/test/message/message.status +++ b/deps/v8/test/message/message.status @@ -30,11 +30,4 @@ # All tests in the bug directory are expected to fail. 'bugs/*': [FAIL], }], # ALWAYS - -############################################################################## -['arch == x87', { - - # Crankshaft compiler did not generate required source position for it: - 'overwritten-builtins': [SKIP], -}], # 'arch == x87' ] diff --git a/deps/v8/test/message/no-legacy-const-2.js b/deps/v8/test/message/no-legacy-const-2.js new file mode 100644 index 0000000000..29aeba5e1f --- /dev/null +++ b/deps/v8/test/message/no-legacy-const-2.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --no-legacy-const + +const = 42; diff --git a/deps/v8/test/message/no-legacy-const-2.out b/deps/v8/test/message/no-legacy-const-2.out new file mode 100644 index 0000000000..55c855ee4f --- /dev/null +++ b/deps/v8/test/message/no-legacy-const-2.out @@ -0,0 +1,5 @@ +*%(basename)s:7: SyntaxError: Unexpected token const +const = 42; +^^^^^ + +SyntaxError: Unexpected token const diff --git a/deps/v8/test/message/no-legacy-const-3.js b/deps/v8/test/message/no-legacy-const-3.js new file mode 100644 index 0000000000..6981571e62 --- /dev/null +++ b/deps/v8/test/message/no-legacy-const-3.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --no-legacy-const + +const diff --git a/deps/v8/test/message/no-legacy-const-3.out b/deps/v8/test/message/no-legacy-const-3.out new file mode 100644 index 0000000000..046e9f7023 --- /dev/null +++ b/deps/v8/test/message/no-legacy-const-3.out @@ -0,0 +1,5 @@ +*%(basename)s:7: SyntaxError: Unexpected token const +const +^^^^^ + +SyntaxError: Unexpected token const diff --git a/deps/v8/test/message/no-legacy-const.js b/deps/v8/test/message/no-legacy-const.js new file mode 100644 index 0000000000..ecad2181b8 --- /dev/null +++ b/deps/v8/test/message/no-legacy-const.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --no-legacy-const + +const x = 42; diff --git a/deps/v8/test/message/no-legacy-const.out b/deps/v8/test/message/no-legacy-const.out new file mode 100644 index 0000000000..b28dd10b77 --- /dev/null +++ b/deps/v8/test/message/no-legacy-const.out @@ -0,0 +1,5 @@ +*%(basename)s:7: SyntaxError: Unexpected token const +const x = 42; +^^^^^ + +SyntaxError: Unexpected token const diff --git a/deps/v8/test/message/rest-param-class-setter-strict.js b/deps/v8/test/message/rest-param-class-setter-strict.js new file mode 100644 index 0000000000..2d478a6644 --- /dev/null +++ b/deps/v8/test/message/rest-param-class-setter-strict.js @@ -0,0 +1,12 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-rest-parameters +'use strict'; + +var _bad = "setting this should fail!"; +class C { + get bad() { return _bad; } + set bad(...args) { _bad = args[0]; } +} diff --git a/deps/v8/test/message/rest-param-class-setter-strict.out b/deps/v8/test/message/rest-param-class-setter-strict.out new file mode 100644 index 0000000000..3296a0f2c8 --- /dev/null +++ b/deps/v8/test/message/rest-param-class-setter-strict.out @@ -0,0 +1,4 @@ +*%(basename)s:11: SyntaxError: Setter function argument must not be a rest parameter + set bad(...args) { _bad = args[0]; } + ^^^^^^^^^ +SyntaxError: Setter function argument must not be a rest parameter diff --git a/deps/v8/test/message/rest-param-object-setter-sloppy.js b/deps/v8/test/message/rest-param-object-setter-sloppy.js new file mode 100644 index 0000000000..08c03298dc --- /dev/null +++ b/deps/v8/test/message/rest-param-object-setter-sloppy.js @@ -0,0 +1,11 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-rest-parameters + +var _bad = "this should fail!"; +({ + get bad() { return _bad; }, + set bad(...args) { _bad = args[0]; } +}); diff --git a/deps/v8/test/message/rest-param-object-setter-sloppy.out b/deps/v8/test/message/rest-param-object-setter-sloppy.out new file mode 100644 index 0000000000..9400a2a9ce --- /dev/null +++ b/deps/v8/test/message/rest-param-object-setter-sloppy.out @@ -0,0 +1,4 @@ +*%(basename)s:10: SyntaxError: Setter function argument must not be a rest parameter + set bad(...args) { _bad = args[0]; } + ^^^^^^^^^ +SyntaxError: Setter function argument must not be a rest parameter diff --git a/deps/v8/test/message/rest-param-object-setter-strict.js b/deps/v8/test/message/rest-param-object-setter-strict.js new file mode 100644 index 0000000000..e3a8f604e6 --- /dev/null +++ b/deps/v8/test/message/rest-param-object-setter-strict.js @@ -0,0 +1,12 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-rest-parameters +'use strict'; + +var _bad = "this should fail!"; +({ + get bad() { return _bad; }, + set bad(...args) { _bad = args[0]; } +}); diff --git a/deps/v8/test/message/rest-param-object-setter-strict.out b/deps/v8/test/message/rest-param-object-setter-strict.out new file mode 100644 index 0000000000..3296a0f2c8 --- /dev/null +++ b/deps/v8/test/message/rest-param-object-setter-strict.out @@ -0,0 +1,4 @@ +*%(basename)s:11: SyntaxError: Setter function argument must not be a rest parameter + set bad(...args) { _bad = args[0]; } + ^^^^^^^^^ +SyntaxError: Setter function argument must not be a rest parameter diff --git a/deps/v8/test/message/strong-object-freeze-prop.js b/deps/v8/test/message/strong-object-freeze-prop.js new file mode 100644 index 0000000000..17250158d5 --- /dev/null +++ b/deps/v8/test/message/strong-object-freeze-prop.js @@ -0,0 +1,11 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode + +"use strong"; + +let o = {}; +Object.defineProperty(o, "foo", { writable: true }); +Object.defineProperty(o, "foo", { writable: false }); diff --git a/deps/v8/test/message/strong-object-freeze-prop.out b/deps/v8/test/message/strong-object-freeze-prop.out new file mode 100644 index 0000000000..0c611c5928 --- /dev/null +++ b/deps/v8/test/message/strong-object-freeze-prop.out @@ -0,0 +1,9 @@ +# Copyright 2015 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +*%(basename)s:11: TypeError: On strong object #<Object>, redefining writable, non-configurable property 'foo' to be non-writable is deprecated +Object.defineProperty(o, "foo", { writable: false }); + ^ +TypeError: On strong object #<Object>, redefining writable, non-configurable property 'foo' to be non-writable is deprecated + at Function.defineProperty (native) + at *%(basename)s:11:8 diff --git a/deps/v8/test/message/strong-object-set-proto.js b/deps/v8/test/message/strong-object-set-proto.js new file mode 100644 index 0000000000..890dd84d72 --- /dev/null +++ b/deps/v8/test/message/strong-object-set-proto.js @@ -0,0 +1,9 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode + +"use strong"; + +({}).__proto__ = {}; diff --git a/deps/v8/test/message/strong-object-set-proto.out b/deps/v8/test/message/strong-object-set-proto.out new file mode 100644 index 0000000000..bf2c9334f7 --- /dev/null +++ b/deps/v8/test/message/strong-object-set-proto.out @@ -0,0 +1,9 @@ +# Copyright 2015 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +*%(basename)s:9: TypeError: On strong object #<Object>, redefining the internal prototype is deprecated +({}).__proto__ = {}; + ^ +TypeError: On strong object #<Object>, redefining the internal prototype is deprecated + at Object.set __proto__ (native) + at *%(basename)s:9:16 diff --git a/deps/v8/test/message/super-constructor-extra-statement.js b/deps/v8/test/message/super-constructor-extra-statement.js index e8ffe2dbfa..541bddbde1 100644 --- a/deps/v8/test/message/super-constructor-extra-statement.js +++ b/deps/v8/test/message/super-constructor-extra-statement.js @@ -1,8 +1,8 @@ // 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. -// -// Flags: --harmony-classes + + 'use strict'; class C { diff --git a/deps/v8/test/message/super-constructor.js b/deps/v8/test/message/super-constructor.js index 430dc58ce7..93ca61844a 100644 --- a/deps/v8/test/message/super-constructor.js +++ b/deps/v8/test/message/super-constructor.js @@ -1,8 +1,8 @@ // 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. -// -// Flags: --harmony-classes + + 'use strict'; class C { diff --git a/deps/v8/test/message/super-in-function.js b/deps/v8/test/message/super-in-function.js index edaa0e4ead..f2e2342c31 100644 --- a/deps/v8/test/message/super-in-function.js +++ b/deps/v8/test/message/super-in-function.js @@ -1,8 +1,8 @@ // Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// -// Flags: --harmony-classes + + 'use strict'; function f() { diff --git a/deps/v8/test/mjsunit/arguments.js b/deps/v8/test/mjsunit/arguments.js index 56c1d7224d..26eb38912a 100644 --- a/deps/v8/test/mjsunit/arguments.js +++ b/deps/v8/test/mjsunit/arguments.js @@ -25,6 +25,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Flags: --allow-natives-syntax + function argc0() { return arguments.length; } @@ -188,3 +190,17 @@ function arg_set(x) { return (arguments[x] = 117); } assertEquals(undefined, arg_get(0xFFFFFFFF)); assertEquals(true, arg_del(0xFFFFFFFF)); assertEquals(117, arg_set(0xFFFFFFFF)); + +(function() { + function f(a) { return arguments; } + var a = f(1,2,3); + // Turn arguments into slow. + assertTrue(%HasSloppyArgumentsElements(a)); + a[10000] = 1; + assertTrue(%HasSloppyArgumentsElements(a)); + // Make it fast again by adding values. + for (var i = 0; i < 1000; i++) { + a[i] = 1.5; + } + assertTrue(%HasSloppyArgumentsElements(a)); +})(); diff --git a/deps/v8/test/mjsunit/array-length.js b/deps/v8/test/mjsunit/array-length.js index 16867db733..c2b325061b 100644 --- a/deps/v8/test/mjsunit/array-length.js +++ b/deps/v8/test/mjsunit/array-length.js @@ -105,6 +105,13 @@ var a = new Array(); assertEquals(Object(12), a.length = new Number(12)); assertEquals(12, a.length); +Number.prototype.valueOf = function() { return 10; } +var n = new Number(100); +assertEquals(n, a.length = n); +assertEquals(10, a.length); +n.valueOf = function() { return 20; } +assertEquals(n, a.length = n); +assertEquals(20, a.length); var o = { length: -23 }; Array.prototype.pop.apply(o); @@ -119,3 +126,9 @@ for (var i = 0; i < 7; i++) { t = a.length = 7; assertEquals(7, t); } + +(function () { + "use strict"; + var frozen_object = Object.freeze({__proto__:[]}); + assertThrows(function () { frozen_object.length = 10 }); +})(); diff --git a/deps/v8/test/mjsunit/array-sort.js b/deps/v8/test/mjsunit/array-sort.js index 62755426ad..36608f5e14 100644 --- a/deps/v8/test/mjsunit/array-sort.js +++ b/deps/v8/test/mjsunit/array-sort.js @@ -445,6 +445,22 @@ function TestSortDoesNotDependOnArrayPrototypeSort() { fail('Should not call sort'); }; sortfn.call(arr); + // Restore for the next test + Array.prototype.sort = sortfn; } TestSortDoesNotDependOnArrayPrototypeSort(); + +function TestSortToObject() { + Number.prototype[0] = 5; + Number.prototype[1] = 4; + Number.prototype.length = 2; + x = new Number(0); + assertEquals(0, Number(Array.prototype.sort.call(x))); + assertEquals(4, x[0]); + assertEquals(5, x[1]); + assertArrayEquals(["0", "1"], Object.getOwnPropertyNames(x)); + // The following would throw if ToObject weren't called. + assertEquals(0, Number(Array.prototype.sort.call(0))); +} +TestSortToObject(); diff --git a/deps/v8/test/mjsunit/asm/atomics-add.js b/deps/v8/test/mjsunit/asm/atomics-add.js new file mode 100644 index 0000000000..69400c8059 --- /dev/null +++ b/deps/v8/test/mjsunit/asm/atomics-add.js @@ -0,0 +1,93 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-atomics --harmony-sharedarraybuffer + +function Module(stdlib, foreign, heap) { + "use asm"; + var MEM8 = new stdlib.Int8Array(heap); + var MEM16 = new stdlib.Int16Array(heap); + var MEM32 = new stdlib.Int32Array(heap); + var MEMU8 = new stdlib.Uint8Array(heap); + var MEMU16 = new stdlib.Uint16Array(heap); + var MEMU32 = new stdlib.Uint32Array(heap); + var add = stdlib.Atomics.add; + var fround = stdlib.Math.fround; + + function addi8(i, x) { + i = i | 0; + x = x | 0; + return add(MEM8, i, x)|0; + } + + function addi16(i, x) { + i = i | 0; + x = x | 0; + return add(MEM16, i, x)|0; + } + + function addi32(i, x) { + i = i | 0; + x = x | 0; + return add(MEM32, i, x)|0; + } + + function addu8(i, x) { + i = i | 0; + x = x >>> 0; + return add(MEMU8, i, x)>>>0; + } + + function addu16(i, x) { + i = i | 0; + x = x >>> 0; + return add(MEMU16, i, x)>>>0; + } + + function addu32(i, x) { + i = i | 0; + x = x >>> 0; + return add(MEMU32, i, x)>>>0; + } + + return { + addi8: addi8, + addi16: addi16, + addi32: addi32, + addu8: addu8, + addu16: addu16, + addu32: addu32, + }; +} + +var sab = new SharedArrayBuffer(16); +var m = Module(this, {}, sab); + +function clearArray() { + var ui8 = new Uint8Array(sab); + for (var i = 0; i < sab.byteLength; ++i) { + ui8[i] = 0; + } +} + +function testElementType(taConstr, f) { + clearArray(); + + var ta = new taConstr(sab); + var name = Object.prototype.toString.call(ta); + assertEquals(0, f(0, 10), name); + assertEquals(10, ta[0]); + assertEquals(10, f(0, 10), name); + assertEquals(20, ta[0]); + // out of bounds + assertEquals(0, f(-1, 0), name); + assertEquals(0, f(ta.length, 0), name); +} + +testElementType(Int8Array, m.addi8); +testElementType(Int16Array, m.addi16); +testElementType(Int32Array, m.addi32); +testElementType(Uint8Array, m.addu8); +testElementType(Uint16Array, m.addu16); +testElementType(Uint32Array, m.addu32); diff --git a/deps/v8/test/mjsunit/asm/atomics-and.js b/deps/v8/test/mjsunit/asm/atomics-and.js new file mode 100644 index 0000000000..e60f1f6a13 --- /dev/null +++ b/deps/v8/test/mjsunit/asm/atomics-and.js @@ -0,0 +1,94 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-atomics --harmony-sharedarraybuffer + +function Module(stdlib, foreign, heap) { + "use asm"; + var MEM8 = new stdlib.Int8Array(heap); + var MEM16 = new stdlib.Int16Array(heap); + var MEM32 = new stdlib.Int32Array(heap); + var MEMU8 = new stdlib.Uint8Array(heap); + var MEMU16 = new stdlib.Uint16Array(heap); + var MEMU32 = new stdlib.Uint32Array(heap); + var and = stdlib.Atomics.and; + var fround = stdlib.Math.fround; + + function andi8(i, x) { + i = i | 0; + x = x | 0; + return and(MEM8, i, x)|0; + } + + function andi16(i, x) { + i = i | 0; + x = x | 0; + return and(MEM16, i, x)|0; + } + + function andi32(i, x) { + i = i | 0; + x = x | 0; + return and(MEM32, i, x)|0; + } + + function andu8(i, x) { + i = i | 0; + x = x >>> 0; + return and(MEMU8, i, x)>>>0; + } + + function andu16(i, x) { + i = i | 0; + x = x >>> 0; + return and(MEMU16, i, x)>>>0; + } + + function andu32(i, x) { + i = i | 0; + x = x >>> 0; + return and(MEMU32, i, x)>>>0; + } + + return { + andi8: andi8, + andi16: andi16, + andi32: andi32, + andu8: andu8, + andu16: andu16, + andu32: andu32, + }; +} + +var sab = new SharedArrayBuffer(16); +var m = Module(this, {}, sab); + +function clearArray() { + var ui8 = new Uint8Array(sab); + for (var i = 0; i < sab.byteLength; ++i) { + ui8[i] = 0; + } +} + +function testElementType(taConstr, f) { + clearArray(); + + var ta = new taConstr(sab); + var name = Object.prototype.toString.call(ta); + ta[0] = 0x7f; + assertEquals(0x7f, f(0, 0xf), name); + assertEquals(0xf, ta[0]); + assertEquals(0xf, f(0, 0x19), name); + assertEquals(0x9, ta[0]); + // out of bounds + assertEquals(0, f(-1, 0), name); + assertEquals(0, f(ta.length, 0), name); +} + +testElementType(Int8Array, m.andi8); +testElementType(Int16Array, m.andi16); +testElementType(Int32Array, m.andi32); +testElementType(Uint8Array, m.andu8); +testElementType(Uint16Array, m.andu16); +testElementType(Uint32Array, m.andu32); diff --git a/deps/v8/test/mjsunit/asm/atomics-compareexchange.js b/deps/v8/test/mjsunit/asm/atomics-compareexchange.js new file mode 100644 index 0000000000..208a06043c --- /dev/null +++ b/deps/v8/test/mjsunit/asm/atomics-compareexchange.js @@ -0,0 +1,121 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-atomics --harmony-sharedarraybuffer + +function Module(stdlib, foreign, heap) { + "use asm"; + var MEM8 = new stdlib.Int8Array(heap); + var MEM16 = new stdlib.Int16Array(heap); + var MEM32 = new stdlib.Int32Array(heap); + var MEMU8 = new stdlib.Uint8Array(heap); + var MEMU16 = new stdlib.Uint16Array(heap); + var MEMU32 = new stdlib.Uint32Array(heap); + var MEMF32 = new stdlib.Float32Array(heap); + var MEMF64 = new stdlib.Float64Array(heap); + var compareExchange = stdlib.Atomics.compareExchange; + var fround = stdlib.Math.fround; + + function compareExchangei8(i, o, n) { + i = i | 0; + o = o | 0; + n = n | 0; + return compareExchange(MEM8, i, o, n)|0; + } + + function compareExchangei16(i, o, n) { + i = i | 0; + o = o | 0; + n = n | 0; + return compareExchange(MEM16, i, o, n)|0; + } + + function compareExchangei32(i, o, n) { + i = i | 0; + o = o | 0; + n = n | 0; + return compareExchange(MEM32, i, o, n)|0; + } + + function compareExchangeu8(i, o, n) { + i = i | 0; + o = o >>> 0; + n = n >>> 0; + return compareExchange(MEMU8, i, o, n)>>>0; + } + + function compareExchangeu16(i, o, n) { + i = i | 0; + o = o >>> 0; + n = n >>> 0; + return compareExchange(MEMU16, i, o, n)>>>0; + } + + function compareExchangeu32(i, o, n) { + i = i | 0; + o = o >>> 0; + n = n >>> 0; + return compareExchange(MEMU32, i, o, n)>>>0; + } + + function compareExchangef32(i, o, n) { + i = i | 0; + o = fround(o); + n = fround(n); + return fround(compareExchange(MEMF32, i, o, n)); + } + + function compareExchangef64(i, o, n) { + i = i | 0; + o = +o; + n = +n; + return +compareExchange(MEMF64, i, o, n); + } + + return { + compareExchangei8: compareExchangei8, + compareExchangei16: compareExchangei16, + compareExchangei32: compareExchangei32, + compareExchangeu8: compareExchangeu8, + compareExchangeu16: compareExchangeu16, + compareExchangeu32: compareExchangeu32, + compareExchangef32: compareExchangef32, + compareExchangef64: compareExchangef64 + }; +} + +var sab = new SharedArrayBuffer(16); +var m = Module(this, {}, sab); + +function clearArray() { + var ui8 = new Uint8Array(sab); + for (var i = 0; i < sab.byteLength; ++i) { + ui8[i] = 0; + } +} + +function testElementType(taConstr, f, oobValue) { + clearArray(); + + var ta = new taConstr(sab); + var name = Object.prototype.toString.call(ta); + assertEquals(0, ta[0]); + assertEquals(0, f(0, 0, 50), name); + assertEquals(50, ta[0]); + // Value is not equal to 0, so compareExchange won't store 100 + assertEquals(50, f(0, 0, 100), name); + assertEquals(50, ta[0]); + // out of bounds + assertEquals(oobValue, f(-1, 0, 0), name); + assertEquals(oobValue, f(ta.length, 0, 0), name); +} + +testElementType(Int8Array, m.compareExchangei8, 0); +testElementType(Int16Array, m.compareExchangei16, 0); +testElementType(Int32Array, m.compareExchangei32, 0); +testElementType(Uint8Array, m.compareExchangeu8, 0); +testElementType(Uint16Array, m.compareExchangeu16, 0); +testElementType(Uint32Array, m.compareExchangeu32, 0); +testElementType(Float32Array, m.compareExchangef32, NaN); +testElementType(Float64Array, m.compareExchangef64, NaN); diff --git a/deps/v8/test/mjsunit/asm/atomics-exchange.js b/deps/v8/test/mjsunit/asm/atomics-exchange.js new file mode 100644 index 0000000000..bb70322c7e --- /dev/null +++ b/deps/v8/test/mjsunit/asm/atomics-exchange.js @@ -0,0 +1,92 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-atomics --harmony-sharedarraybuffer + +function Module(stdlib, foreign, heap) { + "use asm"; + var MEM8 = new stdlib.Int8Array(heap); + var MEM16 = new stdlib.Int16Array(heap); + var MEM32 = new stdlib.Int32Array(heap); + var MEMU8 = new stdlib.Uint8Array(heap); + var MEMU16 = new stdlib.Uint16Array(heap); + var MEMU32 = new stdlib.Uint32Array(heap); + var exchange = stdlib.Atomics.exchange; + var fround = stdlib.Math.fround; + + function exchangei8(i, x) { + i = i | 0; + x = x | 0; + return exchange(MEM8, i, x)|0; + } + + function exchangei16(i, x) { + i = i | 0; + x = x | 0; + return exchange(MEM16, i, x)|0; + } + + function exchangei32(i, x) { + i = i | 0; + x = x | 0; + return exchange(MEM32, i, x)|0; + } + + function exchangeu8(i, x) { + i = i | 0; + x = x >>> 0; + return exchange(MEMU8, i, x)>>>0; + } + + function exchangeu16(i, x) { + i = i | 0; + x = x >>> 0; + return exchange(MEMU16, i, x)>>>0; + } + + function exchangeu32(i, x) { + i = i | 0; + x = x >>> 0; + return exchange(MEMU32, i, x)>>>0; + } + + return { + exchangei8: exchangei8, + exchangei16: exchangei16, + exchangei32: exchangei32, + exchangeu8: exchangeu8, + exchangeu16: exchangeu16, + exchangeu32: exchangeu32, + }; +} + +var sab = new SharedArrayBuffer(16); +var m = Module(this, {}, sab); + +function clearArray() { + var ui8 = new Uint8Array(sab); + for (var i = 0; i < sab.byteLength; ++i) { + ui8[i] = 0; + } +} + +function testElementType(taConstr, f) { + clearArray(); + + var ta = new taConstr(sab); + var name = Object.prototype.toString.call(ta); + ta[0] = 0x7f; + assertEquals(0x7f, f(0, 0xf), name); + assertEquals(0xf, ta[0]); + // out of bounds + assertEquals(0, f(-1, 0), name); + assertEquals(0, f(ta.length, 0), name); +} + +testElementType(Int8Array, m.exchangei8); +testElementType(Int16Array, m.exchangei16); +testElementType(Int32Array, m.exchangei32); +testElementType(Uint8Array, m.exchangeu8); +testElementType(Uint16Array, m.exchangeu16); +testElementType(Uint32Array, m.exchangeu32); diff --git a/deps/v8/test/mjsunit/asm/atomics-load.js b/deps/v8/test/mjsunit/asm/atomics-load.js new file mode 100644 index 0000000000..769fb40e2c --- /dev/null +++ b/deps/v8/test/mjsunit/asm/atomics-load.js @@ -0,0 +1,102 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-atomics --harmony-sharedarraybuffer + +function Module(stdlib, foreign, heap) { + "use asm"; + var MEM8 = new stdlib.Int8Array(heap); + var MEM16 = new stdlib.Int16Array(heap); + var MEM32 = new stdlib.Int32Array(heap); + var MEMU8 = new stdlib.Uint8Array(heap); + var MEMU16 = new stdlib.Uint16Array(heap); + var MEMU32 = new stdlib.Uint32Array(heap); + var MEMF32 = new stdlib.Float32Array(heap); + var MEMF64 = new stdlib.Float64Array(heap); + var load = stdlib.Atomics.load; + var fround = stdlib.Math.fround; + + function loadi8(i) { + i = i | 0; + return load(MEM8, i)|0; + } + + function loadi16(i) { + i = i | 0; + return load(MEM16, i)|0; + } + + function loadi32(i) { + i = i | 0; + return load(MEM32, i)|0; + } + + function loadu8(i) { + i = i | 0; + return load(MEMU8, i)>>>0; + } + + function loadu16(i) { + i = i | 0; + return load(MEMU16, i)>>>0; + } + + function loadu32(i) { + i = i | 0; + return load(MEMU32, i)>>>0; + } + + function loadf32(i) { + i = i | 0; + return fround(load(MEMF32, i)); + } + + function loadf64(i) { + i = i | 0; + return +load(MEMF64, i); + } + + return { + loadi8: loadi8, + loadi16: loadi16, + loadi32: loadi32, + loadu8: loadu8, + loadu16: loadu16, + loadu32: loadu32, + loadf32: loadf32, + loadf64: loadf64 + }; +} + +var sab = new SharedArrayBuffer(16); +var m = Module(this, {}, sab); + +function clearArray() { + var ui8 = new Uint8Array(sab); + for (var i = 0; i < sab.byteLength; ++i) { + ui8[i] = 0; + } +} + +function testElementType(taConstr, f, oobValue) { + clearArray(); + + var ta = new taConstr(sab); + var name = Object.prototype.toString.call(ta); + ta[0] = 10; + assertEquals(10, f(0), name); + assertEquals(0, f(1), name); + // out of bounds + assertEquals(oobValue, f(-1), name); + assertEquals(oobValue, f(ta.length), name); +} + +testElementType(Int8Array, m.loadi8, 0); +testElementType(Int16Array, m.loadi16, 0); +testElementType(Int32Array, m.loadi32, 0); +testElementType(Uint8Array, m.loadu8, 0); +testElementType(Uint16Array, m.loadu16, 0); +testElementType(Uint32Array, m.loadu32, 0); +testElementType(Float32Array, m.loadf32, NaN); +testElementType(Float64Array, m.loadf64, NaN); diff --git a/deps/v8/test/mjsunit/asm/atomics-or.js b/deps/v8/test/mjsunit/asm/atomics-or.js new file mode 100644 index 0000000000..df87d24d74 --- /dev/null +++ b/deps/v8/test/mjsunit/asm/atomics-or.js @@ -0,0 +1,93 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-atomics --harmony-sharedarraybuffer + +function Module(stdlib, foreign, heap) { + "use asm"; + var MEM8 = new stdlib.Int8Array(heap); + var MEM16 = new stdlib.Int16Array(heap); + var MEM32 = new stdlib.Int32Array(heap); + var MEMU8 = new stdlib.Uint8Array(heap); + var MEMU16 = new stdlib.Uint16Array(heap); + var MEMU32 = new stdlib.Uint32Array(heap); + var or = stdlib.Atomics.or; + var fround = stdlib.Math.fround; + + function ori8(i, x) { + i = i | 0; + x = x | 0; + return or(MEM8, i, x)|0; + } + + function ori16(i, x) { + i = i | 0; + x = x | 0; + return or(MEM16, i, x)|0; + } + + function ori32(i, x) { + i = i | 0; + x = x | 0; + return or(MEM32, i, x)|0; + } + + function oru8(i, x) { + i = i | 0; + x = x >>> 0; + return or(MEMU8, i, x)>>>0; + } + + function oru16(i, x) { + i = i | 0; + x = x >>> 0; + return or(MEMU16, i, x)>>>0; + } + + function oru32(i, x) { + i = i | 0; + x = x >>> 0; + return or(MEMU32, i, x)>>>0; + } + + return { + ori8: ori8, + ori16: ori16, + ori32: ori32, + oru8: oru8, + oru16: oru16, + oru32: oru32, + }; +} + +var sab = new SharedArrayBuffer(16); +var m = Module(this, {}, sab); + +function clearArray() { + var ui8 = new Uint8Array(sab); + for (var i = 0; i < sab.byteLength; ++i) { + ui8[i] = 0; + } +} + +function testElementType(taConstr, f) { + clearArray(); + + var ta = new taConstr(sab); + var name = Object.prototype.toString.call(ta); + assertEquals(0, f(0, 0xf), name); + assertEquals(0xf, ta[0]); + assertEquals(0xf, f(0, 0x11), name); + assertEquals(0x1f, ta[0]); + // out of bounds + assertEquals(0, f(-1, 0), name); + assertEquals(0, f(ta.length, 0), name); +} + +testElementType(Int8Array, m.ori8); +testElementType(Int16Array, m.ori16); +testElementType(Int32Array, m.ori32); +testElementType(Uint8Array, m.oru8); +testElementType(Uint16Array, m.oru16); +testElementType(Uint32Array, m.oru32); diff --git a/deps/v8/test/mjsunit/asm/atomics-store.js b/deps/v8/test/mjsunit/asm/atomics-store.js new file mode 100644 index 0000000000..1f7a5f91c7 --- /dev/null +++ b/deps/v8/test/mjsunit/asm/atomics-store.js @@ -0,0 +1,109 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-atomics --harmony-sharedarraybuffer + +function Module(stdlib, foreign, heap) { + "use asm"; + var MEM8 = new stdlib.Int8Array(heap); + var MEM16 = new stdlib.Int16Array(heap); + var MEM32 = new stdlib.Int32Array(heap); + var MEMU8 = new stdlib.Uint8Array(heap); + var MEMU16 = new stdlib.Uint16Array(heap); + var MEMU32 = new stdlib.Uint32Array(heap); + var MEMF32 = new stdlib.Float32Array(heap); + var MEMF64 = new stdlib.Float64Array(heap); + var store = stdlib.Atomics.store; + var fround = stdlib.Math.fround; + + function storei8(i, x) { + i = i | 0; + x = x | 0; + return store(MEM8, i, x)|0; + } + + function storei16(i, x) { + i = i | 0; + x = x | 0; + return store(MEM16, i, x)|0; + } + + function storei32(i, x) { + i = i | 0; + x = x | 0; + return store(MEM32, i, x)|0; + } + + function storeu8(i, x) { + i = i | 0; + x = x >>> 0; + return store(MEMU8, i, x)>>>0; + } + + function storeu16(i, x) { + i = i | 0; + x = x >>> 0; + return store(MEMU16, i, x)>>>0; + } + + function storeu32(i, x) { + i = i | 0; + x = x >>> 0; + return store(MEMU32, i, x)>>>0; + } + + function storef32(i, x) { + i = i | 0; + x = fround(x); + return fround(store(MEMF32, i, x)); + } + + function storef64(i, x) { + i = i | 0; + x = +x; + return +store(MEMF64, i, x); + } + + return { + storei8: storei8, + storei16: storei16, + storei32: storei32, + storeu8: storeu8, + storeu16: storeu16, + storeu32: storeu32, + storef32: storef32, + storef64: storef64 + }; +} + +var sab = new SharedArrayBuffer(16); +var m = Module(this, {}, sab); + +function clearArray() { + var ui8 = new Uint8Array(sab); + for (var i = 0; i < sab.byteLength; ++i) { + ui8[i] = 0; + } +} + +function testElementType(taConstr, f, oobValue) { + clearArray(); + + var ta = new taConstr(sab); + var name = Object.prototype.toString.call(ta); + assertEquals(10, f(0, 10), name); + assertEquals(10, ta[0]); + // out of bounds + assertEquals(oobValue, f(-1, 0), name); + assertEquals(oobValue, f(ta.length, 0), name); +} + +testElementType(Int8Array, m.storei8, 0); +testElementType(Int16Array, m.storei16, 0); +testElementType(Int32Array, m.storei32, 0); +testElementType(Uint8Array, m.storeu8, 0); +testElementType(Uint16Array, m.storeu16, 0); +testElementType(Uint32Array, m.storeu32, 0); +testElementType(Float32Array, m.storef32, NaN); +testElementType(Float64Array, m.storef64, NaN); diff --git a/deps/v8/test/mjsunit/asm/atomics-sub.js b/deps/v8/test/mjsunit/asm/atomics-sub.js new file mode 100644 index 0000000000..f9e56ffa4b --- /dev/null +++ b/deps/v8/test/mjsunit/asm/atomics-sub.js @@ -0,0 +1,94 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-atomics --harmony-sharedarraybuffer + +function Module(stdlib, foreign, heap) { + "use asm"; + var MEM8 = new stdlib.Int8Array(heap); + var MEM16 = new stdlib.Int16Array(heap); + var MEM32 = new stdlib.Int32Array(heap); + var MEMU8 = new stdlib.Uint8Array(heap); + var MEMU16 = new stdlib.Uint16Array(heap); + var MEMU32 = new stdlib.Uint32Array(heap); + var sub = stdlib.Atomics.sub; + var fround = stdlib.Math.fround; + + function subi8(i, x) { + i = i | 0; + x = x | 0; + return sub(MEM8, i, x)|0; + } + + function subi16(i, x) { + i = i | 0; + x = x | 0; + return sub(MEM16, i, x)|0; + } + + function subi32(i, x) { + i = i | 0; + x = x | 0; + return sub(MEM32, i, x)|0; + } + + function subu8(i, x) { + i = i | 0; + x = x >>> 0; + return sub(MEMU8, i, x)>>>0; + } + + function subu16(i, x) { + i = i | 0; + x = x >>> 0; + return sub(MEMU16, i, x)>>>0; + } + + function subu32(i, x) { + i = i | 0; + x = x >>> 0; + return sub(MEMU32, i, x)>>>0; + } + + return { + subi8: subi8, + subi16: subi16, + subi32: subi32, + subu8: subu8, + subu16: subu16, + subu32: subu32, + }; +} + +var sab = new SharedArrayBuffer(16); +var m = Module(this, {}, sab); + +function clearArray() { + var ui8 = new Uint8Array(sab); + for (var i = 0; i < sab.byteLength; ++i) { + ui8[i] = 0; + } +} + +function testElementType(taConstr, f) { + clearArray(); + + var ta = new taConstr(sab); + var name = Object.prototype.toString.call(ta); + ta[0] = 30; + assertEquals(30, f(0, 10), name); + assertEquals(20, ta[0]); + assertEquals(20, f(0, 10), name); + assertEquals(10, ta[0]); + // out of bounds + assertEquals(0, f(-1, 0), name); + assertEquals(0, f(ta.length, 0), name); +} + +testElementType(Int8Array, m.subi8); +testElementType(Int16Array, m.subi16); +testElementType(Int32Array, m.subi32); +testElementType(Uint8Array, m.subu8); +testElementType(Uint16Array, m.subu16); +testElementType(Uint32Array, m.subu32); diff --git a/deps/v8/test/mjsunit/asm/atomics-xor.js b/deps/v8/test/mjsunit/asm/atomics-xor.js new file mode 100644 index 0000000000..893ea013fd --- /dev/null +++ b/deps/v8/test/mjsunit/asm/atomics-xor.js @@ -0,0 +1,93 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-atomics --harmony-sharedarraybuffer + +function Module(stdlib, foreign, heap) { + "use asm"; + var MEM8 = new stdlib.Int8Array(heap); + var MEM16 = new stdlib.Int16Array(heap); + var MEM32 = new stdlib.Int32Array(heap); + var MEMU8 = new stdlib.Uint8Array(heap); + var MEMU16 = new stdlib.Uint16Array(heap); + var MEMU32 = new stdlib.Uint32Array(heap); + var xor = stdlib.Atomics.xor; + var fround = stdlib.Math.fround; + + function xori8(i, x) { + i = i | 0; + x = x | 0; + return xor(MEM8, i, x)|0; + } + + function xori16(i, x) { + i = i | 0; + x = x | 0; + return xor(MEM16, i, x)|0; + } + + function xori32(i, x) { + i = i | 0; + x = x | 0; + return xor(MEM32, i, x)|0; + } + + function xoru8(i, x) { + i = i | 0; + x = x >>> 0; + return xor(MEMU8, i, x)>>>0; + } + + function xoru16(i, x) { + i = i | 0; + x = x >>> 0; + return xor(MEMU16, i, x)>>>0; + } + + function xoru32(i, x) { + i = i | 0; + x = x >>> 0; + return xor(MEMU32, i, x)>>>0; + } + + return { + xori8: xori8, + xori16: xori16, + xori32: xori32, + xoru8: xoru8, + xoru16: xoru16, + xoru32: xoru32, + }; +} + +var sab = new SharedArrayBuffer(16); +var m = Module(this, {}, sab); + +function clearArray() { + var ui8 = new Uint8Array(sab); + for (var i = 0; i < sab.byteLength; ++i) { + ui8[i] = 0; + } +} + +function testElementType(taConstr, f) { + clearArray(); + + var ta = new taConstr(sab); + var name = Object.prototype.toString.call(ta); + assertEquals(0, f(0, 0xf), name); + assertEquals(0xf, ta[0]); + assertEquals(0xf, f(0, 0x11), name); + assertEquals(0x1e, ta[0]); + // out of bounds + assertEquals(0, f(-1, 0), name); + assertEquals(0, f(ta.length, 0), name); +} + +testElementType(Int8Array, m.xori8); +testElementType(Int16Array, m.xori16); +testElementType(Int32Array, m.xori32); +testElementType(Uint8Array, m.xoru8); +testElementType(Uint16Array, m.xoru16); +testElementType(Uint32Array, m.xoru32); diff --git a/deps/v8/test/mjsunit/big-array-literal.js b/deps/v8/test/mjsunit/big-array-literal.js index 7e19c0a2dc..19d1ff406d 100644 --- a/deps/v8/test/mjsunit/big-array-literal.js +++ b/deps/v8/test/mjsunit/big-array-literal.js @@ -27,8 +27,7 @@ // On MacOS X 10.7.5, this test needs a stack size of at least 788 kBytes. // On PPC64, this test needs a stack size of at least 698 kBytes. -// Flags: --stack-size=800 -// Flags: --turbo-deoptimization +// Flags: --stack-size=1000 // Test that we can make large object literals that work. // Also test that we can attempt to make even larger object literals without diff --git a/deps/v8/test/mjsunit/call-counts.js b/deps/v8/test/mjsunit/call-counts.js new file mode 100644 index 0000000000..d1488245f1 --- /dev/null +++ b/deps/v8/test/mjsunit/call-counts.js @@ -0,0 +1,43 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --noalways-opt + +// Locations in the type feedback vector where call counts are maintained for +// the two calls made from bar(); + +(function() { + const kFooCallExtraIndex = 5; + const kArrayCallExtraIndex = 7; + + function GetCallCount(func, slot) { + var vector = %GetTypeFeedbackVector(func); + // Call counts are recorded doubled. + var value = %FixedArrayGet(vector, slot); + return Math.floor(value / 2); + } + + function foo(a) { return a[3] * 16; } + + function bar(a) { + var result = 0; + for (var i = 0; i < 10; i++) { + result = foo(a); + if (i % 2 === 0) { + var r = Array(); + r[0] = 1; + result += r[0]; + } + } + return result; + } + + var a = [1, 2, 3]; + bar(a); + assertEquals(10, GetCallCount(bar, kFooCallExtraIndex)); + assertEquals(5, GetCallCount(bar, kArrayCallExtraIndex)); + + %OptimizeFunctionOnNextCall(bar); + bar(a); +})(); diff --git a/deps/v8/test/mjsunit/call-runtime-tail.js b/deps/v8/test/mjsunit/call-runtime-tail.js new file mode 100644 index 0000000000..6ad107dcb2 --- /dev/null +++ b/deps/v8/test/mjsunit/call-runtime-tail.js @@ -0,0 +1,81 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --nostress-opt --turbo + +var p0 = new Object(); +var p1 = new Object(); +var p2 = new Object(); + +// Ensure 1 parameter passed straight-through is handled correctly +var count1 = 100000; +tailee1 = function() { + "use strict"; + if (count1-- == 0) { + return this; + } + return %_CallFunction(this, tailee1); +}; + +%OptimizeFunctionOnNextCall(tailee1); +assertEquals(p0, tailee1.call(p0)); + +// Ensure 2 parameters passed straight-through trigger a tail call are handled +// correctly and don't cause a stack overflow. +var count2 = 100000; +tailee2 = function(px) { + "use strict"; + assertEquals(p2, px); + assertEquals(p1, this); + count2 = ((count2 | 0) - 1) | 0; + if ((count2 | 0) === 0) { + return this; + } + return %_CallFunction(this, px, tailee2); +}; + +%OptimizeFunctionOnNextCall(tailee2); +assertEquals(p1, tailee2.call(p1, p2)); + +// Ensure swapped 2 parameters don't trigger a tail call (parameter swizzling +// for the tail call isn't supported yet). +var count3 = 100000; +tailee3 = function(px) { + "use strict"; + if (count3-- == 0) { + return this; + } + return %_CallFunction(px, this, tailee3); +}; + +%OptimizeFunctionOnNextCall(tailee3); +assertThrows(function() { tailee3.call(p1, p2); }); + +// Ensure too many parameters defeats the tail call optimization (currently +// unsupported). +var count4 = 1000000; +tailee4 = function(px) { + "use strict"; + if (count4-- == 0) { + return this; + } + return %_CallFunction(this, px, undefined, tailee4); +}; + +%OptimizeFunctionOnNextCall(tailee4); +assertThrows(function() { tailee4.call(p1, p2); }); + +// Ensure too few parameters defeats the tail call optimization (currently +// unsupported). +var count5 = 1000000; +tailee5 = function(px) { + "use strict"; + if (count5-- == 0) { + return this; + } + return %_CallFunction(this, tailee5); +}; + +%OptimizeFunctionOnNextCall(tailee5); +assertThrows(function() { tailee5.call(p1, p2); }); diff --git a/deps/v8/test/mjsunit/compiler/deopt-tonumber-compare.js b/deps/v8/test/mjsunit/compiler/deopt-tonumber-compare.js new file mode 100644 index 0000000000..9a7e992ada --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-tonumber-compare.js @@ -0,0 +1,44 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +var m = (function() { + "use asm"; + function f(x) { + return x < 0; + } + function g(x) { + return 0 < x; + } + return { f: f, g: g }; +})(); +var f = m.f; +var g = m.g; + +var counter = 0; + +function deopt(f) { + return { + toString : function() { + %DeoptimizeFunction(f); + counter++; + return "2"; + } + }; +} + +assertEquals(false, f(deopt(f))); +assertEquals(1, counter); + +assertEquals(true, g(deopt(g))); +assertEquals(2, counter); + +%OptimizeFunctionOnNextCall(f); +assertEquals(false, f(deopt(f))); +assertEquals(3, counter); + +%OptimizeFunctionOnNextCall(g); +assertEquals(true, g(deopt(g))); +assertEquals(4, counter); diff --git a/deps/v8/test/mjsunit/compiler/deopt-tonumber-shift.js b/deps/v8/test/mjsunit/compiler/deopt-tonumber-shift.js new file mode 100644 index 0000000000..bb4d1d5c1c --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/deopt-tonumber-shift.js @@ -0,0 +1,40 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +var f = (function() { + "use asm"; + function f(x, y) { + return x << y; + } + return f; +})(); + +var counter = 0; + +var deopt = { toString : function() { + %DeoptimizeFunction(f); + counter++; + return "2"; +} }; + +var o = { toString : function() { + counter++; + return "1"; +} }; + +counter = 0; +assertEquals(4, f(deopt, o)); +assertEquals(2, counter); + +%OptimizeFunctionOnNextCall(f); +counter = 0; +assertEquals(4, f(o, deopt)); +assertEquals(2, counter); + +%OptimizeFunctionOnNextCall(f); +counter = 0; +assertEquals(8, f(deopt, deopt)); +assertEquals(2, counter); diff --git a/deps/v8/test/mjsunit/compiler/jsnatives.js b/deps/v8/test/mjsunit/compiler/jsnatives.js index ea2ecd2d30..ab70abc1bb 100644 --- a/deps/v8/test/mjsunit/compiler/jsnatives.js +++ b/deps/v8/test/mjsunit/compiler/jsnatives.js @@ -29,5 +29,5 @@ // Test call of JS runtime functions. -var a = %$isNaN(0/0); -assertEquals(true, a); +var a = %MakeError(0, "error"); +assertInstanceof(a, Error); diff --git a/deps/v8/test/mjsunit/compiler/optimize_max.js b/deps/v8/test/mjsunit/compiler/optimize_max.js new file mode 100644 index 0000000000..6baefe48ba --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/optimize_max.js @@ -0,0 +1,69 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +var DOUBLE_ZERO = %AllocateHeapNumber(); +var SMI_ZERO = 0; +var MINUS_ZERO = -0.0; + +function max1(a, b) { + a = +a; + b = +b; + return +(a < b ? b : a); +} + +function max2(a, b) { + a = +a; + b = +b; + return a < b ? b : a; +} + +for (f of [max1, max2]) { + for (var i = 0; i < 5; i++) { + assertEquals(4, f(3, 4)); + assertEquals(4, f(4, 3)); + assertEquals(4.3, f(3.3, 4.3)); + assertEquals(4.4, f(4.4, 3.4)); + + assertEquals(Infinity, 1 / f(SMI_ZERO, MINUS_ZERO)); + assertEquals(Infinity, 1 / f(DOUBLE_ZERO, MINUS_ZERO)); + assertEquals(-Infinity, 1 / f(MINUS_ZERO, SMI_ZERO)); + assertEquals(-Infinity, 1 / f(MINUS_ZERO, DOUBLE_ZERO)); + + assertEquals(NaN, f(NaN, NaN)); + assertEquals(3, f(3, NaN)); + assertEquals(NaN, f(NaN, 3)); + } +} + +function max3(a, b) { + a = +a; + b = +b; + return +(a > b ? a : b); +} + +function max4(a, b) { + a = +a; + b = +b; + return a > b ? a : b; +} + +for (f of [max3, max4]) { + for (var i = 0; i < 5; i++) { + assertEquals(4, f(3, 4)); + assertEquals(4, f(4, 3)); + assertEquals(4.3, f(3.3, 4.3)); + assertEquals(4.4, f(4.4, 3.4)); + + assertEquals(-Infinity, 1 / f(SMI_ZERO, MINUS_ZERO)); + assertEquals(-Infinity, 1 / f(DOUBLE_ZERO, MINUS_ZERO)); + assertEquals(Infinity, 1 / f(MINUS_ZERO, SMI_ZERO)); + assertEquals(Infinity, 1 / f(MINUS_ZERO, DOUBLE_ZERO)); + + assertEquals(NaN, f(NaN, NaN)); + assertEquals(NaN, f(3, NaN)); + assertEquals(3, f(NaN, 3)); + } +} diff --git a/deps/v8/test/mjsunit/compiler/optimize_min.js b/deps/v8/test/mjsunit/compiler/optimize_min.js new file mode 100644 index 0000000000..906b999584 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/optimize_min.js @@ -0,0 +1,69 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +var DOUBLE_ZERO = %AllocateHeapNumber(); +var SMI_ZERO = 0; +var MINUS_ZERO = -0.0; + +function min1(a, b) { + a = +a; + b = +b; + return +(a < b ? a : b); +} + +function min2(a, b) { + a = +a; + b = +b; + return a < b ? a : b; +} + +for (f of [min1, min2]) { + for (var i = 0; i < 5; i++) { + assertEquals(3, f(3, 4)); + assertEquals(3, f(4, 3)); + assertEquals(3.3, f(3.3, 4)); + assertEquals(3.4, f(4, 3.4)); + + assertEquals(-Infinity, 1 / f(SMI_ZERO, MINUS_ZERO)); + assertEquals(-Infinity, 1 / f(DOUBLE_ZERO, MINUS_ZERO)); + assertEquals(Infinity, 1 / f(MINUS_ZERO, SMI_ZERO)); + assertEquals(Infinity, 1 / f(MINUS_ZERO, DOUBLE_ZERO)); + + assertEquals(NaN, f(NaN, NaN)); + assertEquals(NaN, f(3, NaN)); + assertEquals(3, f(NaN, 3)); + } +} + +function min3(a, b) { + a = +a; + b = +b; + return +(a > b ? b : a); +} + +function min4(a, b) { + a = +a; + b = +b; + return a > b ? b : a; +} + +for (f of [min3, min4]) { + for (var i = 0; i < 5; i++) { + assertEquals(3, f(3, 4)); + assertEquals(3, f(4, 3)); + assertEquals(3.3, f(3.3, 4)); + assertEquals(3.4, f(4, 3.4)); + + assertEquals(Infinity, 1 / f(SMI_ZERO, MINUS_ZERO)); + assertEquals(Infinity, 1 / f(DOUBLE_ZERO, MINUS_ZERO)); + assertEquals(-Infinity, 1 / f(MINUS_ZERO, SMI_ZERO)); + assertEquals(-Infinity, 1 / f(MINUS_ZERO, DOUBLE_ZERO)); + + assertEquals(NaN, f(NaN, NaN)); + assertEquals(3, f(3, NaN)); + assertEquals(NaN, f(NaN, 3)); + } +} diff --git a/deps/v8/test/mjsunit/compiler/osr-array-len.js b/deps/v8/test/mjsunit/compiler/osr-array-len.js new file mode 100644 index 0000000000..aaee860d61 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/osr-array-len.js @@ -0,0 +1,22 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + + +function fastaRandom(n, table) { + var line = new Array(5); + while (n > 0) { + if (n < line.length) line = new Array(n); + %OptimizeOsr(); + line[0] = n; + n--; + } +} + +print("---BEGIN 1"); +assertEquals(undefined, fastaRandom(6, null)); +print("---BEGIN 2"); +assertEquals(undefined, fastaRandom(6, null)); +print("---END"); diff --git a/deps/v8/test/mjsunit/compiler/osr-maze1.js b/deps/v8/test/mjsunit/compiler/osr-maze1.js index 6e192c17b7..da17282742 100644 --- a/deps/v8/test/mjsunit/compiler/osr-maze1.js +++ b/deps/v8/test/mjsunit/compiler/osr-maze1.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --allow-natives-syntax --use-osr --turbo-deoptimization +// Flags: --allow-natives-syntax --use-osr function bar(goal) { var count = 0; diff --git a/deps/v8/test/mjsunit/compiler/osr-maze2.js b/deps/v8/test/mjsunit/compiler/osr-maze2.js index 96838a4c34..1fc1cd2db1 100644 --- a/deps/v8/test/mjsunit/compiler/osr-maze2.js +++ b/deps/v8/test/mjsunit/compiler/osr-maze2.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --allow-natives-syntax --use-osr --turbo-deoptimization +// Flags: --allow-natives-syntax --use-osr function bar() { var sum = 11; diff --git a/deps/v8/test/mjsunit/compiler/regress-4206.js b/deps/v8/test/mjsunit/compiler/regress-4206.js new file mode 100644 index 0000000000..742ed5dfe5 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-4206.js @@ -0,0 +1,28 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function Module(stdlib) { + "use asm"; + function TernaryMin(a, b) { + a=+(a); + b=+(b); + return (+((a < b) ? a : b)); + } + function TernaryMax(a, b) { + a=+(a); + b=+(b); + return (+((b < a) ? a : b)); + } + return { TernaryMin: TernaryMin, + TernaryMax: TernaryMax }; +} +var min = Module(this).TernaryMin; +var max = Module(this).TernaryMax; + +assertEquals(0.0, min(-0.0, 0.0)); +assertEquals(0.0, min(NaN, 0.0)); +assertEquals(-0.0, min(NaN, -0.0)); +assertEquals(-0.0, max(0.0, -0.0)); +assertEquals(0.0, max(NaN, 0.0)); +assertEquals(-0.0, max(NaN, -0.0)); diff --git a/deps/v8/test/mjsunit/compiler/regress-4207.js b/deps/v8/test/mjsunit/compiler/regress-4207.js new file mode 100644 index 0000000000..c4ab5a7837 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-4207.js @@ -0,0 +1,15 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +function bar() { return 0/0 && 1; } +assertEquals(NaN, bar()); +%OptimizeFunctionOnNextCall(bar); +assertEquals(NaN, bar()); + +function foo() { return 0/0 || 1; } +assertEquals(1, foo()); +%OptimizeFunctionOnNextCall(foo); +assertEquals(1, foo()); diff --git a/deps/v8/test/mjsunit/compiler/regress-445907.js b/deps/v8/test/mjsunit/compiler/regress-445907.js index c820753eec..8cde94457e 100644 --- a/deps/v8/test/mjsunit/compiler/regress-445907.js +++ b/deps/v8/test/mjsunit/compiler/regress-445907.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --turbo-deoptimization - v = []; v.length = (1 << 30); diff --git a/deps/v8/test/mjsunit/compiler/regress-446647.js b/deps/v8/test/mjsunit/compiler/regress-446647.js index 77757abd66..6387aaa697 100644 --- a/deps/v8/test/mjsunit/compiler/regress-446647.js +++ b/deps/v8/test/mjsunit/compiler/regress-446647.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --always-opt --turbo-filter=* --turbo-deoptimization --allow-natives-syntax +// Flags: --always-opt --turbo-filter=* --allow-natives-syntax function f(a,b) { a%b diff --git a/deps/v8/test/mjsunit/compiler/regress-447567.js b/deps/v8/test/mjsunit/compiler/regress-447567.js index b6dc653709..c348debee2 100644 --- a/deps/v8/test/mjsunit/compiler/regress-447567.js +++ b/deps/v8/test/mjsunit/compiler/regress-447567.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --turbo-deoptimization - assertThrows(function() { [0].every(function(){ Object.seal((new Int8Array())); }); }) diff --git a/deps/v8/test/mjsunit/compiler/regress-491578.js b/deps/v8/test/mjsunit/compiler/regress-491578.js new file mode 100644 index 0000000000..c27570456c --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-491578.js @@ -0,0 +1,15 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +function foo(x) { + if (x === undefined) return; + while (true) { + while (1 || 2) { } + f(); + } +} +%OptimizeFunctionOnNextCall(foo); +foo(); diff --git a/deps/v8/test/mjsunit/compiler/regress-shift-left.js b/deps/v8/test/mjsunit/compiler/regress-shift-left.js new file mode 100644 index 0000000000..110e899729 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-shift-left.js @@ -0,0 +1,41 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +(function ShiftLeftWithDeoptUsage() { + function g() {} + + function f() { + var tmp = 1264475713; + var tmp1 = tmp - (-913041544); + g(); + return 1 << tmp1; + } + + %OptimizeFunctionOnNextCall(f); + assertEquals(512, f()); +})(); + + +(function ShiftLeftWithCallUsage() { + var f = (function() { + "use asm" + // This is not a valid asm.js, we use the "use asm" here to + // trigger Turbofan without deoptimization support. + + function g(x) { return x; } + + function f() { + var tmp = 1264475713; + var tmp1 = tmp - (-913041544); + return g(1 << tmp1, tmp1); + } + + return f; + })(); + + %OptimizeFunctionOnNextCall(f); + assertEquals(512, f()); +})(); diff --git a/deps/v8/test/mjsunit/compiler/regress-shift-right-logical.js b/deps/v8/test/mjsunit/compiler/regress-shift-right-logical.js new file mode 100644 index 0000000000..f2be2ad52f --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-shift-right-logical.js @@ -0,0 +1,41 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +(function ShiftRightLogicalWithDeoptUsage() { + function g() {} + + function f() { + var tmp = 1264475713; + var tmp1 = tmp - (-913041544); + g(); + return 1 >>> tmp1; + } + + %OptimizeFunctionOnNextCall(f); + assertEquals(0, f()); +})(); + + +(function ShiftRightLogicalWithCallUsage() { + var f = (function() { + "use asm" + // This is not a valid asm.js, we use the "use asm" here to + // trigger Turbofan without deoptimization support. + + function g(x) { return x; } + + function f() { + var tmp = 1264475713; + var tmp1 = tmp - (-913041544); + return g(1 >>> tmp1, tmp1); + } + + return f; + })(); + + %OptimizeFunctionOnNextCall(f); + assertEquals(0, f()); +})(); diff --git a/deps/v8/test/mjsunit/compiler/regress-shift-right.js b/deps/v8/test/mjsunit/compiler/regress-shift-right.js new file mode 100644 index 0000000000..71bcb21f0e --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-shift-right.js @@ -0,0 +1,41 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +(function ShiftRightWithDeoptUsage() { + function g() {} + + function f() { + var tmp = 1264475713; + var tmp1 = tmp - (-913041544); + g(); + return 1 >> tmp1; + } + + %OptimizeFunctionOnNextCall(f); + assertEquals(0, f()); +})(); + + +(function ShiftRightWithCallUsage() { + var f = (function() { + "use asm" + // This is not a valid asm.js, we use the "use asm" here to + // trigger Turbofan without deoptimization support. + + function g(x) { return x; } + + function f() { + var tmp = 1264475713; + var tmp1 = tmp - (-913041544); + return g(1 >> tmp1, tmp1); + } + + return f; + })(); + + %OptimizeFunctionOnNextCall(f); + assertEquals(0, f()); +})(); diff --git a/deps/v8/test/mjsunit/compiler/regress-uint8-deopt.js b/deps/v8/test/mjsunit/compiler/regress-uint8-deopt.js index ba2823fa35..5be2d0ce6b 100644 --- a/deps/v8/test/mjsunit/compiler/regress-uint8-deopt.js +++ b/deps/v8/test/mjsunit/compiler/regress-uint8-deopt.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --turbo-asm --turbo-deoptimization --allow-natives-syntax +// Flags: --turbo-asm --turbo-asm-deoptimization --allow-natives-syntax function Module(heap) { "use asm"; diff --git a/deps/v8/test/mjsunit/compiler/regress-variable-liveness.js b/deps/v8/test/mjsunit/compiler/regress-variable-liveness.js new file mode 100644 index 0000000000..e18741d96e --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/regress-variable-liveness.js @@ -0,0 +1,22 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +function foo(x) { + %DeoptimizeFunction(run); + return x; +} + +function run() { + var line = new Array(2); + for (var n = 3; n > 0; n = n - 1) { + if (n < foo(line.length)) line = new Array(n); + line[0] = n; + } +} + +assertEquals(void 0, run()); +%OptimizeFunctionOnNextCall(run); +assertEquals(void 0, run()); diff --git a/deps/v8/test/mjsunit/compiler/stubs/floor-stub.js b/deps/v8/test/mjsunit/compiler/stubs/floor-stub.js new file mode 100644 index 0000000000..e3fc9b6003 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/stubs/floor-stub.js @@ -0,0 +1,54 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax --expose-natives-as=builtins --noalways-opt + +const kExtraTypeFeedbackMinusZeroSentinel = 1; +const kFirstSlotExtraTypeFeedbackIndex = 5; + +(function(){ + var floorFunc = function() { + Math.floor(NaN); + } + // Execute the function once to make sure it has a type feedback vector. + floorFunc(5); + var stub = builtins.MathFloorStub("MathFloorStub", 0); + assertTrue(kExtraTypeFeedbackMinusZeroSentinel !== + %FixedArrayGet(%GetTypeFeedbackVector(floorFunc), + kFirstSlotExtraTypeFeedbackIndex)); + assertEquals(5.0, stub(floorFunc, 4, 5.5)); + assertTrue(kExtraTypeFeedbackMinusZeroSentinel !== + %FixedArrayGet(%GetTypeFeedbackVector(floorFunc), + kFirstSlotExtraTypeFeedbackIndex)); + // Executing floor such that it returns -0 should set the proper sentinel in + // the feedback vector. + assertEquals(-Infinity, 1/stub(floorFunc, 4, -0)); + assertEquals(kExtraTypeFeedbackMinusZeroSentinel, + %FixedArrayGet(%GetTypeFeedbackVector(floorFunc), + kFirstSlotExtraTypeFeedbackIndex)); + %ClearFunctionTypeFeedback(floorFunc); +})(); diff --git a/deps/v8/test/mjsunit/compiler/try-binop.js b/deps/v8/test/mjsunit/compiler/try-binop.js new file mode 100644 index 0000000000..2132ad2c00 --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/try-binop.js @@ -0,0 +1,45 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +var boom = { valueOf: function() { throw "boom" } }; + +function mult_left_plain(x) { + try { + return 2 * x; + } catch (e) { + return e; + } +} + +%OptimizeFunctionOnNextCall(mult_left_plain); +assertEquals("boom", mult_left_plain(boom)); +assertEquals(46, mult_left_plain(23)); + +function mult_right_plain(x) { + try { + return x * 3; + } catch (e) { + return e; + } +} + +%OptimizeFunctionOnNextCall(mult_right_plain); +assertEquals("boom", mult_right_plain(boom)); +assertEquals(69, mult_right_plain(23)); + +function mult_none_plain(x,y) { + try { + return x * y; + } catch (e) { + return e; + } +} + +%OptimizeFunctionOnNextCall(mult_none_plain); +assertEquals("boom", mult_none_plain(boom, boom)); +assertEquals("boom", mult_none_plain(boom, 2)); +assertEquals("boom", mult_none_plain(2, boom)); +assertEquals(966, mult_none_plain(23, 42)); diff --git a/deps/v8/test/mjsunit/compiler/try-deopt.js b/deps/v8/test/mjsunit/compiler/try-deopt.js index dc44e7326f..a4a6eb0304 100644 --- a/deps/v8/test/mjsunit/compiler/try-deopt.js +++ b/deps/v8/test/mjsunit/compiler/try-deopt.js @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO(mstarzinger): Add FLAG_turbo_exceptions once we want ClusterFuzz. -// Flags: --allow-natives-syntax --turbo-deoptimization +// Flags: --allow-natives-syntax function DeoptFromTry(x) { try { diff --git a/deps/v8/test/mjsunit/compiler/try-osr.js b/deps/v8/test/mjsunit/compiler/try-osr.js new file mode 100644 index 0000000000..e4eb8dd9fa --- /dev/null +++ b/deps/v8/test/mjsunit/compiler/try-osr.js @@ -0,0 +1,51 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --turbo-osr + +function OSRInsideTry(x) { + try { + for (var i = 0; i < 10; i++) { if (i == 5) %OptimizeOsr(); } + throw x; + } catch (e) { + return e + 1; + } + return x + 2; +} +assertEquals(24, OSRInsideTry(23)); + + +function OSRInsideCatch(x) { + try { + throw x; + } catch (e) { + for (var i = 0; i < 10; i++) { if (i == 5) %OptimizeOsr(); } + return e + 1; + } + return x + 2; +} +assertEquals(24, OSRInsideCatch(23)); + + +function OSRInsideFinally_Return(x) { + try { + throw x; + } finally { + for (var i = 0; i < 10; i++) { if (i == 5) %OptimizeOsr(); } + return x + 1; + } + return x + 2; +} +assertEquals(24, OSRInsideFinally_Return(23)); + + +function OSRInsideFinally_ReThrow(x) { + try { + throw x; + } finally { + for (var i = 0; i < 10; i++) { if (i == 5) %OptimizeOsr(); } + } + return x + 2; +} +assertThrows("OSRInsideFinally_ReThrow(new Error)", Error); diff --git a/deps/v8/test/mjsunit/regress/regress-1878.js b/deps/v8/test/mjsunit/d8-worker-sharedarraybuffer.js index fbc47bdd14..791529fc89 100644 --- a/deps/v8/test/mjsunit/regress/regress-1878.js +++ b/deps/v8/test/mjsunit/d8-worker-sharedarraybuffer.js @@ -1,4 +1,4 @@ -// Copyright 2012 the V8 project authors. All rights reserved. +// Copyright 2015 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -25,20 +25,44 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// See: http://code.google.com/p/v8/issues/detail?id=1878 +// Flags: --harmony-sharedarraybuffer --harmony-atomics -// Flags: --allow-natives-syntax --expose_natives_as=natives +var workerScript = + `onmessage = function(m) { + var sab = m; + var ta = new Uint32Array(sab); + if (sab.byteLength !== 16) { + throw new Error('SharedArrayBuffer transfer byteLength'); + } + for (var i = 0; i < 4; ++i) { + if (ta[i] !== i) { + throw new Error('SharedArrayBuffer transfer value ' + i); + } + } + // Atomically update ta[0] + Atomics.store(ta, 0, 100); + };`; -var a = Array(); +if (this.Worker) { + var w = new Worker(workerScript); -for (var i = 0; i < 1000; i++) { - var ai = natives.InternalArray(10000); - assertFalse(%HaveSameMap(ai, a)); - assertTrue(%HasFastObjectElements(ai)); -} + var sab = new SharedArrayBuffer(16); + var ta = new Uint32Array(sab); + for (var i = 0; i < 4; ++i) { + ta[i] = i; + } + + // Transfer SharedArrayBuffer + w.postMessage(sab, [sab]); + assertEquals(16, sab.byteLength); // ArrayBuffer should not be neutered. + + // Spinwait for the worker to update ta[0] + var ta0; + while ((ta0 = Atomics.load(ta, 0)) == 0) {} + + assertEquals(100, ta0); + + w.terminate(); -for (var i = 0; i < 1000; i++) { - var ai = new natives.InternalArray(10000); - assertFalse(%HaveSameMap(ai, a)); - assertTrue(%HasFastObjectElements(ai)); + assertEquals(16, sab.byteLength); // Still not neutered. } diff --git a/deps/v8/test/mjsunit/regress/regress-parse-object-literal.js b/deps/v8/test/mjsunit/d8-worker-spawn-worker.js index 93725ebadb..a114d8587e 100644 --- a/deps/v8/test/mjsunit/regress/regress-parse-object-literal.js +++ b/deps/v8/test/mjsunit/d8-worker-spawn-worker.js @@ -1,4 +1,4 @@ -// Copyright 2013 the V8 project authors. All rights reserved. +// Copyright 2015 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -24,8 +24,17 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Flags: --noharmony-classes --noharmony-object-literals -// Should throw, not crash. -assertThrows("var o = { get /*space*/ () {} }"); +if (this.Worker) { + var workerScript = + `var w = new Worker('postMessage(42)'); + onmessage = function(parentMsg) { + w.postMessage(parentMsg); + var childMsg = w.getMessage(); + postMessage(childMsg); + };`; + + var w = new Worker(workerScript); + w.postMessage(9); + assertEquals(42, w.getMessage()); +} diff --git a/deps/v8/test/mjsunit/d8-worker.js b/deps/v8/test/mjsunit/d8-worker.js new file mode 100644 index 0000000000..f172fb1603 --- /dev/null +++ b/deps/v8/test/mjsunit/d8-worker.js @@ -0,0 +1,137 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Test the Worker API of d8. This test only makes sense with d8. A Worker +// spawns a new OS thread and isolate, and runs it concurrently with the +// current running thread. + +var workerScript = + `postMessage('Starting worker'); +// Set a global variable; should not be visible outside of the worker's +// context. + foo = 100; + var c = 0; + onmessage = function(m) { + switch (c++) { + case 0: + if (m !== undefined) throw new Error('undefined'); + break; + case 1: + if (m !== null) throw new Error('null'); + break; + case 2: + if (m !== true) throw new Error('true'); + break; + case 3: + if (m !== false) throw new Error('false'); + break; + case 4: + if (m !== 100) throw new Error('Number'); + break; + case 5: + if (m !== 'hi') throw new Error('String'); + break; + case 6: + if (JSON.stringify(m) !== '[4,true,\"bye\"]') { + throw new Error('Array'); + } + break; + case 7: + if (JSON.stringify(m) !== \"{'a':1,'b':2.5,'c':'three'}\") + throw new Error('Object'); + break; + case 8: + var ab = m; + var t = new Uint32Array(ab); + if (ab.byteLength !== 16) + throw new Error('ArrayBuffer clone byteLength'); + for (var i = 0; i < 4; ++i) + if (t[i] !== i) + throw new Error('ArrayBuffer clone value ' + i); + break; + case 9: + var ab = m; + var t = new Uint32Array(ab); + if (ab.byteLength !== 32) + throw new Error('ArrayBuffer transfer byteLength'); + for (var i = 0; i < 8; ++i) + if (t[i] !== i) + throw new Error('ArrayBuffer transfer value ' + i); + break; + } + if (c == 10) { + postMessage('DONE'); + } + };`; + + +if (this.Worker) { + function createArrayBuffer(byteLength) { + var ab = new ArrayBuffer(byteLength); + var t = new Uint32Array(ab); + for (var i = 0; i < byteLength / 4; ++i) + t[i] = i; + return ab; + } + + var w = new Worker(workerScript); + + assertEquals("Starting worker", w.getMessage()); + + w.postMessage(undefined); + w.postMessage(null); + w.postMessage(true); + w.postMessage(false); + w.postMessage(100); + w.postMessage("hi"); + w.postMessage([4, true, "bye"]); + w.postMessage({a: 1, b: 2.5, c: "three"}); + + // Clone ArrayBuffer + var ab1 = createArrayBuffer(16); + w.postMessage(ab1); + assertEquals(16, ab1.byteLength); // ArrayBuffer should not be neutered. + + // Transfer ArrayBuffer + var ab2 = createArrayBuffer(32); + w.postMessage(ab2, [ab2]); + assertEquals(0, ab2.byteLength); // ArrayBuffer should be neutered. + + assertEquals("undefined", typeof foo); + + // Read a message from the worker. + assertEquals("DONE", w.getMessage()); + + w.terminate(); + + + // Make sure that the main thread doesn't block forever in getMessage() if + // the worker dies without posting a message. + var w2 = new Worker(''); + var msg = w2.getMessage(); + assertEquals(undefined, msg); +} diff --git a/deps/v8/test/mjsunit/date.js b/deps/v8/test/mjsunit/date.js index 3d72032ab8..0fa23f8de1 100644 --- a/deps/v8/test/mjsunit/date.js +++ b/deps/v8/test/mjsunit/date.js @@ -340,3 +340,17 @@ date.getYear(); %OptimizeFunctionOnNextCall(Date.prototype.getYear); assertThrows(function() { Date.prototype.getYear.call(""); }, TypeError); assertUnoptimized(Date.prototype.getYear); + +delete Date.prototype.getUTCFullYear; +delete Date.prototype.getUTCMonth; +delete Date.prototype.getUTCDate; +delete Date.prototype.getUTCHours; +delete Date.prototype.getUTCMinutes; +delete Date.prototype.getUTCSeconds; +delete Date.prototype.getUTCMilliseconds; +date.toISOString(); + +(function TestDeleteToString() { + assertTrue(delete Date.prototype.toString); + assertTrue('[object Date]' !== Date()); +})(); diff --git a/deps/v8/test/mjsunit/debug-backtrace-text.js b/deps/v8/test/mjsunit/debug-backtrace-text.js index 3bfaeb0dad..61648fa4e2 100644 --- a/deps/v8/test/mjsunit/debug-backtrace-text.js +++ b/deps/v8/test/mjsunit/debug-backtrace-text.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --turbo-deoptimization +// Flags: --expose-debug-as debug // The functions used for testing backtraces. function Point(x, y) { diff --git a/deps/v8/test/mjsunit/debug-backtrace.js b/deps/v8/test/mjsunit/debug-backtrace.js index b4fb2c8535..01775f560e 100644 --- a/deps/v8/test/mjsunit/debug-backtrace.js +++ b/deps/v8/test/mjsunit/debug-backtrace.js @@ -165,7 +165,7 @@ function listener(event, exec_state, event_data, data) { assertEquals("f", response.lookup(frame.func.ref).name); assertTrue(frame.constructCall); assertEquals(31, frame.line); - assertEquals(3, frame.column); + assertEquals(2, frame.column); assertEquals(2, frame.arguments.length); assertEquals('x', frame.arguments[0].name); assertEquals('number', response.lookup(frame.arguments[0].value.ref).type); @@ -179,7 +179,7 @@ function listener(event, exec_state, event_data, data) { assertEquals(0, frame.index); assertEquals("f", response.lookup(frame.func.ref).name); assertEquals(31, frame.line); - assertEquals(3, frame.column); + assertEquals(2, frame.column); assertEquals(2, frame.arguments.length); assertEquals('x', frame.arguments[0].name); assertEquals('number', response.lookup(frame.arguments[0].value.ref).type); diff --git a/deps/v8/test/mjsunit/debug-break-inline.js b/deps/v8/test/mjsunit/debug-break-inline.js index 3ef4d4eafe..4418fa8d1b 100644 --- a/deps/v8/test/mjsunit/debug-break-inline.js +++ b/deps/v8/test/mjsunit/debug-break-inline.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --allow-natives-syntax --turbo-deoptimization +// Flags: --expose-debug-as debug --allow-natives-syntax // This test tests that deoptimization due to debug breaks works for // inlined functions where the full-code is generated before the diff --git a/deps/v8/test/mjsunit/debug-breakpoints.js b/deps/v8/test/mjsunit/debug-breakpoints.js index 22c7ab51b2..c293eb313a 100644 --- a/deps/v8/test/mjsunit/debug-breakpoints.js +++ b/deps/v8/test/mjsunit/debug-breakpoints.js @@ -211,7 +211,6 @@ assertTrue(Debug.showBreakPoints(g).indexOf("[B0]") < 0); // (This may be sensitive to compiler break position map generation). function h() {a=f(f2(1,2),f3())+f3();b=f3();} var scenario = [ - [5, "{a[B0]=f"], [6, "{a=[B0]f("], [7, "{a=f([B0]f2("], [16, "f2(1,2),[B0]f3()"], diff --git a/deps/v8/test/mjsunit/debug-clearbreakpointgroup.js b/deps/v8/test/mjsunit/debug-clearbreakpointgroup.js index 3c03bdaa39..b0ff38371f 100644 --- a/deps/v8/test/mjsunit/debug-clearbreakpointgroup.js +++ b/deps/v8/test/mjsunit/debug-clearbreakpointgroup.js @@ -26,7 +26,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug -// Flags: --turbo-deoptimization // Get the Debug object exposed from the debug context global object. var Debug = debug.Debug diff --git a/deps/v8/test/mjsunit/debug-evaluate-arguments.js b/deps/v8/test/mjsunit/debug-evaluate-arguments.js index 9765f19370..92b745f1da 100644 --- a/deps/v8/test/mjsunit/debug-evaluate-arguments.js +++ b/deps/v8/test/mjsunit/debug-evaluate-arguments.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --turbo-deoptimization +// Flags: --expose-debug-as debug // Get the Debug object exposed from the debug context global object. Debug = debug.Debug diff --git a/deps/v8/test/mjsunit/debug-evaluate-closure.js b/deps/v8/test/mjsunit/debug-evaluate-closure.js index cf507b57d2..778defd0ab 100644 --- a/deps/v8/test/mjsunit/debug-evaluate-closure.js +++ b/deps/v8/test/mjsunit/debug-evaluate-closure.js @@ -26,7 +26,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug --allow-natives-syntax -// Flags: --turbo-deoptimization Debug = debug.Debug; var listened = false; diff --git a/deps/v8/test/mjsunit/debug-evaluate-with.js b/deps/v8/test/mjsunit/debug-evaluate-with.js index 3f3310f9f5..4e02d9e188 100644 --- a/deps/v8/test/mjsunit/debug-evaluate-with.js +++ b/deps/v8/test/mjsunit/debug-evaluate-with.js @@ -26,7 +26,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug -// Flags: --turbo-deoptimization // Get the Debug object exposed from the debug context global object. Debug = debug.Debug diff --git a/deps/v8/test/mjsunit/debug-liveedit-breakpoints.js b/deps/v8/test/mjsunit/debug-liveedit-breakpoints.js index 1d28ab9ff6..bbcb4cda94 100644 --- a/deps/v8/test/mjsunit/debug-liveedit-breakpoints.js +++ b/deps/v8/test/mjsunit/debug-liveedit-breakpoints.js @@ -29,6 +29,7 @@ // Get the Debug object exposed from the debug context global object. Debug = debug.Debug +Debug.setListener(function(){}); var function_z_text = " function Z() {\n" @@ -111,3 +112,4 @@ for (var i = 0; i < breaks_ids.length; i++) { } assertEquals(0, Debug.scriptBreakPoints().length); +Debug.setListener(null); diff --git a/deps/v8/test/mjsunit/debug-liveedit-patch-positions.js b/deps/v8/test/mjsunit/debug-liveedit-patch-positions.js index b0d3c20d9a..c669b5e862 100644 --- a/deps/v8/test/mjsunit/debug-liveedit-patch-positions.js +++ b/deps/v8/test/mjsunit/debug-liveedit-patch-positions.js @@ -33,6 +33,7 @@ // corresponding byte-code PCs should coincide before change and after it. Debug = debug.Debug +Debug.setListener(function() {}); eval( "function F1() { return 5; }\n" + @@ -124,3 +125,5 @@ print(pcArray2); if (pcArray1 && pcArray2) { assertArrayEquals(pcArray1, pcArray2); } + +Debug.setListener(null); diff --git a/deps/v8/test/mjsunit/debug-liveedit-stack-padding.js b/deps/v8/test/mjsunit/debug-liveedit-stack-padding.js index 36de356973..b219e568a7 100644 --- a/deps/v8/test/mjsunit/debug-liveedit-stack-padding.js +++ b/deps/v8/test/mjsunit/debug-liveedit-stack-padding.js @@ -29,6 +29,7 @@ // Get the Debug object exposed from the debug context global object. Debug = debug.Debug; +Debug.setListener(listener); SlimFunction = eval( "(function() {\n " + @@ -76,7 +77,6 @@ function listener(event, exec_state, event_data, data) { } } -Debug.setListener(listener); var animal = SlimFunction(); @@ -86,3 +86,5 @@ if (saved_exception) { } assertEquals("Capybara", animal); + +Debug.setListener(null); diff --git a/deps/v8/test/mjsunit/debug-receiver.js b/deps/v8/test/mjsunit/debug-receiver.js index 2d5d2e08de..21cdde84a2 100644 --- a/deps/v8/test/mjsunit/debug-receiver.js +++ b/deps/v8/test/mjsunit/debug-receiver.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --turbo-deoptimization +// Flags: --expose-debug-as debug // Get the Debug object exposed from the debug context global object. Debug = debug.Debug; diff --git a/deps/v8/test/mjsunit/debug-references.js b/deps/v8/test/mjsunit/debug-references.js index cb9f3701e2..f1a0508de6 100644 --- a/deps/v8/test/mjsunit/debug-references.js +++ b/deps/v8/test/mjsunit/debug-references.js @@ -25,8 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --turbo-deoptimization -// Flags: --stack-trace-on-illegal +// Flags: --expose-debug-as debug --stack-trace-on-illegal // Get the Debug object exposed from the debug context global object. Debug = debug.Debug diff --git a/deps/v8/test/mjsunit/debug-scopes.js b/deps/v8/test/mjsunit/debug-scopes.js index ad137de205..c388a67196 100644 --- a/deps/v8/test/mjsunit/debug-scopes.js +++ b/deps/v8/test/mjsunit/debug-scopes.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --allow-natives-syntax --turbo-deoptimization +// Flags: --expose-debug-as debug --allow-natives-syntax // The functions used for testing backtraces. They are at the top to make the // testing of source line/column easier. @@ -167,6 +167,10 @@ function CheckScopeContent(content, number, exec_state) { if (!scope.scopeObject().property('arguments').isUndefined()) { scope_size--; } + // Ditto for 'this'. + if (!scope.scopeObject().property('this').isUndefined()) { + scope_size--; + } // Skip property with empty name. if (!scope.scopeObject().property('').isUndefined()) { scope_size--; diff --git a/deps/v8/test/mjsunit/debug-script-breakpoints.js b/deps/v8/test/mjsunit/debug-script-breakpoints.js index ec9656c28c..d4ce6dc98b 100644 --- a/deps/v8/test/mjsunit/debug-script-breakpoints.js +++ b/deps/v8/test/mjsunit/debug-script-breakpoints.js @@ -28,6 +28,7 @@ // Flags: --expose-debug-as debug // Get the Debug object exposed from the debug context global object. Debug = debug.Debug +Debug.setListener(function(){}); // Set and remove a script break point for a named script. var sbp = Debug.setScriptBreakPointByName("1", 2, 3); @@ -110,3 +111,5 @@ Debug.clearBreakPoint(sbp3); assertEquals(1, Debug.scriptBreakPoints().length); Debug.clearBreakPoint(sbp2); assertEquals(0, Debug.scriptBreakPoints().length); + +Debug.setListener(null); diff --git a/deps/v8/test/mjsunit/debug-script.js b/deps/v8/test/mjsunit/debug-script.js index af1eb454d6..32415c2428 100644 --- a/deps/v8/test/mjsunit/debug-script.js +++ b/deps/v8/test/mjsunit/debug-script.js @@ -26,7 +26,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug --expose-gc --send-idle-notification -// Flags: --allow-natives-syntax +// Flags: --allow-natives-syntax --expose-natives-as natives // Flags: --noharmony-shipping // Note: this test checks that that the number of scripts reported as native // by Debug.scripts() is the same as a number of core native scripts. @@ -36,6 +36,7 @@ // Get the Debug object exposed from the debug context global object. Debug = debug.Debug; +Debug.setListener(function(){}); Date(); RegExp(); @@ -103,3 +104,5 @@ assertEquals(Debug.ScriptType.Normal, debug_script.type); // Check a nonexistent script. var dummy_script = Debug.findScript('dummy.js'); assertTrue(typeof dummy_script == 'undefined'); + +Debug.setListener(null); diff --git a/deps/v8/test/mjsunit/debug-step-2.js b/deps/v8/test/mjsunit/debug-step-2.js index 5fe7466cb7..502b426ee2 100644 --- a/deps/v8/test/mjsunit/debug-step-2.js +++ b/deps/v8/test/mjsunit/debug-step-2.js @@ -26,7 +26,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug -// Flags: --turbo-deoptimization // This test tests that full code compiled without debug break slots // is recompiled with debug break slots when debugging is started. diff --git a/deps/v8/test/mjsunit/debug-stepframe.js b/deps/v8/test/mjsunit/debug-stepframe.js index 8f4ee4ca11..f7983c010e 100644 --- a/deps/v8/test/mjsunit/debug-stepframe.js +++ b/deps/v8/test/mjsunit/debug-stepframe.js @@ -11,7 +11,7 @@ function f0() { try { throw 1; } catch (e) { - try{ + try { f1(); } catch (e) { var v02 = 2; // Break 13 @@ -19,6 +19,8 @@ function f0() { } var v03 = 3; var v04 = 4; + eval('var v05 = 5; // Break 14'); + var v06 = 6; // Break 15 } function f1() { @@ -104,7 +106,7 @@ for (step_size = 1; step_size < 6; step_size++) { Debug.setListener(listener); debugger; // Break 0 f0(); - Debug.setListener(null); // Break 14 + Debug.setListener(null); // Break 16 assertTrue(break_count > 14); } diff --git a/deps/v8/test/mjsunit/debug-stepin-accessor-ic.js b/deps/v8/test/mjsunit/debug-stepin-accessor-ic.js new file mode 100644 index 0000000000..5f40dcb250 --- /dev/null +++ b/deps/v8/test/mjsunit/debug-stepin-accessor-ic.js @@ -0,0 +1,49 @@ +// 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. + +// Flags: --expose-debug-as debug + +function get() { + return 3; // Break +} // Break + +function set(x) { + this.x = x; // Break +} // Break + +var o = {}; +Object.defineProperty(o, "get", { get : get }); +Object.defineProperty(o, "set", { set : set }); + +function f() { + for (var i = 0; i < 10; i++) { // Break + o.get; // Break + o.set = 1; // Break + } +} // Break + +var break_count = 0; +var exception = null; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + var source_line = exec_state.frame(0).sourceLineText(); + assertTrue(source_line.indexOf("// Break") > 0); + exec_state.prepareStep(Debug.StepAction.StepIn, 1); + break_count++; + } catch (e) { + exception = e; + } +} + +var Debug = debug.Debug; +Debug.setListener(listener); + +debugger; // Break +f(); // Break + +Debug.setListener(null); // Break +assertEquals(86, break_count); +assertNull(exception); diff --git a/deps/v8/test/mjsunit/debug-stepin-positions.js b/deps/v8/test/mjsunit/debug-stepin-positions.js index ff532e3dd7..ac010aac42 100644 --- a/deps/v8/test/mjsunit/debug-stepin-positions.js +++ b/deps/v8/test/mjsunit/debug-stepin-positions.js @@ -33,7 +33,7 @@ function DebuggerStatement() { debugger; /*pause*/ } -function TestCase(fun, frame_number) { +function TestCase(fun, frame_number, line_number) { var exception = false; var codeSnippet = undefined; var resultPositions = undefined; @@ -64,8 +64,13 @@ function TestCase(fun, frame_number) { Debug.setListener(listener); + var breakpointId; + if (line_number) breakpointId = Debug.setBreakPoint(fun, line_number); + fun(); + if (line_number) Debug.clearBreakPoint(breakpointId); + Debug.setListener(null); assertTrue(!exception, exception); @@ -116,9 +121,7 @@ function TestCaseWithDebugger(fun) { } function TestCaseWithBreakpoint(fun, line_number, frame_number) { - var breakpointId = Debug.setBreakPoint(fun, line_number); - TestCase(fun, frame_number); - Debug.clearBreakPoint(breakpointId); + TestCase(fun, frame_number, line_number); } function TestCaseWithException(fun, frame_number) { diff --git a/deps/v8/test/mjsunit/debug-stepout-scope-part1.js b/deps/v8/test/mjsunit/debug-stepout-scope-part1.js index f49b1a07eb..cce88b73dc 100644 --- a/deps/v8/test/mjsunit/debug-stepout-scope-part1.js +++ b/deps/v8/test/mjsunit/debug-stepout-scope-part1.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --expose-natives-as=builtins +// Flags: --expose-debug-as debug // Check that the ScopeIterator can properly recreate the scope at // every point when stepping through functions. diff --git a/deps/v8/test/mjsunit/debug-stepout-scope-part2.js b/deps/v8/test/mjsunit/debug-stepout-scope-part2.js index 69cee994aa..ba05317979 100644 --- a/deps/v8/test/mjsunit/debug-stepout-scope-part2.js +++ b/deps/v8/test/mjsunit/debug-stepout-scope-part2.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --expose-natives-as=builtins +// Flags: --expose-debug-as debug // Check that the ScopeIterator can properly recreate the scope at // every point when stepping through functions. diff --git a/deps/v8/test/mjsunit/debug-stepout-scope-part3.js b/deps/v8/test/mjsunit/debug-stepout-scope-part3.js index 319f87991f..c120640605 100644 --- a/deps/v8/test/mjsunit/debug-stepout-scope-part3.js +++ b/deps/v8/test/mjsunit/debug-stepout-scope-part3.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --expose-natives-as=builtins +// Flags: --expose-debug-as debug // Check that the ScopeIterator can properly recreate the scope at // every point when stepping through functions. diff --git a/deps/v8/test/mjsunit/debug-stepout-scope-part4.js b/deps/v8/test/mjsunit/debug-stepout-scope-part4.js index eb9c82f8c7..a5743fe566 100644 --- a/deps/v8/test/mjsunit/debug-stepout-scope-part4.js +++ b/deps/v8/test/mjsunit/debug-stepout-scope-part4.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --expose-natives-as=builtins +// Flags: --expose-debug-as debug // Check that the ScopeIterator can properly recreate the scope at // every point when stepping through functions. diff --git a/deps/v8/test/mjsunit/debug-stepout-scope-part5.js b/deps/v8/test/mjsunit/debug-stepout-scope-part5.js index 250bee4d81..cabacbaa8e 100644 --- a/deps/v8/test/mjsunit/debug-stepout-scope-part5.js +++ b/deps/v8/test/mjsunit/debug-stepout-scope-part5.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --expose-natives-as=builtins +// Flags: --expose-debug-as debug // Check that the ScopeIterator can properly recreate the scope at // every point when stepping through functions. diff --git a/deps/v8/test/mjsunit/debug-stepout-scope-part6.js b/deps/v8/test/mjsunit/debug-stepout-scope-part6.js index 2d8357fea4..f222fbd4fb 100644 --- a/deps/v8/test/mjsunit/debug-stepout-scope-part6.js +++ b/deps/v8/test/mjsunit/debug-stepout-scope-part6.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --expose-natives-as=builtins +// Flags: --expose-debug-as debug // Check that the ScopeIterator can properly recreate the scope at // every point when stepping through functions. diff --git a/deps/v8/test/mjsunit/debug-stepout-scope-part7.js b/deps/v8/test/mjsunit/debug-stepout-scope-part7.js index 4f0c066843..eba115d26f 100644 --- a/deps/v8/test/mjsunit/debug-stepout-scope-part7.js +++ b/deps/v8/test/mjsunit/debug-stepout-scope-part7.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --expose-natives-as=builtins +// Flags: --expose-debug-as debug // Check that the ScopeIterator can properly recreate the scope at // every point when stepping through functions. diff --git a/deps/v8/test/mjsunit/debug-stepout-scope-part8.js b/deps/v8/test/mjsunit/debug-stepout-scope-part8.js index f91fab5e4d..c0a8a0034a 100644 --- a/deps/v8/test/mjsunit/debug-stepout-scope-part8.js +++ b/deps/v8/test/mjsunit/debug-stepout-scope-part8.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-debug-as debug --expose-natives-as=builtins +// Flags: --expose-debug-as debug // Check that the ScopeIterator can properly recreate the scope at // every point when stepping through functions. diff --git a/deps/v8/test/mjsunit/declare-locally.js b/deps/v8/test/mjsunit/declare-locally.js index 20bfe6da1f..dca357b060 100644 --- a/deps/v8/test/mjsunit/declare-locally.js +++ b/deps/v8/test/mjsunit/declare-locally.js @@ -33,7 +33,7 @@ // This exercises the code in runtime.cc in // DeclareGlobal...Locally(). -// Flags: --es52_globals +// Flags: --es52-globals this.__proto__.foo = 42; this.__proto__.bar = 87; diff --git a/deps/v8/test/mjsunit/deserialize-script-id.js b/deps/v8/test/mjsunit/deserialize-script-id.js index ba54b4698e..5dca9f353a 100644 --- a/deps/v8/test/mjsunit/deserialize-script-id.js +++ b/deps/v8/test/mjsunit/deserialize-script-id.js @@ -5,13 +5,13 @@ // Flags: --allow-natives-syntax --cache=code // Test that script ids are unique and we found the correct ones. +var Debug = %GetDebugContext().Debug; +Debug.setListener(function(){}); + var scripts = %DebugGetLoadedScripts(); scripts.sort(function(a, b) { return a.id - b.id; }); -var user_script_count = 0; scripts.reduce(function(prev, cur) { assertTrue(prev === undefined || prev.id != cur.id); - if (cur.type == 2) user_script_count++; }); -// Found mjsunit.js and this script. -assertEquals(2, user_script_count); +Debug.setListener(null); diff --git a/deps/v8/test/mjsunit/elements-kind.js b/deps/v8/test/mjsunit/elements-kind.js index 64b4a094ff..cb2d178a7e 100644 --- a/deps/v8/test/mjsunit/elements-kind.js +++ b/deps/v8/test/mjsunit/elements-kind.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --allow-natives-syntax --expose-gc --nostress-opt --typed-array-max_size_in-heap=2048 +// Flags: --allow-natives-syntax --expose-gc --nostress-opt --typed-array-max-size-in-heap=2048 var elements_kind = { fast_smi_only : 'fast smi only elements', diff --git a/deps/v8/test/mjsunit/enumeration-order.js b/deps/v8/test/mjsunit/enumeration-order.js index 70942ee13c..d2ac90485e 100644 --- a/deps/v8/test/mjsunit/enumeration-order.js +++ b/deps/v8/test/mjsunit/enumeration-order.js @@ -71,9 +71,9 @@ proto2.a = 0; proto2[2] = 0; proto2[3] = 0; // also on the 'proto1' object proto2.b = 0; -proto2[4294967295] = 0; +proto2[4294967294] = 0; proto2.c = 0; -proto2[4294967296] = 0; +proto2[4294967295] = 0; var proto1 = {}; proto1[5] = 0; @@ -98,8 +98,8 @@ var expected = ['23', '42', // indexed from 'o' '-23', '300000000000', 'f', 'g', '-4', // named from 'o' '3', '5', // indexed from 'proto1' 'd', 'e', // named from 'proto1' - '2', '140000', '4294967295', // indexed from 'proto2' - 'a', 'b', 'c', '4294967296']; // named from 'proto2' + '2', '140000', '4294967294', // indexed from 'proto2' + 'a', 'b', 'c', '4294967295']; // named from 'proto2' var actual = []; for (var p in o) actual.push(p); assertArrayEquals(expected, actual); diff --git a/deps/v8/test/mjsunit/es6/arguments-iterator.js b/deps/v8/test/mjsunit/es6/arguments-iterator.js index 32d4b11ee1..cf1e1f97ca 100644 --- a/deps/v8/test/mjsunit/es6/arguments-iterator.js +++ b/deps/v8/test/mjsunit/es6/arguments-iterator.js @@ -219,10 +219,7 @@ function TestArgumentsAsProto() { assertSame([][Symbol.iterator], o[Symbol.iterator]); assertFalse(o.hasOwnProperty(Symbol.iterator)); assertSame([][Symbol.iterator], o[Symbol.iterator]); - // This should throw, but currently it doesn't, because - // ExecutableAccessorInfo callbacks don't see the current strict mode. - // See note in accessors.cc:SetPropertyOnInstanceIfInherited. - o[Symbol.iterator] = 10; + assertThrows(function () { o[Symbol.iterator] = 10 }); assertFalse(o.hasOwnProperty(Symbol.iterator)); assertEquals([][Symbol.iterator], o[Symbol.iterator]); assertSame([][Symbol.iterator], arguments[Symbol.iterator]); diff --git a/deps/v8/test/mjsunit/es6/block-for.js b/deps/v8/test/mjsunit/es6/block-for.js index b91af0116c..420c41e610 100644 --- a/deps/v8/test/mjsunit/es6/block-for.js +++ b/deps/v8/test/mjsunit/es6/block-for.js @@ -158,7 +158,7 @@ closure_in_for_next(); // In a for-in statement the iteration variable is fresh -// for earch iteration. +// for each iteration. function closures3(x) { let a = []; for (let p in x) { @@ -171,3 +171,28 @@ function closures3(x) { } } closures3({a : [0], b : 1, c : {v : 1}, get d() {}, set e(x) {}}); + +// Check normal for statement completion values. +assertEquals(1, eval("for (let i = 0; i < 10; i++) { 1; }")); +assertEquals(9, eval("for (let i = 0; i < 10; i++) { i; }")); +assertEquals(undefined, eval("for (let i = 0; false;) { }")); +assertEquals(undefined, eval("for (const i = 0; false;) { }")); +assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { }")); +assertEquals(undefined, eval("for (let i = 0; false;) { i; }")); +assertEquals(undefined, eval("for (const i = 0; false;) { i; }")); +assertEquals(undefined, eval("for (let i = 0; true;) { break; }")); +assertEquals(undefined, eval("for (const i = 0; true;) { break; }")); +assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { continue; }")); +assertEquals(undefined, eval("for (let i = 0; true;) { break; i; }")); +assertEquals(undefined, eval("for (const i = 0; true;) { break; i; }")); +assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { continue; i; }")); +assertEquals(0, eval("for (let i = 0; true;) { i; break; }")); +assertEquals(0, eval("for (const i = 0; true;) { i; break; }")); +assertEquals(9, eval("for (let i = 0; i < 10; i++) { i; continue; }")); +assertEquals(3, eval("for (let i = 0; true; i++) { i; if (i >= 3) break; }")); +assertEquals(2, eval("for (let i = 0; true; i++) { if (i >= 3) break; i; }")); +assertEquals( + 2, eval("for (let i = 0; i < 10; i++) { if (i >= 3) continue; i; }")); +assertEquals(undefined, eval("foo: for (let i = 0; true;) { break foo; }")); +assertEquals(undefined, eval("foo: for (const i = 0; true;) { break foo; }")); +assertEquals(3, eval("foo: for (let i = 3; true;) { i; break foo; }")); diff --git a/deps/v8/test/mjsunit/es6/block-non-strict-errors.js b/deps/v8/test/mjsunit/es6/block-non-strict-errors.js index 48cac21141..50d5f22cf1 100644 --- a/deps/v8/test/mjsunit/es6/block-non-strict-errors.js +++ b/deps/v8/test/mjsunit/es6/block-non-strict-errors.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-classes - function CheckError(source) { var exception = null; try { diff --git a/deps/v8/test/mjsunit/harmony/class-property-name-eval-arguments.js b/deps/v8/test/mjsunit/es6/class-property-name-eval-arguments.js index cc53030920..72ff60fd3e 100644 --- a/deps/v8/test/mjsunit/harmony/class-property-name-eval-arguments.js +++ b/deps/v8/test/mjsunit/es6/class-property-name-eval-arguments.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-classes --harmony-sloppy +// Flags: --harmony-sloppy (function Method() { diff --git a/deps/v8/test/mjsunit/harmony/classes-experimental.js b/deps/v8/test/mjsunit/es6/classes-experimental.js index e7ebbda735..4607a25957 100644 --- a/deps/v8/test/mjsunit/harmony/classes-experimental.js +++ b/deps/v8/test/mjsunit/es6/classes-experimental.js @@ -1,8 +1,6 @@ // 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. -// -// Flags: --harmony-classes 'use strict'; (function TestArgumentsAccess() { diff --git a/deps/v8/test/mjsunit/harmony/classes-lazy-parsing.js b/deps/v8/test/mjsunit/es6/classes-lazy-parsing.js index 2c0301957a..c1bf31da2d 100644 --- a/deps/v8/test/mjsunit/harmony/classes-lazy-parsing.js +++ b/deps/v8/test/mjsunit/es6/classes-lazy-parsing.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-classes --min-preparse-length=0 +// Flags: --min-preparse-length=0 'use strict'; @@ -16,6 +16,19 @@ class Derived extends Base { m() { return super.m(); } + evalM() { + return eval('super.m()'); + } } assertEquals(42, new Derived().m()); +assertEquals(42, new Derived().evalM()); + + +class LazyDerived extends Base { + constructor() { + eval('super()'); + } +} +assertInstanceof(new LazyDerived(), LazyDerived); +assertInstanceof(new LazyDerived(), Base); diff --git a/deps/v8/test/mjsunit/harmony/classes-maps.js b/deps/v8/test/mjsunit/es6/classes-maps.js index c82fc52d8d..e519676aa6 100644 --- a/deps/v8/test/mjsunit/harmony/classes-maps.js +++ b/deps/v8/test/mjsunit/es6/classes-maps.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Flags: --harmony-classes --allow-natives-syntax +// Flags: --allow-natives-syntax 'use strict'; (function TestMaps() { diff --git a/deps/v8/test/mjsunit/harmony/classes-subclass-arrays.js b/deps/v8/test/mjsunit/es6/classes-subclass-arrays.js index e0363c715b..74feb6aeb4 100644 --- a/deps/v8/test/mjsunit/harmony/classes-subclass-arrays.js +++ b/deps/v8/test/mjsunit/es6/classes-subclass-arrays.js @@ -1,8 +1,7 @@ // Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// -// Flags: --harmony-classes + 'use strict'; (function TestDefaultConstructor() { diff --git a/deps/v8/test/mjsunit/harmony/classes.js b/deps/v8/test/mjsunit/es6/classes.js index 9c09041345..a1420be1c2 100644 --- a/deps/v8/test/mjsunit/harmony/classes.js +++ b/deps/v8/test/mjsunit/es6/classes.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-classes --harmony-sloppy +// Flags: --harmony-sloppy (function TestBasics() { var C = class C {} diff --git a/deps/v8/test/mjsunit/es6/debug-blockscopes.js b/deps/v8/test/mjsunit/es6/debug-blockscopes.js index 39849da95f..31208d41f4 100644 --- a/deps/v8/test/mjsunit/es6/debug-blockscopes.js +++ b/deps/v8/test/mjsunit/es6/debug-blockscopes.js @@ -372,13 +372,16 @@ function for_loop_1() { listener_delegate = function(exec_state) { CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Block, debug.ScopeType.Local, debug.ScopeType.Script, debug.ScopeType.Global], exec_state); CheckScopeContent({x:'y'}, 0, exec_state); // The function scope contains a temporary iteration variable, but it is // hidden to the debugger. - CheckScopeContent({}, 1, exec_state); + // TODO(adamk): This variable is only used to provide a TDZ for the enumerable + // expression and should not be visible to the debugger. + CheckScopeContent({x:undefined}, 1, exec_state); }; for_loop_1(); EndTest(); @@ -398,6 +401,7 @@ function for_loop_2() { listener_delegate = function(exec_state) { CheckScopeChain([debug.ScopeType.Block, debug.ScopeType.Block, + debug.ScopeType.Block, debug.ScopeType.Local, debug.ScopeType.Script, debug.ScopeType.Global], exec_state); @@ -405,7 +409,9 @@ listener_delegate = function(exec_state) { CheckScopeContent({x:'y'}, 1, exec_state); // The function scope contains a temporary iteration variable, hidden to the // debugger. - CheckScopeContent({}, 2, exec_state); + // TODO(adamk): This variable is only used to provide a TDZ for the enumerable + // expression and should not be visible to the debugger. + CheckScopeContent({x:undefined}, 2, exec_state); }; for_loop_2(); EndTest(); diff --git a/deps/v8/test/mjsunit/es6/debug-evaluate-blockscopes.js b/deps/v8/test/mjsunit/es6/debug-evaluate-blockscopes.js index e24ca78315..efc334e35f 100644 --- a/deps/v8/test/mjsunit/es6/debug-evaluate-blockscopes.js +++ b/deps/v8/test/mjsunit/es6/debug-evaluate-blockscopes.js @@ -48,8 +48,6 @@ function f() { // Get the Debug object exposed from the debug context global object. var Debug = debug.Debug -// Set breakpoint on line 6. -var bp = Debug.setBreakPoint(f, 6); function listener(event, exec_state, event_data, data) { if (event == Debug.DebugEvent.Break) { @@ -59,6 +57,10 @@ function listener(event, exec_state, event_data, data) { // Add the debug event listener. Debug.setListener(listener); + +//Set breakpoint on line 6. +var bp = Debug.setBreakPoint(f, 6); + result = -1; f(); assertEquals(1, result); @@ -107,3 +109,5 @@ assertEquals(null, exception, exception); exception = null; f2(); assertEquals(null, exception, exception); + +Debug.setListener(null); diff --git a/deps/v8/test/mjsunit/harmony/debug-step-into-class-extends.js b/deps/v8/test/mjsunit/es6/debug-step-into-class-extends.js index ffc6fda63f..c368414ffc 100644 --- a/deps/v8/test/mjsunit/harmony/debug-step-into-class-extends.js +++ b/deps/v8/test/mjsunit/es6/debug-step-into-class-extends.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --expose-debug-as debug --harmony-classes +// Flags: --expose-debug-as debug 'use strict'; diff --git a/deps/v8/test/mjsunit/harmony/debug-step-into-constructor.js b/deps/v8/test/mjsunit/es6/debug-step-into-constructor.js index dbef60f846..66fc0b99d0 100644 --- a/deps/v8/test/mjsunit/harmony/debug-step-into-constructor.js +++ b/deps/v8/test/mjsunit/es6/debug-step-into-constructor.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --expose-debug-as debug --harmony-classes +// Flags: --expose-debug-as debug 'use strict'; @@ -14,6 +14,7 @@ function listener(event, execState, eventData, data) { if (!done) { execState.prepareStep(Debug.StepAction.StepInto); var s = execState.frame().sourceLineText(); + print(s); assertTrue(s.indexOf('// ' + stepCount + '.') !== -1); stepCount++; } @@ -24,10 +25,10 @@ Debug.setListener(listener); class Base { - constructor() { - var x = 1; // 1. - var y = 2; // 2. - done = true; // 3. + constructor() { // 1. + var x = 1; // 2. + var y = 2; // 3. + done = true; // 4. } } @@ -40,7 +41,7 @@ class Derived extends Base {} var bp = Debug.setBreakPoint(Base, 0); new Base(); - assertEquals(4, stepCount); + assertEquals(5, stepCount); Debug.clearBreakPoint(bp); })(); @@ -52,7 +53,7 @@ class Derived extends Base {} var bp = Debug.setBreakPoint(Base, 0); new Derived(); - assertEquals(4, stepCount); + assertEquals(5, stepCount); Debug.clearBreakPoint(bp); })(); @@ -68,7 +69,7 @@ class Derived extends Base {} var bp = Debug.setBreakPoint(f, 0); f(); - assertEquals(4, stepCount); + assertEquals(5, stepCount); Debug.clearBreakPoint(bp); })(); @@ -86,7 +87,7 @@ class Derived extends Base {} var bp = Debug.setBreakPoint(f, 0); f(); - assertEquals(4, stepCount); + assertEquals(5, stepCount); Debug.clearBreakPoint(bp); })(); @@ -104,7 +105,7 @@ class Derived extends Base {} var bp = Debug.setBreakPoint(f, 0); f(); - assertEquals(4, stepCount); + assertEquals(5, stepCount); Debug.clearBreakPoint(bp); })(); diff --git a/deps/v8/test/mjsunit/es6/debug-stepnext-for.js b/deps/v8/test/mjsunit/es6/debug-stepnext-for.js index 98af911ae3..fe50fa76b9 100644 --- a/deps/v8/test/mjsunit/es6/debug-stepnext-for.js +++ b/deps/v8/test/mjsunit/es6/debug-stepnext-for.js @@ -58,7 +58,9 @@ function f() { s += a[j]; // Break L } - // TODO(yangguo): add test case for for-let. + for (let i = 0; i < 3; i++) { // Break m + s += a[i]; // Break M + } } // Break y function listener(event, exec_state, event_data, data) { @@ -81,36 +83,39 @@ Debug.setListener(listener); f(); Debug.setListener(null); // Break z -print(JSON.stringify(log)); +print("log:\n"+ JSON.stringify(log)); // The let declaration differs from var in that the loop variable // is declared in every iteration. var expected = [ // Entry "a2","b2", - // Empty for-in-var: var decl, get enumerable - "c7","c16", + // Empty for-in-var: get enumerable + "c16", // Empty for-in: get enumerable "d12", - // For-in-var: var decl, get enumerable, assign, body, assign, body, ... - "e7","e16","e11","E4","e11","E4","e11","E4","e11", + // For-in-var: get enumerable, assign, body, assign, body, ... + "e16","e11","E4","e11","E4","e11","E4","e11", // For-in: get enumerable, assign, body, assign, body, ... "f12","f7","F4","f7","F4","f7","F4","f7", - // For-in-let: get enumerable, next, new let, body, next, new let, ... - "g16","g11","g7","G4","g11","g7","G4","g11","g7","G4","g11", - // For-of-var: var decl, next(), body, next(), body, ... - "h7","h16","H4","h16","H4","h16","H4","h16", + // For-in-let: get enumerable, next, body, next, ... + "g16","g11","G4","g11","G4","g11","G4","g11", + // For-of-var: next(), body, next(), body, ... + "h16","H4","h16","H4","h16","H4","h16", // For-of: next(), body, next(), body, ... "i12","I4","i12","I4","i12","I4","i12", - // For-of-let: next(), new let, body, next(), new let, ... - "j16","j7","J4","j16","j7","J4","j16","j7","J4","j16", + // For-of-let: next(), body, next(), ... + "j16","J4","j16","J4","j16","J4","j16", // For-var: var decl, condition, body, next, condition, body, ... "k7","k20","K4","k23","k20","K4","k23","k20","K4","k23","k20", // For: init, condition, body, next, condition, body, ... - "l11","l16","L4","l19","l16","L4","l19","l16","L4","l19","l16", + "l7","l16","L4","l19","l16","L4","l19","l16","L4","l19","l16", + // For-let: init, condition, body, next, condition, body, ... + "m7","m20","M4","m23","m20","M4","m23","m20","M4","m23","m20", // Exit. "y0","z0", ] +print("expected:\n"+ JSON.stringify(expected)); assertArrayEquals(expected, log); -assertEquals(48, s); +assertEquals(54, s); assertNull(exception); diff --git a/deps/v8/test/mjsunit/es6/generators-relocation.js b/deps/v8/test/mjsunit/es6/generators-relocation.js index 6babb148be..2636f52d7b 100644 --- a/deps/v8/test/mjsunit/es6/generators-relocation.js +++ b/deps/v8/test/mjsunit/es6/generators-relocation.js @@ -25,13 +25,13 @@ function RunTest(formals_and_body, args, value1, value2) { // Advance to the first yield. assertIteratorResult(value1, false, obj.next()); - // Add a breakpoint on line 3 (the second yield). - var bp = Debug.setBreakPoint(gen, 3); - // Enable the debugger, which should force recompilation of the generator // function and relocation of the suspended generator activation. Debug.setListener(listener); + // Add a breakpoint on line 3 (the second yield). + var bp = Debug.setBreakPoint(gen, 3); + // Check that the generator resumes and suspends properly. assertIteratorResult(value2, false, obj.next()); diff --git a/deps/v8/test/mjsunit/es6/generators-runtime.js b/deps/v8/test/mjsunit/es6/generators-runtime.js index 115c7a4149..98015b7f7c 100644 --- a/deps/v8/test/mjsunit/es6/generators-runtime.js +++ b/deps/v8/test/mjsunit/es6/generators-runtime.js @@ -35,6 +35,7 @@ function* g() { yield 1; } var GeneratorFunctionPrototype = Object.getPrototypeOf(g); var GeneratorFunction = GeneratorFunctionPrototype.constructor; var GeneratorObjectPrototype = GeneratorFunctionPrototype.prototype; +var IteratorPrototype = Object.getPrototypeOf(GeneratorObjectPrototype); // A generator function should have the same set of properties as any // other function. @@ -51,16 +52,9 @@ function TestGeneratorFunctionInstance() { var prop = f_own_property_names[i]; var f_desc = Object.getOwnPropertyDescriptor(f, prop); var g_desc = Object.getOwnPropertyDescriptor(g, prop); - if (prop === "prototype") { - // ES6 draft 03-17-2015 section 25.2.2.2 - assertFalse(g_desc.writable, prop); - assertFalse(g_desc.enumerable, prop); - assertFalse(g_desc.configurable, prop); - } else { - assertEquals(f_desc.configurable, g_desc.configurable, prop); - assertEquals(f_desc.writable, g_desc.writable, prop); - assertEquals(f_desc.enumerable, g_desc.enumerable, prop); - } + assertEquals(f_desc.configurable, g_desc.configurable, prop); + assertEquals(f_desc.writable, g_desc.writable, prop); + assertEquals(f_desc.enumerable, g_desc.enumerable, prop); } } TestGeneratorFunctionInstance(); @@ -100,7 +94,7 @@ TestGeneratorFunctionPrototype(); // Functions that we associate with generator objects are actually defined by // a common prototype. function TestGeneratorObjectPrototype() { - assertSame(Object.prototype, + assertSame(IteratorPrototype, Object.getPrototypeOf(GeneratorObjectPrototype)); assertSame(GeneratorObjectPrototype, Object.getPrototypeOf((function*(){yield 1}).prototype)); @@ -134,16 +128,6 @@ function TestGeneratorObjectPrototype() { assertTrue(throw_desc.writable); assertFalse(throw_desc.enumerable); assertTrue(throw_desc.configurable); - - var iterator_desc = Object.getOwnPropertyDescriptor(GeneratorObjectPrototype, - Symbol.iterator); - assertTrue(iterator_desc !== undefined); - assertFalse(iterator_desc.writable); - assertFalse(iterator_desc.enumerable); - assertFalse(iterator_desc.configurable); - - // The generator object's "iterator" function is just the identity. - assertSame(iterator_desc.value.call(42), 42); } TestGeneratorObjectPrototype(); @@ -165,6 +149,13 @@ function TestGeneratorFunction() { assertTrue((new GeneratorFunction()) instanceof GeneratorFunction); assertTrue(GeneratorFunction() instanceof GeneratorFunction); + + // ES6 draft 04-14-15, section 25.2.2.2 + var prototype_desc = Object.getOwnPropertyDescriptor(GeneratorFunction, + "prototype"); + assertFalse(prototype_desc.writable); + assertFalse(prototype_desc.enumerable); + assertFalse(prototype_desc.configurable); } TestGeneratorFunction(); diff --git a/deps/v8/test/mjsunit/es6/indexed-integer-exotics.js b/deps/v8/test/mjsunit/es6/indexed-integer-exotics.js index 7aefd78c4f..85ae3692d8 100644 --- a/deps/v8/test/mjsunit/es6/indexed-integer-exotics.js +++ b/deps/v8/test/mjsunit/es6/indexed-integer-exotics.js @@ -8,7 +8,7 @@ Object.prototype["10"] = "unreachable"; Object.prototype["7"] = "unreachable"; Object.prototype["-1"] = "unreachable"; Object.prototype["-0"] = "unreachable"; -Object.prototype["4294967296"] = "unreachable"; +Object.prototype["4294967295"] = "unreachable"; var array = new Int32Array(10); @@ -17,12 +17,12 @@ function check() { assertEquals(undefined, array["-1"]); assertEquals(undefined, array["-0"]); assertEquals(undefined, array["10"]); - assertEquals(undefined, array["4294967296"]); + assertEquals(undefined, array["4294967295"]); } assertEquals("unreachable", array.__proto__["-1"]); assertEquals("unreachable", array.__proto__["-0"]); assertEquals("unreachable", array.__proto__["10"]); - assertEquals("unreachable", array.__proto__["4294967296"]); + assertEquals("unreachable", array.__proto__["4294967295"]); } check(); @@ -30,19 +30,19 @@ check(); array["-1"] = "unreachable"; array["-0"] = "unreachable"; array["10"] = "unreachable"; -array["4294967296"] = "unreachable"; +array["4294967295"] = "unreachable"; check(); delete array["-0"]; delete array["-1"]; delete array["10"]; -delete array["4294967296"]; +delete array["4294967295"]; assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "-1")); assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "-0")); assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "10")); -assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "4294967296")); +assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "4294967295")); assertEquals(10, Object.keys(array).length); check(); @@ -55,9 +55,10 @@ for (var i = 0; i < 3; i++) { %OptimizeFunctionOnNextCall(f); assertEquals(undefined, f()); -Object.defineProperty(new Int32Array(), "-1", {'value': 1}); -Object.defineProperty(new Int32Array(), "-0", {'value': 1}); -Object.defineProperty(new Int32Array(), "-10", {'value': 1}); -Object.defineProperty(new Int32Array(), "4294967296", {'value': 1}); +assertThrows('Object.defineProperty(new Int32Array(100), -1, {value: 1})'); +// -0 gets converted to the string "0", so use "-0" instead. +assertThrows('Object.defineProperty(new Int32Array(100), "-0", {value: 1})'); +assertThrows('Object.defineProperty(new Int32Array(100), -10, {value: 1})'); +assertThrows('Object.defineProperty(new Int32Array(), 4294967295, {value: 1})'); check(); diff --git a/deps/v8/test/mjsunit/es6/iterator-prototype.js b/deps/v8/test/mjsunit/es6/iterator-prototype.js new file mode 100644 index 0000000000..0b266e9897 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/iterator-prototype.js @@ -0,0 +1,58 @@ +// 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. + +var arrayIteratorPrototype = [].entries().__proto__; +var iteratorPrototype = arrayIteratorPrototype.__proto__; + +assertSame(Object.prototype, Object.getPrototypeOf(iteratorPrototype)); +assertTrue(Object.isExtensible(iteratorPrototype)); +assertSame(0, Object.getOwnPropertyNames(iteratorPrototype).length); +assertSame(1, Object.getOwnPropertySymbols(iteratorPrototype).length); +assertSame(Symbol.iterator, + Object.getOwnPropertySymbols(iteratorPrototype)[0]); + +var descr = Object.getOwnPropertyDescriptor(iteratorPrototype, Symbol.iterator); +assertTrue(descr.configurable); +assertFalse(descr.enumerable); +assertTrue(descr.writable); + +var iteratorFunction = descr.value; +assertSame('function', typeof iteratorFunction); +assertSame(0, iteratorFunction.length); +assertSame('[Symbol.iterator]', iteratorFunction.name); + +var obj = {}; +assertSame(obj, iteratorFunction.call(obj)); +assertSame(iteratorPrototype, iteratorPrototype[Symbol.iterator]()); + +var mapIteratorPrototype = new Map().entries().__proto__; +var setIteratorPrototype = new Set().values().__proto__; +var stringIteratorPrototype = 'abc'[Symbol.iterator]().__proto__; +assertSame(iteratorPrototype, mapIteratorPrototype.__proto__); +assertSame(iteratorPrototype, setIteratorPrototype.__proto__); +assertSame(iteratorPrototype, stringIteratorPrototype.__proto__); + +var typedArrays = [ + Float32Array, + Float64Array, + Int16Array, + Int32Array, + Int8Array, + Uint16Array, + Uint32Array, + Uint8Array, + Uint8ClampedArray, +]; + +for (var constructor of typedArrays) { + var array = new constructor(); + var iterator = array[Symbol.iterator](); + assertSame(iteratorPrototype, iterator.__proto__.__proto__); +} + +function* gen() {} +assertSame(iteratorPrototype, gen.prototype.__proto__.__proto__); +var g = gen(); +assertSame(gen.prototype, g.__proto__); +assertSame(iteratorPrototype, g.__proto__.__proto__.__proto__); diff --git a/deps/v8/test/mjsunit/harmony/method-name-eval-arguments.js b/deps/v8/test/mjsunit/es6/method-name-eval-arguments.js index 360aadbca9..8792177e25 100644 --- a/deps/v8/test/mjsunit/harmony/method-name-eval-arguments.js +++ b/deps/v8/test/mjsunit/es6/method-name-eval-arguments.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-object-literals - (function TestSloppyMode() { var o = { eval() { diff --git a/deps/v8/test/mjsunit/harmony/object-literals-method.js b/deps/v8/test/mjsunit/es6/object-literals-method.js index 535231ea62..e4527cb776 100644 --- a/deps/v8/test/mjsunit/harmony/object-literals-method.js +++ b/deps/v8/test/mjsunit/es6/object-literals-method.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-object-literals --allow-natives-syntax +// Flags: --allow-natives-syntax (function TestBasics() { @@ -156,6 +156,7 @@ var GeneratorFunction = function*() {}.__proto__.constructor; +var GeneratorPrototype = Object.getPrototypeOf(function*() {}).prototype; function assertIteratorResult(value, done, result) { @@ -215,6 +216,19 @@ function assertIteratorResult(value, done, result) { })(); +(function TestGeneratorPrototypeDescriptor() { + var object = { + *method() {} + }; + + var desc = Object.getOwnPropertyDescriptor(object.method, 'prototype'); + assertFalse(desc.enumerable); + assertFalse(desc.configurable); + assertTrue(desc.writable); + assertEquals(GeneratorPrototype, Object.getPrototypeOf(desc.value)); +})(); + + (function TestGeneratorProto() { var object = { *method() {} diff --git a/deps/v8/test/mjsunit/harmony/object-literals-property-shorthand.js b/deps/v8/test/mjsunit/es6/object-literals-property-shorthand.js index 9756da46c1..29ce66d270 100644 --- a/deps/v8/test/mjsunit/harmony/object-literals-property-shorthand.js +++ b/deps/v8/test/mjsunit/es6/object-literals-property-shorthand.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-object-literals - (function TestBasics() { var x = 1; diff --git a/deps/v8/test/mjsunit/es6/promise-internal-setter.js b/deps/v8/test/mjsunit/es6/promise-internal-setter.js new file mode 100644 index 0000000000..83e4738316 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/promise-internal-setter.js @@ -0,0 +1,17 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +'use strict'; + +Object.defineProperties(Object.prototype, { + promise: {set: assertUnreachable}, + reject: {set: assertUnreachable}, + resolve: {set: assertUnreachable}, +}); + +class P extends Promise {} + +P.all([Promise.resolve('ok')]); +P.race([Promise.resolve('ok')]); +P.defer(); diff --git a/deps/v8/test/mjsunit/es6/regress/regress-2506.js b/deps/v8/test/mjsunit/es6/regress/regress-2506.js index b5cc91dbd7..5f88fcd1d4 100644 --- a/deps/v8/test/mjsunit/es6/regress/regress-2506.js +++ b/deps/v8/test/mjsunit/es6/regress/regress-2506.js @@ -18,15 +18,15 @@ assertEquals(3, f[2]()); let x = 1; s = 0; -for (const x of [x, x+1, x+2]) { - s += x; +for (const z of [x, x+1, x+2]) { + s += z; } assertEquals(6, s); s = 0; var q = 1; -for (const q of [q, q+1, q+2]) { - s += q; +for (const x of [q, q+1, q+2]) { + s += x; } assertEquals(6, s); @@ -56,15 +56,15 @@ assertThrows("'use strict'; for (const x in [1,2,3]) { x++ }", TypeError); let x = 1; s = 0; - for (const x of [x, x+1, x+2]) { - s += x; + for (const q of [x, x+1, x+2]) { + s += q; } assertEquals(6, s); s = 0; var q = 1; - for (const q of [q, q+1, q+2]) { - s += q; + for (const x of [q, q+1, q+2]) { + s += x; } assertEquals(6, s); diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-3750.js b/deps/v8/test/mjsunit/es6/regress/regress-3750.js index d1f21f9bd3..a425def2b7 100644 --- a/deps/v8/test/mjsunit/harmony/regress/regress-3750.js +++ b/deps/v8/test/mjsunit/es6/regress/regress-3750.js @@ -1,8 +1,7 @@ // 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. -// -// Flags: --harmony-classes + 'use strict'; class Example { } Object.observe(Example.prototype, function(){}); diff --git a/deps/v8/test/mjsunit/es6/regress/regress-4097.js b/deps/v8/test/mjsunit/es6/regress/regress-4097.js new file mode 100644 index 0000000000..52f2e9f20d --- /dev/null +++ b/deps/v8/test/mjsunit/es6/regress/regress-4097.js @@ -0,0 +1,37 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(function StoreToSuper () { + "use strict"; + class A { + s() { + super.bla = 10; + } + }; + + let a = new A(); + (new A).s.call(a); + assertEquals(10, a.bla); + assertThrows(function() { (new A).s.call(undefined); }, TypeError); + assertThrows(function() { (new A).s.call(42); }, TypeError); + assertThrows(function() { (new A).s.call(null); }, TypeError); + assertThrows(function() { (new A).s.call("abc"); }, TypeError); +})(); + + +(function LoadFromSuper () { + "use strict"; + class A { + s() { + return super.bla; + } + }; + + let a = new A(); + assertSame(undefined, (new A).s.call(a)); + assertSame(undefined, (new A).s.call(undefined)); + assertSame(undefined, (new A).s.call(42)); + assertSame(undefined, (new A).s.call(null)); + assertSame(undefined, (new A).s.call("abc")); +})(); diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-455141.js b/deps/v8/test/mjsunit/es6/regress/regress-455141.js index cf2141f903..676adebe72 100644 --- a/deps/v8/test/mjsunit/harmony/regress/regress-455141.js +++ b/deps/v8/test/mjsunit/es6/regress/regress-455141.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Flags: --harmony-classes --no-lazy +// Flags: --no-lazy "use strict"; class Base { } diff --git a/deps/v8/test/mjsunit/es6/string-html.js b/deps/v8/test/mjsunit/es6/string-html.js index 4f3feb56dd..690830ba84 100644 --- a/deps/v8/test/mjsunit/es6/string-html.js +++ b/deps/v8/test/mjsunit/es6/string-html.js @@ -157,3 +157,45 @@ assertThrows(function() { String.prototype.sup.call(null); }, TypeError); assertEquals(String.prototype.sup.length, 0); + + +(function TestToString() { + var calls = 0; + var obj = { + toString() { + calls++; + return 'abc'; + }, + valueOf() { + assertUnreachable(); + } + }; + + var methodNames = [ + 'anchor', + 'big', + 'blink', + 'bold', + 'fixed', + 'fontcolor', + 'fontsize', + 'italics', + 'link', + 'small', + 'strike', + 'sub', + 'sup', + ]; + for (var name of methodNames) { + calls = 0; + String.prototype[name].call(obj); + assertEquals(1, calls); + } +})(); + + +(function TestDeleteStringRelace() { + assertEquals('<a name="n">s</a>', 's'.anchor('n')); + assertTrue(delete String.prototype.replace); + assertEquals('<a name="n">s</a>', 's'.anchor('n')); +})(); diff --git a/deps/v8/test/mjsunit/es6/templates.js b/deps/v8/test/mjsunit/es6/templates.js index 0734f0e5d0..feb7364613 100644 --- a/deps/v8/test/mjsunit/es6/templates.js +++ b/deps/v8/test/mjsunit/es6/templates.js @@ -588,6 +588,26 @@ var global = this; })(); +(function testReturnValueAsTagFn() { + "use strict"; + var i = 0; + function makeTag() { + return function tag(cs) { + var args = Array.prototype.slice.call(arguments, 1); + var rcs = []; + rcs.raw = cs.map(function(s) { + return '!' + s + '!'; + }); + args.unshift(rcs); + return String.raw.apply(null, args); + } + } + assertEquals('!hi!', makeTag()`hi`); + assertEquals('!test!0!test!', makeTag()`test${0}test`); + assertEquals('!!', makeTag()``); +}); + + (function testToStringSubstitutions() { var a = { toString: function() { return "a"; }, diff --git a/deps/v8/test/mjsunit/harmony/toMethod.js b/deps/v8/test/mjsunit/es6/toMethod.js index 81db5830c2..c18251b2dc 100644 --- a/deps/v8/test/mjsunit/harmony/toMethod.js +++ b/deps/v8/test/mjsunit/es6/toMethod.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Flags: --harmony-classes --allow-natives-syntax +// Flags: --allow-natives-syntax (function TestSingleClass() { diff --git a/deps/v8/test/mjsunit/es6/typedarray-copywithin.js b/deps/v8/test/mjsunit/es6/typedarray-copywithin.js new file mode 100644 index 0000000000..ad5a0df563 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/typedarray-copywithin.js @@ -0,0 +1,173 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var typedArrayConstructors = [ + Uint8Array, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, + Uint8ClampedArray, + Float32Array, + Float64Array]; + +function CheckEachTypedArray(fn) { + typedArrayConstructors.forEach(fn); +} + +CheckEachTypedArray(function copyWithinArity(constructor) { + assertEquals(new constructor([]).copyWithin.length, 2); +}); + + +CheckEachTypedArray(function copyWithinTargetAndStart(constructor) { + // works with two arguments + assertArrayEquals([4, 5, 3, 4, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(0, 3)); + assertArrayEquals([1, 4, 5, 4, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(1, 3)); + assertArrayEquals([1, 3, 4, 5, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(1, 2)); + assertArrayEquals([1, 2, 3, 4, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(2, 2)); +}); + + +CheckEachTypedArray(function copyWithinTargetStartAndEnd(constructor) { + // works with three arguments + assertArrayEquals(new constructor([1, 2, 3, 4, 5]).copyWithin(0, 3, 4), + [4, 2, 3, 4, 5]); + assertArrayEquals(new constructor([1, 2, 3, 4, 5]).copyWithin(1, 3, 4), + [1, 4, 3, 4, 5]); + assertArrayEquals(new constructor([1, 2, 3, 4, 5]).copyWithin(1, 2, 4), + [1, 3, 4, 4, 5]); +}); + + +CheckEachTypedArray(function copyWithinNegativeRelativeOffsets(constructor) { + // works with negative arguments + assertArrayEquals([4, 5, 3, 4, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(0, -2)); + assertArrayEquals([4, 2, 3, 4, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(0, -2, -1)); + assertArrayEquals([1, 3, 3, 4, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(-4, -3, -2)); + assertArrayEquals([1, 3, 4, 4, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(-4, -3, -1)); + assertArrayEquals([1, 3, 4, 5, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(-4, -3)); + // test with arguments equal to -this.length + assertArrayEquals([1, 2, 3, 4, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(-5, 0)); +}); + + +CheckEachTypedArray(function mustBeTypedArray(constructor) { + // throws on non-TypedArray values + assertThrows(function() { + return constructor.prototype.copyWithin.call(null, 0, 3); + }, TypeError); + assertThrows(function() { + return constructor.prototype.copyWithin.call(undefined, 0, 3); + }, TypeError); + assertThrows(function() { + return constructor.prototype.copyWithin.call(34, 0, 3); + }, TypeError); + assertThrows(function() { + return constructor.prototype.copyWithin.call([1, 2, 3, 4, 5], 0, 3); + }, TypeError); +}); + + +CheckEachTypedArray(function copyWithinStartLessThanTarget(constructor) { + // test with target > start on 2 arguments + assertArrayEquals([1, 2, 3, 1, 2], + new constructor([1, 2, 3, 4, 5]).copyWithin(3, 0)); + + // test with target > start on 3 arguments + assertArrayEquals([1, 2, 3, 1, 2], + new constructor([1, 2, 3, 4, 5]).copyWithin(3, 0, 4)); +}); + +CheckEachTypedArray(function copyWithinNonIntegerRelativeOffsets(constructor) { + // test on fractional arguments + assertArrayEquals([4, 5, 3, 4, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(0.2, 3.9)); +}); + + +CheckEachTypedArray(function copyWithinNegativeZeroTarget(constructor) { + // test with -0 + assertArrayEquals([4, 5, 3, 4, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(-0, 3)); +}); + + +CheckEachTypedArray(function copyWithinTargetOutsideStart(constructor) { + // test with arguments more than this.length + assertArrayEquals([1, 2, 3, 4, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(0, 7)); + + // test with arguments less than -this.length + assertArrayEquals([1, 2, 3, 4, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(-7, 0)); +}); + + +CheckEachTypedArray(function copyWithinEmptyArray(constructor) { + // test on empty array + assertArrayEquals([], new constructor([]).copyWithin(0, 3)); +}); + + +CheckEachTypedArray(function copyWithinTargetCutOff(constructor) { + // test with target range being shorter than end - start + assertArrayEquals([1, 2, 2, 3, 4], [1, 2, 3, 4, 5].copyWithin(2, 1, 4)); +}); + + +CheckEachTypedArray(function copyWithinOverlappingRanges(constructor) { + // test overlapping ranges + var arr = [1, 2, 3, 4, 5]; + arr.copyWithin(2, 1, 4); + assertArrayEquals([1, 2, 2, 2, 3], arr.copyWithin(2, 1, 4)); +}); + + +CheckEachTypedArray(function copyWithinDefaultEnd(constructor) { + // undefined as third argument + assertArrayEquals([4, 5, 3, 4, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(0, 3, undefined)); +}); + + +CheckEachTypedArray(function copyWithinLargeArray(constructor) { + var large = 10000; + + // test on a large array + var arr = new constructor(large); + assertArrayEquals(arr, arr.copyWithin(45, 9000)); + + var expected = new Array(large); + // test on numbers + for (var i = 0; i < large; i++) { + arr[i] = Math.random() * 100; // May be cast to an int + expected[i] = arr[i]; + if (i >= 9000) { + expected[(i - 9000) + 45] = arr[i]; + } + } + assertArrayEquals(expected, arr.copyWithin(45, 9000)); + + // test array length remains same + assertEquals(large, arr.length); +}); + + +CheckEachTypedArray(function copyWithinNullEnd(constructor) { + // test null on third argument is converted to +0 + assertArrayEquals([1, 2, 3, 4, 5], + new constructor([1, 2, 3, 4, 5]).copyWithin(0, 3, null)); +}); diff --git a/deps/v8/test/mjsunit/harmony/typedarrays-every.js b/deps/v8/test/mjsunit/es6/typedarray-every.js index 3f95ba9d4c..22132f32b1 100644 --- a/deps/v8/test/mjsunit/harmony/typedarrays-every.js +++ b/deps/v8/test/mjsunit/es6/typedarray-every.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-arrays --allow-natives-syntax +// Flags: --allow-natives-syntax var typedArrayConstructors = [ Uint8Array, @@ -85,8 +85,9 @@ function TestTypedArrayForEach(constructor) { // still make .forEach() finish, and the array should keep being // empty after neutering it. count = 0; - a = new constructor(2); + a = new constructor(3); result = a.every(function (n, index, array) { + assertFalse(array[index] === undefined); // don't get here if neutered if (count > 0) %ArrayBufferNeuter(array.buffer); array[index] = n + 1; count++; @@ -134,6 +135,16 @@ function TestTypedArrayForEach(constructor) { constructor.prototype.every.call(a, function (x) { count++; return true; }); assertEquals(a.length, count); } + + // Shadowing length doesn't affect every, unlike Array.prototype.every + a = new constructor([1, 2]); + Object.defineProperty(a, 'length', {value: 1}); + var x = 0; + assertEquals(a.every(function(elt) { x += elt; return true; }), true); + assertEquals(x, 3); + assertEquals(Array.prototype.every.call(a, + function(elt) { x += elt; return true; }), true); + assertEquals(x, 4); } for (i = 0; i < typedArrayConstructors.length; i++) { diff --git a/deps/v8/test/mjsunit/es6/typedarray-fill.js b/deps/v8/test/mjsunit/es6/typedarray-fill.js new file mode 100644 index 0000000000..2c612016f6 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/typedarray-fill.js @@ -0,0 +1,45 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var typedArrayConstructors = [ + Uint8Array, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, + Uint8ClampedArray, + Float32Array, + Float64Array]; + +for (var constructor of typedArrayConstructors) { + assertEquals(1, constructor.prototype.fill.length); + + assertArrayEquals(new constructor([]).fill(8), []); + assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8), [8, 8, 8, 8, 8]); + assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, 1), [0, 8, 8, 8, 8]); + assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, 10), [0, 0, 0, 0, 0]); + assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, -5), [8, 8, 8, 8, 8]); + assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, 1, 4), [0, 8, 8, 8, 0]); + assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, 1, -1), [0, 8, 8, 8, 0]); + assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, 1, 42), [0, 8, 8, 8, 8]); + assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, -3, 42), [0, 0, 8, 8, 8]); + assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, -3, 4), [0, 0, 8, 8, 0]); + assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, -2, -1), [0, 0, 0, 8, 0]); + assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, -1, -3), [0, 0, 0, 0, 0]); + assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, 0, 4), [8, 8, 8, 8, 0]); + + // Test exceptions + assertThrows('constructor.prototype.fill.call(null)', TypeError); + assertThrows('constructor.prototype.fill.call(undefined)', TypeError); + assertThrows('constructor.prototype.fill.call([])', TypeError); + + // Shadowing length doesn't affect fill, unlike Array.prototype.fill + var a = new constructor([2, 2]); + Object.defineProperty(a, 'length', {value: 1}); + a.fill(3); + assertArrayEquals([a[0], a[1]], [3, 3]); + Array.prototype.fill.call(a, 4); + assertArrayEquals([a[0], a[1]], [4, 3]); +} diff --git a/deps/v8/test/mjsunit/es6/typedarray-find.js b/deps/v8/test/mjsunit/es6/typedarray-find.js new file mode 100644 index 0000000000..69ceedc8b5 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/typedarray-find.js @@ -0,0 +1,187 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var typedArrayConstructors = [ + Uint8Array, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, + Uint8ClampedArray, + Float32Array, + Float64Array]; + +for (var constructor of typedArrayConstructors) { + +assertEquals(1, constructor.prototype.find.length); + +var a = new constructor([21, 22, 23, 24]); +assertEquals(undefined, a.find(function() { return false; })); +assertEquals(21, a.find(function() { return true; })); +assertEquals(undefined, a.find(function(val) { return 121 === val; })); +assertEquals(24, a.find(function(val) { return 24 === val; })); +assertEquals(23, a.find(function(val) { return 23 === val; }), null); +assertEquals(22, a.find(function(val) { return 22 === val; }), undefined); + + +// +// Test predicate is not called when array is empty +// +(function() { + var a = new constructor([]); + var l = -1; + var o = -1; + var v = -1; + var k = -1; + + a.find(function(val, key, obj) { + o = obj; + l = obj.length; + v = val; + k = key; + + return false; + }); + + assertEquals(-1, l); + assertEquals(-1, o); + assertEquals(-1, v); + assertEquals(-1, k); +})(); + + +// +// Test predicate is called with correct arguments +// +(function() { + var a = new constructor([5]); + var l = -1; + var o = -1; + var v = -1; + var k = -1; + + var found = a.find(function(val, key, obj) { + o = obj; + l = obj.length; + v = val; + k = key; + + return false; + }); + + assertArrayEquals(a, o); + assertEquals(a.length, l); + assertEquals(5, v); + assertEquals(0, k); + assertEquals(undefined, found); +})(); + + +// +// Test predicate is called array.length times +// +(function() { + var a = new constructor([1, 2, 3, 4, 5]); + var l = 0; + var found = a.find(function() { + l++; + return false; + }); + + assertEquals(a.length, l); + assertEquals(undefined, found); +})(); + + +// +// Test array modifications +// +(function() { + a = new constructor([1, 2, 3]); + found = a.find(function(val, key) { a[key] = ++val; return false; }); + assertArrayEquals([2, 3, 4], a); + assertEquals(3, a.length); + assertEquals(undefined, found); +})(); + +// +// Test thisArg +// +(function() { + // Test String as a thisArg + var found = new constructor([1, 2, 3]).find(function(val, key) { + return this.charAt(Number(key)) === String(val); + }, "321"); + assertEquals(2, found); + + // Test object as a thisArg + var thisArg = { + elementAt: function(key) { + return this[key]; + } + }; + Array.prototype.push.apply(thisArg, [3, 2, 1]); + + found = new constructor([1, 2, 3]).find(function(val, key) { + return this.elementAt(key) === val; + }, thisArg); + assertEquals(2, found); + + // Create a new object in each function call when receiver is a + // primitive value. See ECMA-262, Annex C. + a = []; + new constructor([1, 2]).find(function() { a.push(this) }, ""); + assertTrue(a[0] !== a[1]); + + // Do not create a new object otherwise. + a = []; + new constructor([1, 2]).find(function() { a.push(this) }, {}); + assertEquals(a[0], a[1]); + + // In strict mode primitive values should not be coerced to an object. + a = []; + new constructor([1, 2]).find(function() { 'use strict'; a.push(this); }, ""); + assertEquals("", a[0]); + assertEquals(a[0], a[1]); + +})(); + +// Test exceptions +assertThrows('constructor.prototype.find.call(null, function() { })', + TypeError); +assertThrows('constructor.prototype.find.call(undefined, function() { })', + TypeError); +assertThrows('constructor.prototype.find.apply(null, function() { }, [])', + TypeError); +assertThrows('constructor.prototype.find.apply(undefined, function() { }, [])', + TypeError); +assertThrows('constructor.prototype.find.apply([], function() { }, [])', + TypeError); +assertThrows('constructor.prototype.find.apply({}, function() { }, [])', + TypeError); +assertThrows('constructor.prototype.find.apply("", function() { }, [])', + TypeError); + +assertThrows('new constructor([]).find(null)', TypeError); +assertThrows('new constructor([]).find(undefined)', TypeError); +assertThrows('new constructor([]).find(0)', TypeError); +assertThrows('new constructor([]).find(true)', TypeError); +assertThrows('new constructor([]).find(false)', TypeError); +assertThrows('new constructor([]).find("")', TypeError); +assertThrows('new constructor([]).find({})', TypeError); +assertThrows('new constructor([]).find([])', TypeError); +assertThrows('new constructor([]).find(/\d+/)', TypeError); + +// Shadowing length doesn't affect find, unlike Array.prototype.find +a = new constructor([1, 2]); +Object.defineProperty(a, 'length', {value: 1}); +var x = 0; +assertEquals(a.find(function(elt) { x += elt; return false; }), undefined); +assertEquals(x, 3); +assertEquals(Array.prototype.find.call(a, + function(elt) { x += elt; return false; }), undefined); +assertEquals(x, 4); + +} diff --git a/deps/v8/test/mjsunit/es6/typedarray-findindex.js b/deps/v8/test/mjsunit/es6/typedarray-findindex.js new file mode 100644 index 0000000000..51c439203d --- /dev/null +++ b/deps/v8/test/mjsunit/es6/typedarray-findindex.js @@ -0,0 +1,187 @@ +// 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. + +var typedArrayConstructors = [ + Uint8Array, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, + Uint8ClampedArray, + Float32Array, + Float64Array]; + +for (var constructor of typedArrayConstructors) { + +assertEquals(1, constructor.prototype.findIndex.length); + +var a = new constructor([21, 22, 23, 24]); +assertEquals(-1, a.findIndex(function() { return false; })); +assertEquals(-1, a.findIndex(function(val) { return 121 === val; })); +assertEquals(0, a.findIndex(function() { return true; })); +assertEquals(1, a.findIndex(function(val) { return 22 === val; }), undefined); +assertEquals(2, a.findIndex(function(val) { return 23 === val; }), null); +assertEquals(3, a.findIndex(function(val) { return 24 === val; })); + + +// +// Test predicate is not called when array is empty +// +(function() { + var a = new constructor([]); + var l = -1; + var o = -1; + var v = -1; + var k = -1; + + a.findIndex(function(val, key, obj) { + o = obj; + l = obj.length; + v = val; + k = key; + + return false; + }); + + assertEquals(-1, l); + assertEquals(-1, o); + assertEquals(-1, v); + assertEquals(-1, k); +})(); + + +// +// Test predicate is called with correct argumetns +// +(function() { + var a = new constructor([5]); + var l = -1; + var o = -1; + var v = -1; + var k = -1; + + var index = a.findIndex(function(val, key, obj) { + o = obj; + l = obj.length; + v = val; + k = key; + + return false; + }); + + assertArrayEquals(a, o); + assertEquals(a.length, l); + assertEquals(5, v); + assertEquals(0, k); + assertEquals(-1, index); +})(); + + +// +// Test predicate is called array.length times +// +(function() { + var a = new constructor([1, 2, 3, 4, 5]); + var l = 0; + + a.findIndex(function() { + l++; + return false; + }); + + assertEquals(a.length, l); +})(); + + +// +// Test array modifications +// +(function() { + a = new constructor([1, 2, 3]); + a.findIndex(function(val, key) { a[key] = ++val; return false; }); + assertArrayEquals([2, 3, 4], a); + assertEquals(3, a.length); +})(); + + +// +// Test thisArg +// +(function() { + // Test String as a thisArg + var index = new constructor([1, 2, 3]).findIndex(function(val, key) { + return this.charAt(Number(key)) === String(val); + }, "321"); + assertEquals(1, index); + + // Test object as a thisArg + var thisArg = { + elementAt: function(key) { + return this[key]; + } + }; + Array.prototype.push.apply(thisArg, [3, 2, 1]); + + index = new constructor([1, 2, 3]).findIndex(function(val, key) { + return this.elementAt(key) === val; + }, thisArg); + assertEquals(1, index); + + // Create a new object in each function call when receiver is a + // primitive value. See ECMA-262, Annex C. + a = []; + new constructor([1, 2]).findIndex(function() { a.push(this) }, ""); + assertTrue(a[0] !== a[1]); + + // Do not create a new object otherwise. + a = []; + new constructor([1, 2]).findIndex(function() { a.push(this) }, {}); + assertEquals(a[0], a[1]); + + // In strict mode primitive values should not be coerced to an object. + a = []; + new constructor([1, 2]).findIndex(function() { 'use strict'; a.push(this); }, ""); + assertEquals("", a[0]); + assertEquals(a[0], a[1]); + +})(); + +// Test exceptions +assertThrows('constructor.prototype.findIndex.call(null, function() { })', + TypeError); +assertThrows('constructor.prototype.findIndex.call(undefined, function() { })', + TypeError); +assertThrows('constructor.prototype.findIndex.apply(null, function() { }, [])', + TypeError); +assertThrows('constructor.prototype.findIndex.apply(undefined, function() { }, [])', + TypeError); +assertThrows('constructor.prototype.findIndex.apply([], function() { }, [])', + TypeError); +assertThrows('constructor.prototype.findIndex.apply({}, function() { }, [])', + TypeError); +assertThrows('constructor.prototype.findIndex.apply("", function() { }, [])', + TypeError); + +assertThrows('new constructor([]).findIndex(null)', TypeError); +assertThrows('new constructor([]).findIndex(undefined)', TypeError); +assertThrows('new constructor([]).findIndex(0)', TypeError); +assertThrows('new constructor([]).findIndex(true)', TypeError); +assertThrows('new constructor([]).findIndex(false)', TypeError); +assertThrows('new constructor([]).findIndex("")', TypeError); +assertThrows('new constructor([]).findIndex({})', TypeError); +assertThrows('new constructor([]).findIndex([])', TypeError); +assertThrows('new constructor([]).findIndex(/\d+/)', TypeError); + +// Shadowing length doesn't affect findIndex, unlike Array.prototype.findIndex +a = new constructor([1, 2]); +Object.defineProperty(a, 'length', {value: 1}); +var x = 0; +assertEquals(a.findIndex(function(elt) { x += elt; return false; }), -1); +assertEquals(x, 3); +assertEquals(Array.prototype.findIndex.call(a, + function(elt) { x += elt; return false; }), -1); +assertEquals(x, 4); + +} diff --git a/deps/v8/test/mjsunit/harmony/typedarrays-foreach.js b/deps/v8/test/mjsunit/es6/typedarray-foreach.js index 4bfa655449..b9789805f6 100644 --- a/deps/v8/test/mjsunit/harmony/typedarrays-foreach.js +++ b/deps/v8/test/mjsunit/es6/typedarray-foreach.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-arrays --allow-natives-syntax +// Flags: --allow-natives-syntax var typedArrayConstructors = [ Uint8Array, @@ -85,8 +85,13 @@ function TestTypedArrayForEach(constructor) { assertEquals(42, a[1]); // Neutering the buffer backing the typed array mid-way should - // still make .forEach() finish, and the array should keep being - // empty after neutering it. + // still make .forEach() finish, but exiting early due to the missing + // elements, and the array should keep being empty after detaching it. + // TODO(dehrenberg): According to the ES6 spec, accessing or testing + // for members on a detached TypedArray should throw, so really this + // should throw in the third iteration. However, this behavior matches + // the Khronos spec. + a = new constructor(3); count = 0; a.forEach(function (n, index, array) { if (count > 0) %ArrayBufferNeuter(array.buffer); @@ -133,6 +138,16 @@ function TestTypedArrayForEach(constructor) { constructor.prototype.forEach.call(a, function (x) { count++ }); assertEquals(a.length, count); } + + // Shadowing length doesn't affect forEach, unlike Array.prototype.forEach + a = new constructor([1, 2]); + Object.defineProperty(a, 'length', {value: 1}); + var x = 0; + assertEquals(a.forEach(function(elt) { x += elt; }), undefined); + assertEquals(x, 3); + assertEquals(Array.prototype.forEach.call(a, + function(elt) { x += elt; }), undefined); + assertEquals(x, 4); } for (i = 0; i < typedArrayConstructors.length; i++) { diff --git a/deps/v8/test/mjsunit/es6/typedarray-from.js b/deps/v8/test/mjsunit/es6/typedarray-from.js new file mode 100644 index 0000000000..709c453379 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/typedarray-from.js @@ -0,0 +1,121 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var typedArrayConstructors = [ + Uint8Array, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, + Uint8ClampedArray, + Float32Array, + Float64Array +]; + +for (var constructor of typedArrayConstructors) { + assertEquals(1, constructor.from.length); + + // TypedArray.from only callable on this subclassing %TypedArray% + assertThrows(function () {constructor.from.call(Array, [])}, TypeError); + + function assertArrayLikeEquals(value, expected, type) { + assertEquals(value.__proto__, type.prototype); + assertEquals(expected.length, value.length); + for (var i = 0; i < value.length; ++i) { + assertEquals(expected[i], value[i]); + } + } + + // Assert that calling mapfn with / without thisArg in sloppy and strict modes + // works as expected. + var global = this; + function non_strict() { assertEquals(global, this); } + function strict() { 'use strict'; assertEquals(undefined, this); } + function strict_null() { 'use strict'; assertEquals(null, this); } + constructor.from([1], non_strict); + constructor.from([1], non_strict, void 0); + constructor.from([1], non_strict, null); + constructor.from([1], strict); + constructor.from([1], strict, void 0); + constructor.from([1], strict_null, null); + + // TypedArray.from can only be called on TypedArray constructors + assertThrows(function() {constructor.from.call({}, [])}, TypeError); + assertThrows(function() {constructor.from.call([], [])}, TypeError); + assertThrows(function() {constructor.from.call(1, [])}, TypeError); + assertThrows(function() {constructor.from.call(undefined, [])}, TypeError); + + // Converting from various other types, demonstrating that it can + // operate on array-like objects as well as iterables. + // TODO(littledan): constructors should have similar flexibility. + assertArrayLikeEquals(constructor.from( + { length: 1, 0: 5 }), [5], constructor); + + assertArrayLikeEquals(constructor.from( + { length: -1, 0: 5 }), [], constructor); + + assertArrayLikeEquals(constructor.from( + [1, 2, 3]), [1, 2, 3], constructor); + + var set = new Set([1, 2, 3]); + assertArrayLikeEquals(constructor.from(set), [1, 2, 3], + constructor); + + function* generator() { + yield 4; + yield 5; + yield 6; + } + + assertArrayLikeEquals(constructor.from(generator()), + [4, 5, 6], constructor); + + assertThrows(function() { constructor.from(null); }, TypeError); + assertThrows(function() { constructor.from(undefined); }, TypeError); + assertThrows(function() { constructor.from([], null); }, TypeError); + assertThrows(function() { constructor.from([], 'noncallable'); }, + TypeError); + + var nullIterator = {}; + nullIterator[Symbol.iterator] = null; + assertArrayLikeEquals(constructor.from(nullIterator), [], + constructor); + + var nonObjIterator = {}; + nonObjIterator[Symbol.iterator] = function() { return 'nonObject'; }; + assertThrows(function() { constructor.from(nonObjIterator); }, + TypeError); + + assertThrows(function() { constructor.from([], null); }, TypeError); + + // Ensure iterator is only accessed once, and only invoked once + var called = 0; + var arr = [1, 2, 3]; + var obj = {}; + var counter = 0; + + // Test order --- only get iterator method once + function testIterator() { + called++; + assertEquals(obj, this); + return arr[Symbol.iterator](); + } + var getCalled = 0; + Object.defineProperty(obj, Symbol.iterator, { + get: function() { + getCalled++; + return testIterator; + }, + set: function() { + assertUnreachable('@@iterator should not be set'); + } + }); + assertArrayLikeEquals(constructor.from(obj), [1, 2, 3], constructor); + assertEquals(getCalled, 1); + assertEquals(called, 1); + + assertEquals(constructor, Uint8Array.from.call(constructor, [1]).constructor); + assertEquals(Uint8Array, constructor.from.call(Uint8Array, [1]).constructor); +} diff --git a/deps/v8/test/mjsunit/es6/typedarray-indexing.js b/deps/v8/test/mjsunit/es6/typedarray-indexing.js new file mode 100644 index 0000000000..44472e3eb3 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/typedarray-indexing.js @@ -0,0 +1,71 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var typedArrayConstructors = [ + Uint8Array, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, + Uint8ClampedArray, + Float32Array, + Float64Array +]; + +for (var constructor of typedArrayConstructors) { + var array = new constructor([1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]); + + // ---------------------------------------------------------------------- + // %TypedArray%.prototype.indexOf. + // ---------------------------------------------------------------------- + + // Negative cases. + assertEquals(-1, new constructor([]).indexOf(1)); + assertEquals(-1, array.indexOf(4)); + assertEquals(-1, array.indexOf(3, array.length)); + + assertEquals(2, array.indexOf(3)); + // Negative index out of range. + assertEquals(0, array.indexOf(1, -17)); + // Negative index in rage. + assertEquals(3, array.indexOf(1, -11)); + // Index in range. + assertEquals(3, array.indexOf(1, 1)); + assertEquals(3, array.indexOf(1, 3)); + assertEquals(6, array.indexOf(1, 4)); + + // Basic TypedArray function properties + assertEquals(1, array.indexOf.length); + assertThrows(function(){ array.indexOf.call([1], 1); }, TypeError); + Object.defineProperty(array, 'length', {value: 1}); + assertEquals(array.indexOf(2), 1); + + + // ---------------------------------------------------------------------- + // %TypedArray%.prototype.lastIndexOf. + // ---------------------------------------------------------------------- + array = new constructor([1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]); + + // Negative cases. + assertEquals(-1, new constructor([]).lastIndexOf(1)); + assertEquals(-1, array.lastIndexOf(1, -17)); + + assertEquals(9, array.lastIndexOf(1)); + // Index out of range. + assertEquals(9, array.lastIndexOf(1, array.length)); + // Index in range. + assertEquals(0, array.lastIndexOf(1, 2)); + assertEquals(3, array.lastIndexOf(1, 4)); + assertEquals(3, array.lastIndexOf(1, 3)); + // Negative index in range. + assertEquals(0, array.lastIndexOf(1, -11)); + + // Basic TypedArray function properties + assertEquals(1, array.lastIndexOf.length); + assertThrows(function(){ array.lastIndexOf.call([1], 1); }, TypeError); + Object.defineProperty(array, 'length', {value: 1}); + assertEquals(array.lastIndexOf(2), 10); + delete array.length; +} diff --git a/deps/v8/test/mjsunit/es6/typedarray-iteration.js b/deps/v8/test/mjsunit/es6/typedarray-iteration.js new file mode 100644 index 0000000000..9560cbc5df --- /dev/null +++ b/deps/v8/test/mjsunit/es6/typedarray-iteration.js @@ -0,0 +1,194 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Tests for standard TypedArray array iteration functions. + +var typedArrayConstructors = [ + Uint8Array, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, + Uint8ClampedArray, + Float32Array, + Float64Array +]; + +function assertArrayLikeEquals(expected, value, type) { + assertEquals(value.__proto__, type.prototype); + assertEquals(expected.length, value.length); + for (var i = 0; i < value.length; ++i) { + assertEquals(expected[i], value[i]); + } +} + +for (var constructor of typedArrayConstructors) { + (function TypedArrayFilterTest() { + // Simple use. + var a = new constructor([0, 1]); + assertArrayLikeEquals([0], a.filter(function(n) { return n == 0; }), + constructor); + assertArrayLikeEquals([0, 1], a, constructor); + + // Use specified object as this object when calling the function. + var o = { value: 42 } + a = new constructor([1, 42, 3, 42, 4]); + assertArrayLikeEquals([42, 42], a.filter(function(n) { + return this.value == n + }, o), constructor); + + // Modify original array. + a = new constructor([1, 42, 3, 42, 4]); + assertArrayLikeEquals([42, 42], a.filter(function(n, index, array) { + array[index] = 43; return 42 == n; + }), constructor); + assertArrayLikeEquals([43, 43, 43, 43, 43], a, constructor); + + // Create a new object in each function call when receiver is a + // primitive value. See ECMA-262, Annex C. + a = []; + new constructor([1, 2]).filter(function() { a.push(this) }, ''); + assertTrue(a[0] !== a[1]); + + // Do not create a new object otherwise. + a = []; + new constructor([1, 2]).filter(function() { a.push(this) }, {}); + assertEquals(a[0], a[1]); + + // In strict mode primitive values should not be coerced to an object. + a = []; + new constructor([1, 2]).filter(function() { + 'use strict'; + a.push(this); + }, ''); + assertEquals('', a[0]); + assertEquals(a[0], a[1]); + + // Calling this method on other types is a TypeError + assertThrows(function() { + constructor.prototype.filter.call([], function() {}); + }, TypeError); + + // Shadowing the length property doesn't change anything + a = new constructor([1, 2]); + Object.defineProperty(a, 'length', { value: 1 }); + assertArrayLikeEquals([2], a.filter(function(elt) { + return elt == 2; + }), constructor); + })(); + + (function TypedArrayMapTest() { + var a = new constructor([0, 1, 2, 3, 4]); + + // Simple use. + var result = [1, 2, 3, 4, 5]; + assertArrayLikeEquals(result, a.map(function(n) { return n + 1; }), + constructor); + assertEquals(a, a); + + // Use specified object as this object when calling the function. + var o = { delta: 42 } + result = [42, 43, 44, 45, 46]; + assertArrayLikeEquals(result, a.map(function(n) { + return this.delta + n; + }, o), constructor); + + // Modify original array. + a = new constructor([0, 1, 2, 3, 4]); + result = [1, 2, 3, 4, 5]; + assertArrayLikeEquals(result, a.map(function(n, index, array) { + array[index] = n + 1; + return n + 1; + }), constructor); + assertArrayLikeEquals(result, a, constructor); + + // Create a new object in each function call when receiver is a + // primitive value. See ECMA-262, Annex C. + a = []; + new constructor([1, 2]).map(function() { a.push(this) }, ''); + assertTrue(a[0] !== a[1]); + + // Do not create a new object otherwise. + a = []; + new constructor([1, 2]).map(function() { a.push(this) }, {}); + assertEquals(a[0], a[1]); + + // In strict mode primitive values should not be coerced to an object. + a = []; + new constructor([1, 2]).map(function() { 'use strict'; a.push(this); }, ''); + assertEquals('', a[0]); + assertEquals(a[0], a[1]); + + // Test that the result is converted to the right type + assertArrayLikeEquals([3, 3], new constructor([1, 2]).map(function() { + return "3"; + }), constructor); + if (constructor !== Float32Array && constructor !== Float64Array) { + assertArrayLikeEquals([0, 0], new constructor([1, 2]).map(function() { + return NaN; + }), constructor); + } + })(); + + // + // %TypedArray%.prototype.some + // + (function TypedArraySomeTest() { + var a = new constructor([0, 1, 2, 3, 4]); + + // Simple use. + assertTrue(a.some(function(n) { return n == 3})); + assertFalse(a.some(function(n) { return n == 5})); + + // Use specified object as this object when calling the function. + var o = { element: 42 }; + a = new constructor([1, 42, 3]); + assertTrue(a.some(function(n) { return this.element == n; }, o)); + a = new constructor([1]); + assertFalse(a.some(function(n) { return this.element == n; }, o)); + + // Modify original array. + a = new constructor([0, 1, 2, 3]); + assertTrue(a.some(function(n, index, array) { + array[index] = n + 1; + return n == 2; + })); + assertArrayLikeEquals([1, 2, 3, 3], a, constructor); + + // Create a new object in each function call when receiver is a + // primitive value. See ECMA-262, Annex C. + a = []; + new constructor([1, 2]).some(function() { a.push(this) }, ''); + assertTrue(a[0] !== a[1]); + + // Do not create a new object otherwise. + a = []; + new constructor([1, 2]).some(function() { a.push(this) }, {}); + assertEquals(a[0], a[1]); + + // In strict mode primitive values should not be coerced to an object. + a = []; + new constructor([1, 2]).some(function() { + 'use strict'; + a.push(this); + }, ''); + assertEquals('', a[0]); + assertEquals(a[0], a[1]); + + // Calling this method on other types is a TypeError + assertThrows(function() { + constructor.prototype.some.call([], function() {}); + }, TypeError); + + // Shadowing the length property doesn't change anything + a = new constructor([1, 2]); + Object.defineProperty(a, 'length', { value: 1 }); + assertEquals(true, a.some(function(elt) { return elt == 2; })); + assertEquals(false, Array.prototype.some.call(a, function(elt) { + return elt == 2; + })); + })(); + +} diff --git a/deps/v8/test/mjsunit/harmony/typedarrays-of.js b/deps/v8/test/mjsunit/es6/typedarray-of.js index 9df1d30c8e..cf57615d12 100644 --- a/deps/v8/test/mjsunit/harmony/typedarrays-of.js +++ b/deps/v8/test/mjsunit/es6/typedarray-of.js @@ -4,8 +4,6 @@ // Based on Mozilla Array.of() tests at http://dxr.mozilla.org/mozilla-central/source/js/src/jit-test/tests/collections -// Flags: --harmony-arrays - var typedArrayConstructors = [ Uint8Array, Int8Array, diff --git a/deps/v8/test/mjsunit/harmony/typedarray-proto.js b/deps/v8/test/mjsunit/es6/typedarray-proto.js index c164a317e5..558cb0ad7a 100644 --- a/deps/v8/test/mjsunit/harmony/typedarray-proto.js +++ b/deps/v8/test/mjsunit/es6/typedarray-proto.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-arrays - // Test that the methods for different TypedArray types have the same // identity. // TODO(dehrenberg): Test that the TypedArray proto hierarchy is set diff --git a/deps/v8/test/mjsunit/es6/typedarray-reduce.js b/deps/v8/test/mjsunit/es6/typedarray-reduce.js new file mode 100644 index 0000000000..1fddeca0bc --- /dev/null +++ b/deps/v8/test/mjsunit/es6/typedarray-reduce.js @@ -0,0 +1,250 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var typedArrayConstructors = [ + Uint8Array, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, + Uint8ClampedArray, + Float32Array, + Float64Array +]; + +function clone(v) { + // Shallow-copies arrays, returns everything else verbatim. + if (v instanceof Array) { + // Shallow-copy an array. + var newArray = new Array(v.length); + for (var i in v) { + newArray[i] = v[i]; + } + return newArray; + } + return v; +} + + +// Creates a callback function for reduce/reduceRight that tests the number +// of arguments and otherwise behaves as "func", but which also +// records all calls in an array on the function (as arrays of arguments +// followed by result). +function makeRecorder(func, testName) { + var record = []; + var f = function recorder(a, b, i, s) { + assertEquals(4, arguments.length, + testName + "(number of arguments: " + arguments.length + ")"); + assertEquals("number", typeof(i), testName + "(index must be number)"); + assertEquals(s[i], b, testName + "(current argument is at index)"); + if (record.length > 0) { + var prevRecord = record[record.length - 1]; + var prevResult = prevRecord[prevRecord.length - 1]; + assertEquals(prevResult, a, + testName + "(prev result -> current input)"); + } + var args = [clone(a), clone(b), i, clone(s)]; + var result = func.apply(this, arguments); + args.push(clone(result)); + record.push(args); + return result; + }; + f.record = record; + return f; +} + + +function testReduce(type, + testName, + expectedResult, + expectedCalls, + array, + combine, + init) { + var rec = makeRecorder(combine); + var result; + var performsCall; + if (arguments.length > 6) { + result = array[type](rec, init); + } else { + result = array[type](rec); + } + var calls = rec.record; + assertEquals(expectedCalls.length, calls.length, + testName + " (number of calls)"); + for (var i = 0; i < expectedCalls.length; i++) { + assertEquals(expectedCalls[i], calls[i], + testName + " (call " + (i + 1) + ")"); + } + assertEquals(expectedResult, result, testName + " (result)"); +} + + +function sum(a, b) { return a + b; } +function prod(a, b) { return a * b; } +function dec(a, b, i, arr) { return a + b * Math.pow(10, arr.length - i - 1); } +function accumulate(acc, elem, i) { acc[i] = elem; return acc; } + +for (var constructor of typedArrayConstructors) { + // ---- Test Reduce[Left] + + var simpleArray = new constructor([2,4,6]) + + testReduce("reduce", "SimpleReduceSum", 12, + [[0, 2, 0, simpleArray, 2], + [2, 4, 1, simpleArray, 6], + [6, 6, 2, simpleArray, 12]], + simpleArray, sum, 0); + + testReduce("reduce", "SimpleReduceProd", 48, + [[1, 2, 0, simpleArray, 2], + [2, 4, 1, simpleArray, 8], + [8, 6, 2, simpleArray, 48]], + simpleArray, prod, 1); + + testReduce("reduce", "SimpleReduceDec", 246, + [[0, 2, 0, simpleArray, 200], + [200, 4, 1, simpleArray, 240], + [240, 6, 2, simpleArray, 246]], + simpleArray, dec, 0); + + testReduce("reduce", "SimpleReduceAccumulate", [2, 4, 6], + [[[], 2, 0, simpleArray, [2]], + [[2], 4, 1, simpleArray, [2, 4]], + [[2,4], 6, 2, simpleArray, [2, 4, 6]]], + simpleArray, accumulate, []); + + + testReduce("reduce", "EmptyReduceSum", 0, [], new constructor([]), sum, 0); + testReduce("reduce", "EmptyReduceProd", 1, [], new constructor([]), prod, 1); + testReduce("reduce", "EmptyReduceDec", 0, [], new constructor([]), dec, 0); + testReduce("reduce", "EmptyReduceAccumulate", [], [], new constructor([]), accumulate, []); + + testReduce("reduce", "EmptyReduceSumNoInit", 0, [], new constructor([0]), sum); + testReduce("reduce", "EmptyReduceProdNoInit", 1, [], new constructor([1]), prod); + testReduce("reduce", "EmptyReduceDecNoInit", 0, [], new constructor([0]), dec); + + // ---- Test ReduceRight + + testReduce("reduceRight", "SimpleReduceRightSum", 12, + [[0, 6, 2, simpleArray, 6], + [6, 4, 1, simpleArray, 10], + [10, 2, 0, simpleArray, 12]], + simpleArray, sum, 0); + + testReduce("reduceRight", "SimpleReduceRightProd", 48, + [[1, 6, 2, simpleArray, 6], + [6, 4, 1, simpleArray, 24], + [24, 2, 0, simpleArray, 48]], + simpleArray, prod, 1); + + testReduce("reduceRight", "SimpleReduceRightDec", 246, + [[0, 6, 2, simpleArray, 6], + [6, 4, 1, simpleArray, 46], + [46, 2, 0, simpleArray, 246]], + simpleArray, dec, 0); + + + testReduce("reduceRight", "EmptyReduceRightSum", 0, [], new constructor([]), sum, 0); + testReduce("reduceRight", "EmptyReduceRightProd", 1, [], new constructor([]), prod, 1); + testReduce("reduceRight", "EmptyReduceRightDec", 0, [], new constructor([]), dec, 0); + testReduce("reduceRight", "EmptyReduceRightAccumulate", [], + [], new constructor([]), accumulate, []); + + testReduce("reduceRight", "EmptyReduceRightSumNoInit", 0, [], new constructor([0]), sum); + testReduce("reduceRight", "EmptyReduceRightProdNoInit", 1, [], new constructor([1]), prod); + testReduce("reduceRight", "EmptyReduceRightDecNoInit", 0, [], new constructor([0]), dec); + + // Ignore non-array properties: + + var arrayPlus = new constructor([1,2,3]); + arrayPlus[-1] = NaN; + arrayPlus["00"] = NaN; + arrayPlus["02"] = NaN; + arrayPlus["-0"] = NaN; + arrayPlus.x = NaN; + + testReduce("reduce", "ArrayWithNonElementPropertiesReduce", 6, + [[0, 1, 0, arrayPlus, 1], + [1, 2, 1, arrayPlus, 3], + [3, 3, 2, arrayPlus, 6], + ], arrayPlus, sum, 0); + + testReduce("reduceRight", "ArrayWithNonElementPropertiesReduceRight", 6, + [[0, 3, 2, arrayPlus, 3], + [3, 2, 1, arrayPlus, 5], + [5, 1, 0, arrayPlus, 6], + ], arrayPlus, sum, 0); + + + // Test error conditions: + + var exception = false; + try { + new constructor([1]).reduce("not a function"); + } catch (e) { + exception = true; + assertTrue(e instanceof TypeError, + "reduce callback not a function not throwing TypeError"); + assertTrue(e.message.indexOf(" is not a function") >= 0, + "reduce non function TypeError type"); + } + assertTrue(exception); + + exception = false; + try { + new constructor([1]).reduceRight("not a function"); + } catch (e) { + exception = true; + assertTrue(e instanceof TypeError, + "reduceRight callback not a function not throwing TypeError"); + assertTrue(e.message.indexOf(" is not a function") >= 0, + "reduceRight non function TypeError type"); + } + assertTrue(exception); + + exception = false; + try { + new constructor([]).reduce(sum); + } catch (e) { + exception = true; + assertTrue(e instanceof TypeError, + "reduce no initial value not throwing TypeError"); + assertEquals("Reduce of empty array with no initial value", e.message, + "reduce no initial TypeError type"); + } + assertTrue(exception); + + exception = false; + try { + new constructor([]).reduceRight(sum); + } catch (e) { + exception = true; + assertTrue(e instanceof TypeError, + "reduceRight no initial value not throwing TypeError"); + assertEquals("Reduce of empty array with no initial value", e.message, + "reduceRight no initial TypeError type"); + } + assertTrue(exception); + + // Reduce fails when called on non-TypedArrays + assertThrows(function() { + constructor.prototype.reduce.call([], function() {}, null); + }, TypeError); + assertThrows(function() { + constructor.prototype.reduceRight.call([], function() {}, null); + }, TypeError); + + // Shadowing length doesn't affect every, unlike Array.prototype.every + var a = new constructor([1, 2]); + Object.defineProperty(a, 'length', {value: 1}); + assertEquals(a.reduce(sum, 0), 3); + assertEquals(Array.prototype.reduce.call(a, sum, 0), 1); + assertEquals(a.reduceRight(sum, 0), 3); + assertEquals(Array.prototype.reduceRight.call(a, sum, 0), 1); + + assertEquals(1, constructor.prototype.reduce.length); + assertEquals(1, constructor.prototype.reduceRight.length); +} diff --git a/deps/v8/test/mjsunit/es6/typedarray-reverse.js b/deps/v8/test/mjsunit/es6/typedarray-reverse.js new file mode 100644 index 0000000000..f32813e155 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/typedarray-reverse.js @@ -0,0 +1,54 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function ArrayMaker(x) { + return x; +} +ArrayMaker.prototype = Array.prototype; + +var arrayConstructors = [ + Uint8Array, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, + Uint8ClampedArray, + Float32Array, + Float64Array, + ArrayMaker // Also test arrays +]; + +function assertArrayLikeEquals(value, expected, type) { + assertEquals(value.__proto__, type.prototype); + assertEquals(expected.length, value.length); + for (var i = 0; i < value.length; ++i) { + assertEquals(expected[i], value[i]); + } +} + +for (var constructor of arrayConstructors) { + // Test reversing both even and odd length arrays + var a = new constructor([1, 2, 3]); + assertArrayLikeEquals(a.reverse(), [3, 2, 1], constructor); + assertArrayLikeEquals(a, [3, 2, 1], constructor); + + a = new constructor([1, 2, 3, 4]); + assertArrayLikeEquals(a.reverse(), [4, 3, 2, 1], constructor); + assertArrayLikeEquals(a, [4, 3, 2, 1], constructor); + + if (constructor != ArrayMaker) { + // Cannot be called on objects which are not TypedArrays + assertThrows(function () { a.reverse.call({ length: 0 }); }, TypeError); + } else { + // Array.reverse works on array-like objects + var x = { length: 2, 1: 5 }; + a.reverse.call(x); + assertEquals(2, x.length); + assertFalse(Object.hasOwnProperty(x, '1')); + assertEquals(5, x[0]); + } + + assertEquals(0, a.reverse.length); +} diff --git a/deps/v8/test/mjsunit/es6/typedarray-slice.js b/deps/v8/test/mjsunit/es6/typedarray-slice.js new file mode 100644 index 0000000000..ddd021a8fa --- /dev/null +++ b/deps/v8/test/mjsunit/es6/typedarray-slice.js @@ -0,0 +1,71 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var typedArrayConstructors = [ + Uint8Array, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, + Uint8ClampedArray, + Float32Array, + Float64Array +]; + +for (var constructor of typedArrayConstructors) { + // Check various variants of empty array's slicing. + var array = new constructor(0); + for (var i = 0; i < 7; i++) { + assertEquals(0, array.slice(0, 0).length); + assertEquals(0, array.slice(1, 0).length); + assertEquals(0, array.slice(0, 1).length); + assertEquals(0, array.slice(-1, 0).length); + } + + + // Check various forms of arguments omission. + array = new constructor(7); + + for (var i = 0; i < 7; i++) { + assertEquals(array, array.slice()); + assertEquals(array, array.slice(0)); + assertEquals(array, array.slice(undefined)); + assertEquals(array, array.slice("foobar")); + assertEquals(array, array.slice(undefined, undefined)); + } + + + // Check variants of negatives and positive indices. + array = new constructor(7); + + assertEquals(7, array.slice(-100).length); + assertEquals(3, array.slice(-3).length); + assertEquals(3, array.slice(4).length); + assertEquals(1, array.slice(6).length); + assertEquals(0, array.slice(7).length); + assertEquals(0, array.slice(8).length); + assertEquals(0, array.slice(100).length); + + assertEquals(0, array.slice(0, -100).length); + assertEquals(4, array.slice(0, -3).length); + assertEquals(4, array.slice(0, 4).length); + assertEquals(6, array.slice(0, 6).length); + assertEquals(7, array.slice(0, 7).length); + assertEquals(7, array.slice(0, 8).length); + assertEquals(7, array.slice(0, 100).length); + + // Does not permit being called on other types + assertThrows(function () { + constructor.prototype.slice.call([], 0, 0); + }, TypeError); + + // Check that elements are copied properly in slice + array = new constructor([1, 2, 3, 4]); + var slice = array.slice(1, 3); + assertEquals(2, slice.length); + assertEquals(2, slice[0]); + assertEquals(3, slice[1]); + assertTrue(slice instanceof constructor); +} diff --git a/deps/v8/test/mjsunit/es6/typedarray-sort.js b/deps/v8/test/mjsunit/es6/typedarray-sort.js new file mode 100644 index 0000000000..4fb8469075 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/typedarray-sort.js @@ -0,0 +1,55 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var typedArrayConstructors = [ + Uint8Array, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, + Uint8ClampedArray, + Float32Array, + Float64Array +]; + +function assertArrayLikeEquals(value, expected, type) { + assertEquals(value.__proto__, type.prototype); + // Don't test value.length because we mess with that; + // instead in certain callsites we check that length + // is set appropriately. + for (var i = 0; i < expected.length; ++i) { + // Use Object.is to differentiate between +-0 + assertSame(expected[i], value[i]); + } +} + +for (var constructor of typedArrayConstructors) { + // Test default numerical sorting order + var a = new constructor([100, 7, 45]) + assertEquals(a.sort(), a); + assertArrayLikeEquals(a, [7, 45, 100], constructor); + assertEquals(a.length, 3); + + // For arrays of floats, certain handling of +-0/NaN + if (constructor === Float32Array || constructor === Float64Array) { + var b = new constructor([+0, -0, NaN, -0, NaN, +0]) + b.sort(); + assertArrayLikeEquals(b, [-0, -0, +0, +0, NaN, NaN], constructor); + assertEquals(b.length, 6); + } + + // Custom sort--backwards + a.sort(function(x, y) { return y - x; }); + assertArrayLikeEquals(a, [100, 45, 7], constructor); + + // Basic TypedArray method properties: + // Length field is ignored + Object.defineProperty(a, 'length', {value: 1}); + assertEquals(a.sort(), a); + assertArrayLikeEquals(a, [7, 45, 100], constructor); + assertEquals(a.length, 1); + // Method doesn't work on other objects + assertThrows(function() { a.sort.call([]); }, TypeError); +} diff --git a/deps/v8/test/mjsunit/es6/typedarray-tostring.js b/deps/v8/test/mjsunit/es6/typedarray-tostring.js new file mode 100644 index 0000000000..e6adda0405 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/typedarray-tostring.js @@ -0,0 +1,86 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Array's toString should call the object's own join method, if one exists and +// is callable. Otherwise, just use the original Object.toString function. + +var typedArrayConstructors = [ + Uint8Array, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, + Uint8ClampedArray, + Float32Array, + Float64Array +]; + +for (var constructor of typedArrayConstructors) { + var success = "[test success]"; + var expectedThis; + function testJoin() { + assertEquals(0, arguments.length); + assertSame(expectedThis, this); + return success; + } + + + // On an Array object. + + // Default case. + var a1 = new constructor([1, 2, 3]); + assertEquals("1,2,3", a1.toString()); + assertEquals("1,2,3", a1.join()); + assertEquals("1,2,3", a1.toLocaleString()); + + // Non-standard "join" function is called correctly. + var a2 = new constructor([1, 2, 3]); + a2.join = testJoin; + expectedThis = a2; + assertEquals(success, a2.toString()); + assertEquals(success, a2.join()); + assertEquals("1,2,3", a2.toLocaleString()); + + // Non-callable join function is ignored and Object.prototype.toString is + // used instead. + var a3 = new constructor([1, 2, 3]); + a3.join = "not callable"; + assertEquals(0, a3.toString().search(/\[object .+Array\]/)); + + // Non-existing join function is treated same as non-callable. + var a4 = new constructor([1, 2, 3]); + a4.__proto__ = { toString: constructor.prototype.toString }; + // No join on Array. + assertEquals(0, a3.toString().search(/\[object .+Array\]/)); + + + // On a non-Array object, throws. + var o1 = {length: 3, 0: 1, 1: 2, 2: 3, + toString: constructor.prototype.toString, + join: constructor.prototype.join, + toLocaleString: constructor.prototype.toLocaleString}; + assertThrows(function() { o1.join() }, TypeError); + assertThrows(function() { o1.toString() }, TypeError); + assertThrows(function() { o1.toLocaleString() }, TypeError); + // toString is OK if join not from here: + o1.join = Array.prototype.join; + assertEquals("1,2,3", o1.join()); + assertEquals("1,2,3", o1.toString()); + assertThrows(function() { o1.toLocaleString() }, TypeError); + // TODO(littledan): Use the same function for TypedArray as for + // Array, as the spec says (but Firefox doesn't do either). + // Currently, using the same method leads to a bootstrap failure. + // assertEquals(o1.toString, Array.prototype.toString); + + // Redefining length does not change result + var a5 = new constructor([1, 2, 3]) + Object.defineProperty(a5, 'length', { value: 2 }); + assertEquals("1,2,3", a5.join()); + assertEquals("1,2,3", a5.toString()); + assertEquals("1,2,3", a5.toLocaleString()); + assertEquals("1,2", Array.prototype.join.call(a5)); + assertEquals("1,2,3", Array.prototype.toString.call(a5)); + assertEquals("1,2", Array.prototype.toLocaleString.call(a5)); +} diff --git a/deps/v8/test/mjsunit/harmony/typedarrays.js b/deps/v8/test/mjsunit/es6/typedarray.js index 70bd17e338..ef7955ce92 100644 --- a/deps/v8/test/mjsunit/harmony/typedarrays.js +++ b/deps/v8/test/mjsunit/es6/typedarray.js @@ -276,6 +276,43 @@ function TestTypedArray(constr, elementSize, typicalElement) { assertFalse(!!desc.writable); assertFalse(!!desc.set); assertEquals("function", typeof desc.get); + + // Test that the constructor can be called with an iterable + function* gen() { for (var i = 0; i < 10; i++) yield i; } + var genArr = new constr(gen()); + assertEquals(10, genArr.length); + assertEquals(0, genArr[0]); + assertEquals(9, genArr[9]); + // Arrays can be converted to TypedArrays + genArr = new constr([1, 2, 3]); + assertEquals(3, genArr.length); + assertEquals(1, genArr[0]); + assertEquals(3, genArr[2]); + // Redefining Array.prototype[Symbol.iterator] still works + var arrayIterator = Array.prototype[Symbol.iterator]; + Array.prototype[Symbol.iterator] = gen; + genArr = new constr([1, 2, 3]); + assertEquals(10, genArr.length); + assertEquals(0, genArr[0]); + assertEquals(9, genArr[9]); + Array.prototype[Symbol.iterator] = arrayIterator; + // Other array-like things can be made into a TypedArray + var myObject = { 0: 5, 1: 6, length: 2 }; + genArr = new constr(myObject); + assertEquals(2, genArr.length); + assertEquals(5, genArr[0]); + assertEquals(6, genArr[1]); + // Iterator takes precedence over array-like, and the property + // is read only once. + var iteratorReadCount = 0; + Object.defineProperty(myObject, Symbol.iterator, { + get: function() { iteratorReadCount++; return gen; } + }); + genArr = new constr(myObject); + assertEquals(10, genArr.length); + assertEquals(0, genArr[0]); + assertEquals(9, genArr[9]); + assertEquals(1, iteratorReadCount); } TestTypedArray(Uint8Array, 1, 0xFF); diff --git a/deps/v8/test/mjsunit/external-array-no-sse2.js b/deps/v8/test/mjsunit/external-array-no-sse2.js deleted file mode 100644 index 575a8b53cf..0000000000 --- a/deps/v8/test/mjsunit/external-array-no-sse2.js +++ /dev/null @@ -1,715 +0,0 @@ -// Copyright 2012 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Flags: --allow-natives-syntax --noenable-sse2 - -// Helper -function assertInstance(o, f) { - assertSame(o.constructor, f); - assertInstanceof(o, f); -} - -// This is a regression test for overlapping key and value registers. -function f(a) { - a[0] = 0; - a[1] = 0; -} - -var a = new Int32Array(2); -for (var i = 0; i < 5; i++) { - f(a); -} -%OptimizeFunctionOnNextCall(f); -f(a); - -assertEquals(0, a[0]); -assertEquals(0, a[1]); - -// Test derivation from an ArrayBuffer -var ab = new ArrayBuffer(12); -assertInstance(ab, ArrayBuffer); -var derived_uint8 = new Uint8Array(ab); -assertInstance(derived_uint8, Uint8Array); -assertSame(ab, derived_uint8.buffer); -assertEquals(12, derived_uint8.length); -assertEquals(12, derived_uint8.byteLength); -assertEquals(0, derived_uint8.byteOffset); -assertEquals(1, derived_uint8.BYTES_PER_ELEMENT); -var derived_uint8_2 = new Uint8Array(ab,7); -assertInstance(derived_uint8_2, Uint8Array); -assertSame(ab, derived_uint8_2.buffer); -assertEquals(5, derived_uint8_2.length); -assertEquals(5, derived_uint8_2.byteLength); -assertEquals(7, derived_uint8_2.byteOffset); -assertEquals(1, derived_uint8_2.BYTES_PER_ELEMENT); -var derived_int16 = new Int16Array(ab); -assertInstance(derived_int16, Int16Array); -assertSame(ab, derived_int16.buffer); -assertEquals(6, derived_int16.length); -assertEquals(12, derived_int16.byteLength); -assertEquals(0, derived_int16.byteOffset); -assertEquals(2, derived_int16.BYTES_PER_ELEMENT); -var derived_int16_2 = new Int16Array(ab,6); -assertInstance(derived_int16_2, Int16Array); -assertSame(ab, derived_int16_2.buffer); -assertEquals(3, derived_int16_2.length); -assertEquals(6, derived_int16_2.byteLength); -assertEquals(6, derived_int16_2.byteOffset); -assertEquals(2, derived_int16_2.BYTES_PER_ELEMENT); -var derived_uint32 = new Uint32Array(ab); -assertInstance(derived_uint32, Uint32Array); -assertSame(ab, derived_uint32.buffer); -assertEquals(3, derived_uint32.length); -assertEquals(12, derived_uint32.byteLength); -assertEquals(0, derived_uint32.byteOffset); -assertEquals(4, derived_uint32.BYTES_PER_ELEMENT); -var derived_uint32_2 = new Uint32Array(ab,4); -assertInstance(derived_uint32_2, Uint32Array); -assertSame(ab, derived_uint32_2.buffer); -assertEquals(2, derived_uint32_2.length); -assertEquals(8, derived_uint32_2.byteLength); -assertEquals(4, derived_uint32_2.byteOffset); -assertEquals(4, derived_uint32_2.BYTES_PER_ELEMENT); -var derived_uint32_3 = new Uint32Array(ab,4,1); -assertInstance(derived_uint32_3, Uint32Array); -assertSame(ab, derived_uint32_3.buffer); -assertEquals(1, derived_uint32_3.length); -assertEquals(4, derived_uint32_3.byteLength); -assertEquals(4, derived_uint32_3.byteOffset); -assertEquals(4, derived_uint32_3.BYTES_PER_ELEMENT); -var derived_float64 = new Float64Array(ab,0,1); -assertInstance(derived_float64, Float64Array); -assertSame(ab, derived_float64.buffer); -assertEquals(1, derived_float64.length); -assertEquals(8, derived_float64.byteLength); -assertEquals(0, derived_float64.byteOffset); -assertEquals(8, derived_float64.BYTES_PER_ELEMENT); - -// If a given byteOffset and length references an area beyond the end of the -// ArrayBuffer an exception is raised. -function abfunc3() { - new Uint32Array(ab,4,3); -} -assertThrows(abfunc3); -function abfunc4() { - new Uint32Array(ab,16); -} -assertThrows(abfunc4); - -// The given byteOffset must be a multiple of the element size of the specific -// type, otherwise an exception is raised. -function abfunc5() { - new Uint32Array(ab,5); -} -assertThrows(abfunc5); - -// If length is not explicitly specified, the length of the ArrayBuffer minus -// the byteOffset must be a multiple of the element size of the specific type, -// or an exception is raised. -var ab2 = new ArrayBuffer(13); -function abfunc6() { - new Uint32Array(ab2,4); -} -assertThrows(abfunc6); - -// Test that an array constructed without an array buffer creates one properly. -a = new Uint8Array(31); -assertEquals(a.byteLength, a.buffer.byteLength); -assertEquals(a.length, a.buffer.byteLength); -assertEquals(a.length * a.BYTES_PER_ELEMENT, a.buffer.byteLength); -a = new Int16Array(5); -assertEquals(a.byteLength, a.buffer.byteLength); -assertEquals(a.length * a.BYTES_PER_ELEMENT, a.buffer.byteLength); -a = new Float64Array(7); -assertEquals(a.byteLength, a.buffer.byteLength); -assertEquals(a.length * a.BYTES_PER_ELEMENT, a.buffer.byteLength); - -// Test that an implicitly created buffer is a valid buffer. -a = new Float64Array(7); -assertSame(a.buffer, (new Uint16Array(a.buffer)).buffer); -assertSame(a.buffer, (new Float32Array(a.buffer,4)).buffer); -assertSame(a.buffer, (new Int8Array(a.buffer,3,51)).buffer); -assertInstance(a.buffer, ArrayBuffer); - -// Test the correct behavior of the |BYTES_PER_ELEMENT| property. -a = new Int32Array(2); -assertEquals(4, a.BYTES_PER_ELEMENT); -a.BYTES_PER_ELEMENT = 42; -a = new Uint8Array(2); -assertEquals(1, a.BYTES_PER_ELEMENT); -a = new Int16Array(2); -assertEquals(2, a.BYTES_PER_ELEMENT); - -// Test Float64Arrays. -function get(a, index) { - return a[index]; -} -function set(a, index, value) { - a[index] = value; -} -function temp() { -var array = new Float64Array(2); -for (var i = 0; i < 5; i++) { - set(array, 0, 2.5); - assertEquals(2.5, array[0]); -} -%OptimizeFunctionOnNextCall(set); -set(array, 0, 2.5); -assertEquals(2.5, array[0]); -set(array, 1, 3.5); -assertEquals(3.5, array[1]); -for (var i = 0; i < 5; i++) { - assertEquals(2.5, get(array, 0)); - assertEquals(3.5, array[1]); -} -%OptimizeFunctionOnNextCall(get); -assertEquals(2.5, get(array, 0)); -assertEquals(3.5, get(array, 1)); -} - -// Test non-number parameters. -var array_with_length_from_non_number = new Int32Array("2"); -assertEquals(2, array_with_length_from_non_number.length); - -// Test loads and stores. -types = [Array, Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, - Uint32Array, Uint8ClampedArray, Float32Array, Float64Array]; - -test_result_nan = [NaN, 0, 0, 0, 0, 0, 0, 0, NaN, NaN]; -test_result_low_int = [-1, -1, 255, -1, 65535, -1, 0xFFFFFFFF, 0, -1, -1]; -test_result_low_double = [-1.25, -1, 255, -1, 65535, -1, 0xFFFFFFFF, 0, -1.25, -1.25]; -test_result_middle = [253.75, -3, 253, 253, 253, 253, 253, 254, 253.75, 253.75]; -test_result_high_int = [256, 0, 0, 256, 256, 256, 256, 255, 256, 256]; -test_result_high_double = [256.25, 0, 0, 256, 256, 256, 256, 255, 256.25, 256.25]; - -const kElementCount = 40; - -function test_load(array, sum) { - for (var i = 0; i < kElementCount; i++) { - sum += array[i]; - } - return sum; -} - -function test_load_const_key(array, sum) { - sum += array[0]; - sum += array[1]; - sum += array[2]; - return sum; -} - -function test_store(array, sum) { - for (var i = 0; i < kElementCount; i++) { - sum += array[i] = i+1; - } - return sum; -} - -function test_store_const_key(array, sum) { - sum += array[0] = 1; - sum += array[1] = 2; - sum += array[2] = 3; - return sum; -} - -function zero() { - return 0.0; -} - -function test_store_middle_tagged(array, sum) { - array[0] = 253.75; - return array[0]; -} - -function test_store_high_tagged(array, sum) { - array[0] = 256.25; - return array[0]; -} - -function test_store_middle_double(array, sum) { - array[0] = 253.75 + zero(); // + forces double type feedback - return array[0]; -} - -function test_store_high_double(array, sum) { - array[0] = 256.25 + zero(); // + forces double type feedback - return array[0]; -} - -function test_store_high_double(array, sum) { - array[0] = 256.25; - return array[0]; -} - -function test_store_low_int(array, sum) { - array[0] = -1; - return array[0]; -} - -function test_store_low_tagged(array, sum) { - array[0] = -1.25; - return array[0]; -} - -function test_store_low_double(array, sum) { - array[0] = -1.25 + zero(); // + forces double type feedback - return array[0]; -} - -function test_store_high_int(array, sum) { - array[0] = 256; - return array[0]; -} - -function test_store_nan(array, sum) { - array[0] = NaN; - return array[0]; -} - -const kRuns = 10; - -function run_test(test_func, array, expected_result) { - for (var i = 0; i < 5; i++) test_func(array, 0); - %OptimizeFunctionOnNextCall(test_func); - var sum = 0; - for (var i = 0; i < kRuns; i++) { - sum = test_func(array, sum); - } - assertEquals(expected_result, sum); - %DeoptimizeFunction(test_func); - %ClearFunctionTypeFeedback(test_func); -} - -function run_bounds_test(test_func, array, expected_result) { - assertEquals(undefined, a[kElementCount]); - a[kElementCount] = 456; - assertEquals(undefined, a[kElementCount]); - assertEquals(undefined, a[kElementCount+1]); - a[kElementCount+1] = 456; - assertEquals(undefined, a[kElementCount+1]); -} - -for (var t = 0; t < types.length; t++) { - var type = types[t]; - var a = new type(kElementCount); - - for (var i = 0; i < kElementCount; i++) { - a[i] = i; - } - - // Run test functions defined above. - run_test(test_load, a, 780 * kRuns); - run_test(test_load_const_key, a, 3 * kRuns); - run_test(test_store, a, 820 * kRuns); - run_test(test_store_const_key, a, 6 * kRuns); - run_test(test_store_low_int, a, test_result_low_int[t]); - run_test(test_store_low_double, a, test_result_low_double[t]); - run_test(test_store_low_tagged, a, test_result_low_double[t]); - run_test(test_store_high_int, a, test_result_high_int[t]); - run_test(test_store_nan, a, test_result_nan[t]); - run_test(test_store_middle_double, a, test_result_middle[t]); - run_test(test_store_middle_tagged, a, test_result_middle[t]); - run_test(test_store_high_double, a, test_result_high_double[t]); - run_test(test_store_high_tagged, a, test_result_high_double[t]); - - // Test the correct behavior of the |length| property (which is read-only). - if (t != 0) { - assertEquals(kElementCount, a.length); - a.length = 2; - assertEquals(kElementCount, a.length); - assertTrue(delete a.length); - - // Make sure bounds checks are handled correctly for external arrays. - run_bounds_test(a); - run_bounds_test(a); - run_bounds_test(a); - %OptimizeFunctionOnNextCall(run_bounds_test); - run_bounds_test(a); - %DeoptimizeFunction(run_bounds_test); - %ClearFunctionTypeFeedback(run_bounds_test); - } - - function array_load_set_smi_check(a) { - return a[0] = a[0] = 1; - } - - array_load_set_smi_check(a); - array_load_set_smi_check(0); - - function array_load_set_smi_check2(a) { - return a[0] = a[0] = 1; - } - - array_load_set_smi_check2(a); - %OptimizeFunctionOnNextCall(array_load_set_smi_check2); - array_load_set_smi_check2(a); - array_load_set_smi_check2(0); - %DeoptimizeFunction(array_load_set_smi_check2); - %ClearFunctionTypeFeedback(array_load_set_smi_check2); -} - -// Check handling of undefined in 32- and 64-bit external float arrays. - -function store_float32_undefined(ext_array) { - ext_array[0] = undefined; -} - -var float32_array = new Float32Array(1); -// Make sure runtime does it right -store_float32_undefined(float32_array); -assertTrue(isNaN(float32_array[0])); -// Make sure the ICs do it right -store_float32_undefined(float32_array); -assertTrue(isNaN(float32_array[0])); -// Make sure that Cranskshft does it right. -%OptimizeFunctionOnNextCall(store_float32_undefined); -store_float32_undefined(float32_array); -assertTrue(isNaN(float32_array[0])); - -function store_float64_undefined(ext_array) { - ext_array[0] = undefined; -} - -var float64_array = new Float64Array(1); -// Make sure runtime does it right -store_float64_undefined(float64_array); -assertTrue(isNaN(float64_array[0])); -// Make sure the ICs do it right -store_float64_undefined(float64_array); -assertTrue(isNaN(float64_array[0])); -// Make sure that Cranskshft does it right. -%OptimizeFunctionOnNextCall(store_float64_undefined); -store_float64_undefined(float64_array); -assertTrue(isNaN(float64_array[0])); - - -// Check handling of 0-sized buffers and arrays. -ab = new ArrayBuffer(0); -assertInstance(ab, ArrayBuffer); -assertEquals(0, ab.byteLength); -a = new Int8Array(ab); -assertInstance(a, Int8Array); -assertEquals(0, a.byteLength); -assertEquals(0, a.length); -a[0] = 1; -assertEquals(undefined, a[0]); -ab = new ArrayBuffer(16); -assertInstance(ab, ArrayBuffer); -a = new Float32Array(ab,4,0); -assertInstance(a, Float32Array); -assertEquals(0, a.byteLength); -assertEquals(0, a.length); -a[0] = 1; -assertEquals(undefined, a[0]); -a = new Uint16Array(0); -assertInstance(a, Uint16Array); -assertEquals(0, a.byteLength); -assertEquals(0, a.length); -a[0] = 1; -assertEquals(undefined, a[0]); - - -// Check construction from arrays. -a = new Uint32Array([]); -assertInstance(a, Uint32Array); -assertEquals(0, a.length); -assertEquals(0, a.byteLength); -assertEquals(0, a.buffer.byteLength); -assertEquals(4, a.BYTES_PER_ELEMENT); -assertInstance(a.buffer, ArrayBuffer); -a = new Uint16Array([1,2,3]); -assertInstance(a, Uint16Array); -assertEquals(3, a.length); -assertEquals(6, a.byteLength); -assertEquals(6, a.buffer.byteLength); -assertEquals(2, a.BYTES_PER_ELEMENT); -assertEquals(1, a[0]); -assertEquals(3, a[2]); -assertInstance(a.buffer, ArrayBuffer); -a = new Uint32Array(a); -assertInstance(a, Uint32Array); -assertEquals(3, a.length); -assertEquals(12, a.byteLength); -assertEquals(12, a.buffer.byteLength); -assertEquals(4, a.BYTES_PER_ELEMENT); -assertEquals(1, a[0]); -assertEquals(3, a[2]); -assertInstance(a.buffer, ArrayBuffer); - -// Check subarrays. -a = new Uint16Array([1,2,3,4,5,6]); -aa = a.subarray(3); -assertInstance(aa, Uint16Array); -assertEquals(3, aa.length); -assertEquals(6, aa.byteLength); -assertEquals(2, aa.BYTES_PER_ELEMENT); -assertSame(a.buffer, aa.buffer); -aa = a.subarray(3,5); -assertInstance(aa, Uint16Array); -assertEquals(2, aa.length); -assertEquals(4, aa.byteLength); -assertEquals(2, aa.BYTES_PER_ELEMENT); -assertSame(a.buffer, aa.buffer); -aa = a.subarray(4,8); -assertInstance(aa, Uint16Array); -assertEquals(2, aa.length); -assertEquals(4, aa.byteLength); -assertEquals(2, aa.BYTES_PER_ELEMENT); -assertSame(a.buffer, aa.buffer); -aa = a.subarray(9); -assertInstance(aa, Uint16Array); -assertEquals(0, aa.length); -assertEquals(0, aa.byteLength); -assertEquals(2, aa.BYTES_PER_ELEMENT); -assertSame(a.buffer, aa.buffer); -aa = a.subarray(-4); -assertInstance(aa, Uint16Array); -assertEquals(4, aa.length); -assertEquals(8, aa.byteLength); -assertEquals(2, aa.BYTES_PER_ELEMENT); -assertSame(a.buffer, aa.buffer); -aa = a.subarray(-3,-1); -assertInstance(aa, Uint16Array); -assertEquals(2, aa.length); -assertEquals(4, aa.byteLength); -assertEquals(2, aa.BYTES_PER_ELEMENT); -assertSame(a.buffer, aa.buffer); -aa = a.subarray(3,2); -assertInstance(aa, Uint16Array); -assertEquals(0, aa.length); -assertEquals(0, aa.byteLength); -assertEquals(2, aa.BYTES_PER_ELEMENT); -assertSame(a.buffer, aa.buffer); -aa = a.subarray(-3,-4); -assertInstance(aa, Uint16Array); -assertEquals(0, aa.length); -assertEquals(0, aa.byteLength); -assertEquals(2, aa.BYTES_PER_ELEMENT); -assertSame(a.buffer, aa.buffer); -aa = a.subarray(0,-8); -assertInstance(aa, Uint16Array); -assertEquals(0, aa.length); -assertEquals(0, aa.byteLength); -assertEquals(2, aa.BYTES_PER_ELEMENT); -assertSame(a.buffer, aa.buffer); - -assertThrows(function(){ a.subarray.call({}, 0) }); -assertThrows(function(){ a.subarray.call([], 0) }); - -// Try to call constructors directly as functions, and through .call -// and .apply. Should fail. - -assertThrows(function() { ArrayBuffer(100); }, TypeError); -assertThrows(function() { Int8Array(b, 5, 77); }, TypeError); -assertThrows(function() { ArrayBuffer.call(null, 10); }, TypeError); -assertThrows(function() { Uint16Array.call(null, b, 2, 4); }, TypeError); -assertThrows(function() { ArrayBuffer.apply(null, [1000]); }, TypeError); -assertThrows(function() { Float32Array.apply(null, [b, 128, 1]); }, TypeError); - -// Test array.set in different combinations. - -function assertArrayPrefix(expected, array) { - for (var i = 0; i < expected.length; ++i) { - assertEquals(expected[i], array[i]); - } -} - -var a11 = new Int16Array([1, 2, 3, 4, 0, -1]) -var a12 = new Uint16Array(15) -a12.set(a11, 3) -assertArrayPrefix([0, 0, 0, 1, 2, 3, 4, 0, 0xffff, 0, 0], a12) -assertThrows(function(){ a11.set(a12) }) - -var a21 = [1, undefined, 10, NaN, 0, -1, {valueOf: function() {return 3}}] -var a22 = new Int32Array(12) -a22.set(a21, 2) -assertArrayPrefix([0, 0, 1, 0, 10, 0, 0, -1, 3, 0], a22) - -var a31 = new Float32Array([2, 4, 6, 8, 11, NaN, 1/0, -3]) -var a32 = a31.subarray(2, 6) -a31.set(a32, 4) -assertArrayPrefix([2, 4, 6, 8, 6, 8, 11, NaN], a31) -assertArrayPrefix([6, 8, 6, 8], a32) - -var a4 = new Uint8ClampedArray([3,2,5,6]) -a4.set(a4) -assertArrayPrefix([3, 2, 5, 6], a4) - -// Cases with overlapping backing store but different element sizes. -var b = new ArrayBuffer(4) -var a5 = new Int16Array(b) -var a50 = new Int8Array(b) -var a51 = new Int8Array(b, 0, 2) -var a52 = new Int8Array(b, 1, 2) -var a53 = new Int8Array(b, 2, 2) - -a5.set([0x5050, 0x0a0a]) -assertArrayPrefix([0x50, 0x50, 0x0a, 0x0a], a50) -assertArrayPrefix([0x50, 0x50], a51) -assertArrayPrefix([0x50, 0x0a], a52) -assertArrayPrefix([0x0a, 0x0a], a53) - -a50.set([0x50, 0x50, 0x0a, 0x0a]) -a51.set(a5) -assertArrayPrefix([0x50, 0x0a, 0x0a, 0x0a], a50) - -a50.set([0x50, 0x50, 0x0a, 0x0a]) -a52.set(a5) -assertArrayPrefix([0x50, 0x50, 0x0a, 0x0a], a50) - -a50.set([0x50, 0x50, 0x0a, 0x0a]) -a53.set(a5) -assertArrayPrefix([0x50, 0x50, 0x50, 0x0a], a50) - -a50.set([0x50, 0x51, 0x0a, 0x0b]) -a5.set(a51) -assertArrayPrefix([0x0050, 0x0051], a5) - -a50.set([0x50, 0x51, 0x0a, 0x0b]) -a5.set(a52) -assertArrayPrefix([0x0051, 0x000a], a5) - -a50.set([0x50, 0x51, 0x0a, 0x0b]) -a5.set(a53) -assertArrayPrefix([0x000a, 0x000b], a5) - -// Mixed types of same size. -var a61 = new Float32Array([1.2, 12.3]) -var a62 = new Int32Array(2) -a62.set(a61) -assertArrayPrefix([1, 12], a62) -a61.set(a62) -assertArrayPrefix([1, 12], a61) - -// Invalid source -assertThrows(function() { a.set(0); }, TypeError); -assertArrayPrefix([1,2,3,4,5,6], a); -a.set({}); // does not throw -assertArrayPrefix([1,2,3,4,5,6], a); - - -// Test arraybuffer.slice - -var a0 = new Int8Array([1, 2, 3, 4, 5, 6]) -var b0 = a0.buffer - -var b1 = b0.slice(0) -assertEquals(b0.byteLength, b1.byteLength) -assertArrayPrefix([1, 2, 3, 4, 5, 6], new Int8Array(b1)) - -var b2 = b0.slice(3) -assertEquals(b0.byteLength - 3, b2.byteLength) -assertArrayPrefix([4, 5, 6], new Int8Array(b2)) - -var b3 = b0.slice(2, 4) -assertEquals(2, b3.byteLength) -assertArrayPrefix([3, 4], new Int8Array(b3)) - -function goo(a, i) { - return a[i]; -} - -function boo(a, i, v) { - return a[i] = v; -} - -function do_tagged_index_external_array_test(constructor) { - var t_array = new constructor([1, 2, 3, 4, 5, 6]); - assertEquals(1, goo(t_array, 0)); - assertEquals(1, goo(t_array, 0)); - boo(t_array, 0, 13); - assertEquals(13, goo(t_array, 0)); - %OptimizeFunctionOnNextCall(goo); - %OptimizeFunctionOnNextCall(boo); - boo(t_array, 0, 15); - assertEquals(15, goo(t_array, 0)); - %ClearFunctionTypeFeedback(goo); - %ClearFunctionTypeFeedback(boo); -} - -do_tagged_index_external_array_test(Int8Array); -do_tagged_index_external_array_test(Uint8Array); -do_tagged_index_external_array_test(Int16Array); -do_tagged_index_external_array_test(Uint16Array); -do_tagged_index_external_array_test(Int32Array); -do_tagged_index_external_array_test(Uint32Array); -do_tagged_index_external_array_test(Float32Array); -do_tagged_index_external_array_test(Float64Array); - -var built_in_array = new Array(1, 2, 3, 4, 5, 6); -assertEquals(1, goo(built_in_array, 0)); -assertEquals(1, goo(built_in_array, 0)); -%OptimizeFunctionOnNextCall(goo); -%OptimizeFunctionOnNextCall(boo); -boo(built_in_array, 0, 11); -assertEquals(11, goo(built_in_array, 0)); -%ClearFunctionTypeFeedback(goo); -%ClearFunctionTypeFeedback(boo); - -built_in_array = new Array(1.5, 2, 3, 4, 5, 6); -assertEquals(1.5, goo(built_in_array, 0)); -assertEquals(1.5, goo(built_in_array, 0)); -%OptimizeFunctionOnNextCall(goo); -%OptimizeFunctionOnNextCall(boo); -boo(built_in_array, 0, 2.5); -assertEquals(2.5, goo(built_in_array, 0)); -%ClearFunctionTypeFeedback(goo); -%ClearFunctionTypeFeedback(boo); - -// Check all int range edge cases -function checkRange() { - var e32 = Math.pow(2,32); var e31 = Math.pow(2,31); - var e16 = Math.pow(2,16); var e15 = Math.pow(2,15); - var e8 = Math.pow(2,8); var e7 = Math.pow(2,7); - var a7 = new Uint32Array(2); var a71 = new Int32Array(2); - var a72 = new Uint16Array(2); var a73 = new Int16Array(2); - var a74 = new Uint8Array(2); var a75 = new Int8Array(2); - for (i = 1; i <= Math.pow(2,33); i *= 2) { - var j = i-1; - a7[0] = i; a71[0] = i; a72[0] = i; a73[0] = i; a74[0] = i; a75[0] = i; - a7[1] = j; a71[1] = j; a72[1] = j; a73[1] = j; a74[1] = j; a75[1] = j; - - if (i < e32) { assertEquals(a7[0], i); } else { assertEquals(a7[0], 0); } - if (j < e32) { assertEquals(a7[1], j); } else { assertEquals(a7[1],e32-1); } - if (i < e31) { assertEquals(a71[0], i); } else { - assertEquals(a71[0], (i < e32) ? -e31 : 0 ); } - if (j < e31) { assertEquals(a71[1], j); } else { assertEquals(a71[1], -1); } - - if (i < e16) { assertEquals(a72[0], i); } else { assertEquals(a72[0], 0); } - if (j < e16) { assertEquals(a72[1], j); } else { assertEquals(a72[1], e16-1); } - if (i < e15) { assertEquals(a73[0], i); } else { - assertEquals(a73[0], (i < e16) ? -e15 : 0 ); } - if (j < e15) { assertEquals(a73[1], j); } else { assertEquals(a73[1], -1); } - - if (i < e8) { assertEquals(a74[0], i); } else { assertEquals(a74[0], 0); } - if (j < e8) { assertEquals(a74[1], j); } else { assertEquals(a74[1], e8-1); } - if (i < e7) { assertEquals(a75[0], i); } else { - assertEquals(a75[0], (i < e8) ? -e7 : 0); } - if (j < e7) { assertEquals(a75[1], j); } else { assertEquals(a75[1], -1); } - } -} -checkRange(); diff --git a/deps/v8/test/mjsunit/for-in.js b/deps/v8/test/mjsunit/for-in.js index ab35e95ee3..644c27a632 100644 --- a/deps/v8/test/mjsunit/for-in.js +++ b/deps/v8/test/mjsunit/for-in.js @@ -119,3 +119,15 @@ for (i=0 ; i < 3; ++i) { assertEquals("undefined", typeof y[2], "y[2]"); assertEquals("undefined", typeof y[0], "y[0]"); } + +(function() { + var large_key = 2147483650; + var o = {__proto__: {}}; + o[large_key] = 1; + o.__proto__[large_key] = 1; + var keys = []; + for (var k in o) { + keys.push(k); + } + assertEquals(["2147483650"], keys); +})(); diff --git a/deps/v8/test/mjsunit/function-bind-name.js b/deps/v8/test/mjsunit/function-bind-name.js new file mode 100644 index 0000000000..3bebf3e72d --- /dev/null +++ b/deps/v8/test/mjsunit/function-bind-name.js @@ -0,0 +1,13 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function f() {} +var fb = f.bind({}); +assertEquals('bound f', fb.name); +assertEquals('function bound f() { [native code] }', fb.toString()); + +Object.defineProperty(f, 'name', {value: 42}); +var fb2 = f.bind({}); +assertEquals('bound ', fb2.name); +assertEquals('function bound () { [native code] }', fb2.toString()); diff --git a/deps/v8/test/mjsunit/get-caller-js-function-throws.js b/deps/v8/test/mjsunit/get-caller-js-function-throws.js new file mode 100644 index 0000000000..42b098aee9 --- /dev/null +++ b/deps/v8/test/mjsunit/get-caller-js-function-throws.js @@ -0,0 +1,14 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --noalways-opt --nostress-opt + +// Ensure that "real" js functions that call GetCallerJSFunction get an +// exception, since they are not stubs. +(function() { + var a = function() { + return %_GetCallerJSFunction(); + } + assertThrows(a); +}()); diff --git a/deps/v8/test/mjsunit/get-caller-js-function.js b/deps/v8/test/mjsunit/get-caller-js-function.js new file mode 100644 index 0000000000..5c7af64814 --- /dev/null +++ b/deps/v8/test/mjsunit/get-caller-js-function.js @@ -0,0 +1,21 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --turbo-filter=* --nostress-opt + +// Test that for fully optimized but non inlined code, GetCallerJSFunction walks +// up a single stack frame to get the calling function. Full optimization elides +// the check in the runtime version of the intrinsic that would throw since the +// caller isn't a stub. It's a bit of a hack, but allows minimal testing of the +// intrinsic without writing a full-blown cctest. +(function() { + var a = function() { + return %_GetCallerJSFunction(); + }; + var b = function() { + return a(); + }; + %OptimizeFunctionOnNextCall(a); + assertEquals(b, b()); +}()); diff --git a/deps/v8/test/mjsunit/global-deleted-property-keyed.js b/deps/v8/test/mjsunit/global-deleted-property-keyed.js index dba3a4d405..a0e48ffdeb 100644 --- a/deps/v8/test/mjsunit/global-deleted-property-keyed.js +++ b/deps/v8/test/mjsunit/global-deleted-property-keyed.js @@ -26,9 +26,9 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-natives_as natives -// Test keyed access to deleted property in a global object without access checks. -// Regression test that exposed the_hole value from Runtime_KeyedGetPoperty. +// Flags: --expose-natives-as natives +// Test keyed access to deleted property in a global object w/o access checks. +// Regression test that exposed the_hole value from Runtime_KeyedGetProperty. var name = "fisk"; natives[name] = name; diff --git a/deps/v8/test/mjsunit/global-hash.js b/deps/v8/test/mjsunit/global-hash.js new file mode 100644 index 0000000000..54dfc4c779 --- /dev/null +++ b/deps/v8/test/mjsunit/global-hash.js @@ -0,0 +1,19 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var global = this; + +assertEquals("object", typeof global); // Global object. + +var s = new Set(); +s.add(global); // Puts a hash code on the global object. +assertTrue(s.has(global)); +for (var i = 0; i < 100; i++) { + // Force rehash. Global object is placed according to the hash code that it + // gets in the C++ runtime. + s.add(i); +} + +// Hopefully still findable using the JS hash code. +assertTrue(s.has(global)); diff --git a/deps/v8/test/mjsunit/handle-count-ast.js b/deps/v8/test/mjsunit/handle-count-ast.js new file mode 100644 index 0000000000..8d095598e7 --- /dev/null +++ b/deps/v8/test/mjsunit/handle-count-ast.js @@ -0,0 +1,12 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --check-handle-count + +var ones = eval("[" + Array(12 * 1024).join("1,") + 1 + "]") + +var sum = 0; +for (var i = 0; i < ones.length; i++) { + sum += ones[i]; +} diff --git a/deps/v8/test/mjsunit/handle-count-runtime-literals.js b/deps/v8/test/mjsunit/handle-count-runtime-literals.js new file mode 100644 index 0000000000..91774d2b6f --- /dev/null +++ b/deps/v8/test/mjsunit/handle-count-runtime-literals.js @@ -0,0 +1,1230 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --check-handle-count + +(function (s) { + s.frob = function () { + var j; + var p0 = /^[\],:{}\s]*$/; + var p1 = /"[^"\\\n\r]*"|a|b|c|_*-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g; + var p2 = /(?:^|:|,)(?:\s*\[)+/g; + if (p0.test(this.replace(/\\./g, '@').replace(p1, ']').replace(p2, ''))) { + var tmp = eval('(' + this + ')'); + return 0; + } + return -1; + }; +})(String.prototype); + +var kvJSON = '[\ + {\n \"key\": "ionion",\n \"value\": 779249\n },\ + {\n \"key\": "essess",\n \"value\": 775215\n },\ + {\n \"key\": "lerler",\n \"value\": 773163\n },\ + {\n \"key\": "essess",\n \"value\": 778638\n },\ + {\n \"key\": "suosuo",\n \"value\": 778428\n },\ + {\n \"key\": "astast",\n \"value\": 779719\n },\ + {\n \"key\": "oidoid",\n \"value\": 776316\n },\ + {\n \"key\": "onyony",\n \"value\": 777017\n },\ + {\n \"key\": "oryory",\n \"value\": 775785\n },\ + {\n \"key\": "ardard",\n \"value\": 776276\n },\ + {\n \"key\": "nicnic",\n \"value\": 773163\n },\ + {\n \"key\": "udyudy",\n \"value\": 775255\n },\ + {\n \"key\": "blybly",\n \"value\": 776546\n },\ + {\n \"key\": "ormorm",\n \"value\": 770040\n },\ + {\n \"key\": "izeize",\n \"value\": 774534\n },\ + {\n \"key\": "lialia",\n \"value\": 775135\n },\ + {\n \"key\": "thythy",\n \"value\": 773823\n },\ + {\n \"key\": "hiphip",\n \"value\": 776526\n },\ + {\n \"key\": "iseise",\n \"value\": 772322\n },\ + {\n \"key\": "salsal",\n \"value\": 772122\n },\ + {\n \"key\": "essess",\n \"value\": 775915\n },\ + {\n \"key\": "etaeta",\n \"value\": 779719\n },\ + {\n \"key\": "kcakca",\n \"value\": 776616\n },\ + {\n \"key\": "tiktik",\n \"value\": 773513\n },\ + {\n \"key\": "rerrer",\n \"value\": 773413\n },\ + {\n \"key\": "teatea",\n \"value\": 773313\n },\ + {\n \"key\": "izeize",\n \"value\": 774214\n },\ + {\n \"key\": "reyrey",\n \"value\": 777117\n },\ + {\n \"key\": "oteote",\n \"value\": 770110\n },\ + {\n \"key\": "essess",\n \"value\": 773013\n },\ + {\n \"key\": "essess",\n \"value\": 778798\n },\ + {\n \"key\": "tchtch",\n \"value\": 774294\n },\ + {\n \"key\": "taltal",\n \"value\": 775785\n },\ + {\n \"key\": "risris",\n \"value\": 770380\n },\ + {\n \"key\": "ateate",\n \"value\": 779879\n },\ + {\n \"key\": "ousous",\n \"value\": 770570\n },\ + {\n \"key\": "essess",\n \"value\": 775175\n },\ + {\n \"key\": "lesles",\n \"value\": 772862\n },\ + {\n \"key\": "iveive",\n \"value\": 771561\n },\ + {\n \"key\": "diadia",\n \"value\": 772262\n },\ + {\n \"key\": "ekieki",\n \"value\": 776956\n },\ + {\n \"key\": "omaoma",\n \"value\": 771751\n },\ + {\n \"key\": "nalnal",\n \"value\": 777457\n },\ + {\n \"key\": "essess",\n \"value\": 776256\n },\ + {\n \"key\": "ilyily",\n \"value\": 775055\n },\ + {\n \"key\": "emuemu",\n \"value\": 776846\n },\ + {\n \"key\": "eeteet",\n \"value\": 778648\n },\ + {\n \"key\": "rerrer",\n \"value\": 770540\n },\ + {\n \"key\": "eaeeae",\n \"value\": 774344\n },\ + {\n \"key\": "lumlum",\n \"value\": 779149\n },\ + {\n \"key\": "essess",\n \"value\": 774044\n },\ + {\n \"key\": "antant",\n \"value\": 771931\n },\ + {\n \"key\": "lahlah",\n \"value\": 778738\n },\ + {\n \"key\": "tnatna",\n \"value\": 775635\n },\ + {\n \"key\": "oseose",\n \"value\": 774534\n },\ + {\n \"key\": "ataata",\n \"value\": 773433\n },\ + {\n \"key\": "inging",\n \"value\": 772332\n },\ + {\n \"key\": "ypeype",\n \"value\": 772232\n },\ + {\n \"key\": "tictic",\n \"value\": 772132\n },\ + {\n \"key\": "hiphip",\n \"value\": 773033\n },\ + {\n \"key\": "taltal",\n \"value\": 774924\n },\ + {\n \"key\": "istist",\n \"value\": 776826\n },\ + {\n \"key\": "ralral",\n \"value\": 778728\n },\ + {\n \"key\": "tortor",\n \"value\": 770720\n },\ + {\n \"key\": "rnsrns",\n \"value\": 773623\n },\ + {\n \"key\": "siasia",\n \"value\": 776526\n },\ + {\n \"key\": "yabyab",\n \"value\": 779429\n },\ + {\n \"key\": "noinoi",\n \"value\": 773423\n },\ + {\n \"key\": "ardard",\n \"value\": 777327\n },\ + {\n \"key\": "derder",\n \"value\": 771321\n },\ + {\n \"key\": "iveive",\n \"value\": 775225\n },\ + {\n \"key\": "ateate",\n \"value\": 779129\n },\ + {\n \"key\": "imoimo",\n \"value\": 774124\n },\ + {\n \"key\": "adeade",\n \"value\": 779029\n },\ + {\n \"key\": "ugeuge",\n \"value\": 774024\n },\ + {\n \"key\": "iveive",\n \"value\": 779919\n },\ + {\n \"key\": "belbel",\n \"value\": 775915\n },\ + {\n \"key\": "inging",\n \"value\": 770910\n },\ + {\n \"key\": "barbar",\n \"value\": 776816\n },\ + {\n \"key\": "ionion",\n \"value\": 772812\n },\ + {\n \"key\": "ineine",\n \"value\": 778718\n },\ + {\n \"key\": "ityity",\n \"value\": 774714\n },\ + {\n \"key\": "ytiyti",\n \"value\": 770710\n },\ + {\n \"key\": "ismism",\n \"value\": 777617\n },\ + {\n \"key\": "iumium",\n \"value\": 773613\n },\ + {\n \"key\": "hichic",\n \"value\": 770610\n },\ + {\n \"key\": "ideide",\n \"value\": 777517\n },\ + {\n \"key\": "denden",\n \"value\": 774514\n },\ + {\n \"key\": "redred",\n \"value\": 770510\n },\ + {\n \"key\": "perper",\n \"value\": 778418\n },\ + {\n \"key\": "rusrus",\n \"value\": 775415\n },\ + {\n \"key\": "herher",\n \"value\": 772412\n },\ + {\n \"key\": "sidsid",\n \"value\": 779319\n },\ + {\n \"key\": "ianian",\n \"value\": 777317\n },\ + {\n \"key\": "ricric",\n \"value\": 774314\n },\ + {\n \"key\": "odyody",\n \"value\": 772312\n },\ + {\n \"key\": "ferfer",\n \"value\": 779219\n },\ + {\n \"key\": "ogyogy",\n \"value\": 777217\n },\ + {\n \"key\": "micmic",\n \"value\": 775215\n },\ + {\n \"key\": "ateate",\n \"value\": 772212\n },\ + {\n \"key\": "tantan",\n \"value\": 770210\n },\ + {\n \"key\": "getget",\n \"value\": 778118\n },\ + {\n \"key\": "ulaula",\n \"value\": 776116\n },\ + {\n \"key\": "calcal",\n \"value\": 774114\n },\ + {\n \"key\": "izeize",\n \"value\": 772112\n },\ + {\n \"key\": "manman",\n \"value\": 770110\n },\ + {\n \"key\": "terter",\n \"value\": 778018\n },\ + {\n \"key\": "hedhed",\n \"value\": 777017\n },\ + {\n \"key\": "berber",\n \"value\": 775015\n },\ + {\n \"key\": "olfolf",\n \"value\": 773013\n },\ + {\n \"key\": "opeope",\n \"value\": 772012\n },\ + {\n \"key\": "hiphip",\n \"value\": 770010\n },\ + {\n \"key\": "tedted",\n \"value\": 779899\n },\ + {\n \"key\": "ismism",\n \"value\": 773793\n },\ + {\n \"key\": "terter",\n \"value\": 778598\n },\ + {\n \"key\": "ismism",\n \"value\": 774494\n },\ + {\n \"key\": "ikeike",\n \"value\": 779299\n },\ + {\n \"key\": "sdrsdr",\n \"value\": 776196\n },\ + {\n \"key\": "calcal",\n \"value\": 772092\n },\ + {\n \"key\": "ledled",\n \"value\": 779889\n },\ + {\n \"key\": "coicoi",\n \"value\": 776786\n },\ + {\n \"key\": "ialial",\n \"value\": 773683\n },\ + {\n \"key\": "izeize",\n \"value\": 771581\n },\ + {\n \"key\": "ogyogy",\n \"value\": 778388\n },\ + {\n \"key\": "ismism",\n \"value\": 777287\n },\ + {\n \"key\": "Huk",\n \"value\": 775185\n },\ + {\n \"key\": "nonnon",\n \"value\": 774084\n },\ + {\n \"key\": "ledled",\n \"value\": 773973\n },\ + {\n \"key\": "llylly",\n \"value\": 772872\n },\ + {\n \"key\": "ishish",\n \"value\": 771771\n },\ + {\n \"key\": "terter",\n \"value\": 771671\n },\ + {\n \"key\": "iorior",\n \"value\": 771571\n },\ + {\n \"key\": "ionion",\n \"value\": 771471\n },\ + {\n \"key\": "luslus",\n \"value\": 771371\n },\ + {\n \"key\": "detdet",\n \"value\": 771271\n },\ + {\n \"key\": "ionion",\n \"value\": 772172\n },\ + {\n \"key\": "ezoezo",\n \"value\": 773073\n },\ + {\n \"key\": "iceice",\n \"value\": 774964\n },\ + {\n \"key\": "piapia",\n \"value\": 775865\n },\ + {\n \"key\": "nedned",\n \"value\": 776766\n },\ + {\n \"key\": "ffaffa",\n \"value\": 778668\n },\ + {\n \"key\": "oidoid",\n \"value\": 779569\n },\ + {\n \"key\": "ureure",\n \"value\": 771561\n },\ + {\n \"key\": "akaaka",\n \"value\": 773463\n },\ + {\n \"key\": "jimjim",\n \"value\": 775365\n },\ + {\n \"key\": "calcal",\n \"value\": 778268\n },\ + {\n \"key\": "istist",\n \"value\": 770260\n },\ + {\n \"key\": "ickick",\n \"value\": 773163\n },\ + {\n \"key\": "ncence",\n \"value\": 775065\n },\ + {\n \"key\": "ikeike",\n \"value\": 778958\n },\ + {\n \"key\": "omeome",\n \"value\": 771951\n },\ + {\n \"key\": "ismism",\n \"value\": 774854\n },\ + {\n \"key\": "eeleel",\n \"value\": 778758\n },\ + {\n \"key\": "ialial",\n \"value\": 771751\n },\ + {\n \"key\": "deadea",\n \"value\": 774654\n },\ + {\n \"key\": "fulful",\n \"value\": 778558\n },\ + {\n \"key\": "bleble",\n \"value\": 772552\n },\ + {\n \"key\": "tahtah",\n \"value\": 776456\n },\ + {\n \"key\": "astast",\n \"value\": 770450\n },\ + {\n \"key\": "ylsyls",\n \"value\": 774354\n },\ + {\n \"key\": "ziazia",\n \"value\": 778258\n },\ + {\n \"key\": "ssesse",\n \"value\": 772252\n },\ + {\n \"key\": "essess",\n \"value\": 776156\n },\ + {\n \"key\": "lewlew",\n \"value\": 771151\n },\ + {\n \"key\": "ionion",\n \"value\": 775055\n },\ + {\n \"key\": "ackack",\n \"value\": 770050\n },\ + {\n \"key\": "wedwed",\n \"value\": 775945\n },\ + {\n \"key\": "gnigni",\n \"value\": 779849\n },\ + {\n \"key\": "areare",\n \"value\": 774844\n },\ + {\n \"key\": "oleole",\n \"value\": 779749\n },\ + {\n \"key\": "ateate",\n \"value\": 774744\n },\ + {\n \"key\": "ousous",\n \"value\": 779649\n },\ + {\n \"key\": "niania",\n \"value\": 775645\n },\ + {\n \"key\": "tletle",\n \"value\": 770640\n },\ + {\n \"key\": "cimcim",\n \"value\": 775545\n },\ + {\n \"key\": "eedeed",\n \"value\": 771541\n },\ + {\n \"key\": "bleble",\n \"value\": 776446\n },\ + {\n \"key\": "tcatca",\n \"value\": 772442\n },\ + {\n \"key\": "oneone",\n \"value\": 777347\n },\ + {\n \"key\": "nidnid",\n \"value\": 773343\n },\ + {\n \"key\": "hnahna",\n \"value\": 779249\n },\ + {\n \"key\": "olfolf",\n \"value\": 775245\n },\ + {\n \"key\": "ousous",\n \"value\": 770240\n },\ + {\n \"key\": "verver",\n \"value\": 776146\n },\ + {\n \"key\": "oseose",\n \"value\": 772142\n },\ + {\n \"key\": "tictic",\n \"value\": 779049\n },\ + {\n \"key\": "essess",\n \"value\": 775045\n },\ + {\n \"key\": "ionion",\n \"value\": 771041\n },\ + {\n \"key\": "iedied",\n \"value\": 777937\n },\ + {\n \"key\": "diadia",\n \"value\": 773933\n },\ + {\n \"key\": "ityity",\n \"value\": 770930\n },\ + {\n \"key\": "fulful",\n \"value\": 776836\n },\ + {\n \"key\": "ukeuke",\n \"value\": 773833\n },\ + {\n \"key\": "intint",\n \"value\": 779739\n },\ + {\n \"key\": "hoqhoq",\n \"value\": 776736\n },\ + {\n \"key\": "yoxyox",\n \"value\": 772732\n },\ + {\n \"key\": "taltal",\n \"value\": 779639\n },\ + {\n \"key\": "paipai",\n \"value\": 776636\n },\ + {\n \"key\": "eanean",\n \"value\": 772632\n },\ + {\n \"key\": "ineine",\n \"value\": 779539\n },\ + {\n \"key\": "uthuth",\n \"value\": 776536\n },\ + {\n \"key\": "izeize",\n \"value\": 773533\n },\ + {\n \"key\": "rubrub",\n \"value\": 770530\n },\ + {\n \"key\": "ilyily",\n \"value\": 777437\n },\ + {\n \"key\": "ylbylb",\n \"value\": 774434\n },\ + {\n \"key\": "liclic",\n \"value\": 771431\n },\ + {\n \"key\": "bleble",\n \"value\": 778338\n },\ + {\n \"key\": "elyely",\n \"value\": 775335\n },\ + {\n \"key\": "nelnel",\n \"value\": 772332\n },\ + {\n \"key\": "siasia",\n \"value\": 779239\n },\ + {\n \"key\": "monmon",\n \"value\": 777237\n },\ + {\n \"key\": "rinrin",\n \"value\": 774234\n },\ + {\n \"key\": "nalnal",\n \"value\": 771231\n },\ + {\n \"key\": "etyety",\n \"value\": 779139\n },\ + {\n \"key\": "tictic",\n \"value\": 776136\n },\ + {\n \"key\": "hsuhsu",\n \"value\": 773133\n },\ + {\n \"key\": "testes",\n \"value\": 771131\n },\ + {\n \"key\": "ritrit",\n \"value\": 778038\n },\ + {\n \"key\": "gabgab",\n \"value\": 776036\n },\ + {\n \"key\": "naenae",\n \"value\": 773033\n },\ + {\n \"key\": "noinoi",\n \"value\": 771031\n },\ + {\n \"key\": "ondond",\n \"value\": 778928\n },\ + {\n \"key\": "nisnis",\n \"value\": 776926\n },\ + {\n \"key\": "ianian",\n \"value\": 774924\n },\ + {\n \"key\": "cincin",\n \"value\": 771921\n },\ + {\n \"key\": "luslus",\n \"value\": 779829\n },\ + {\n \"key\": "llylly",\n \"value\": 777827\n },\ + {\n \"key\": "ltylty",\n \"value\": 775825\n },\ + {\n \"key\": "nienie",\n \"value\": 772822\n },\ + {\n \"key\": "ookook",\n \"value\": 770820\n },\ + {\n \"key\": "oinoin",\n \"value\": 778728\n },\ + {\n \"key\": "dmidmi",\n \"value\": 776726\n },\ + {\n \"key\": "macmac",\n \"value\": 774724\n },\ + {\n \"key\": "bleble",\n \"value\": 772722\n },\ + {\n \"key\": "ionion",\n \"value\": 770720\n },\ + {\n \"key\": "manman",\n \"value\": 778628\n },\ + {\n \"key\": "cipcip",\n \"value\": 776626\n },\ + {\n \"key\": "barbar",\n \"value\": 774624\n },\ + {\n \"key\": "llylly",\n \"value\": 772622\n },\ + {\n \"key\": "hothot",\n \"value\": 770620\n },\ + {\n \"key\": "oodood",\n \"value\": 778528\n },\ + {\n \"key\": "cumcum",\n \"value\": 776526\n },\ + {\n \"key\": "rkarka",\n \"value\": 774524\n },\ + {\n \"key\": "iveive",\n \"value\": 772522\n },\ + {\n \"key\": "ranran",\n \"value\": 771521\n },\ + {\n \"key\": "lesles",\n \"value\": 779429\n },\ + {\n \"key\": "fulful",\n \"value\": 777427\n },\ + {\n \"key\": "nalnal",\n \"value\": 775425\n },\ + {\n \"key\": "ousous",\n \"value\": 773423\n },\ + {\n \"key\": "inging",\n \"value\": 772422\n },\ + {\n \"key\": "ionion",\n \"value\": 770420\n },\ + {\n \"key\": "ousous",\n \"value\": 778328\n },\ + {\n \"key\": "pitpit",\n \"value\": 777327\n },\ + {\n \"key\": "oicoic",\n \"value\": 775325\n },\ + {\n \"key\": "vetvet",\n \"value\": 773323\n },\ + {\n \"key\": "erkerk",\n \"value\": 772322\n },\ + {\n \"key\": "ncyncy",\n \"value\": 770320\n },\ + {\n \"key\": "ionion",\n \"value\": 779229\n },\ + {\n \"key\": "inging",\n \"value\": 777227\n },\ + {\n \"key\": "tictic",\n \"value\": 775225\n },\ + {\n \"key\": "sissis",\n \"value\": 774224\n },\ + {\n \"key\": "rgyrgy",\n \"value\": 772222\n },\ + {\n \"key\": "tictic",\n \"value\": 771221\n },\ + {\n \"key\": "oedoed",\n \"value\": 779129\n },\ + {\n \"key\": "omaoma",\n \"value\": 778128\n },\ + {\n \"key\": "hiphip",\n \"value\": 777127\n },\ + {\n \"key\": "ncence",\n \"value\": 775125\n },\ + {\n \"key\": "ousous",\n \"value\": 774124\n },\ + {\n \"key\": "rghrgh",\n \"value\": 772122\n },\ + {\n \"key\": "ebtebt",\n \"value\": 771121\n },\ + {\n \"key\": "msimsi",\n \"value\": 779029\n },\ + {\n \"key\": "inging",\n \"value\": 778028\n },\ + {\n \"key\": "aukauk",\n \"value\": 777027\n },\ + {\n \"key\": "getget",\n \"value\": 775025\n },\ + {\n \"key\": "otaota",\n \"value\": 774024\n },\ + {\n \"key\": "oseose",\n \"value\": 773023\n },\ + {\n \"key\": "sapsap",\n \"value\": 771021\n },\ + {\n \"key\": "micmic",\n \"value\": 770020\n },\ + {\n \"key\": "calcal",\n \"value\": 779919\n },\ + {\n \"key\": "ismism",\n \"value\": 778918\n },\ + {\n \"key\": "dlydly",\n \"value\": 776916\n },\ + {\n \"key\": "ionion",\n \"value\": 775915\n },\ + {\n \"key\": "stysty",\n \"value\": 774914\n },\ + {\n \"key\": "kgokgo",\n \"value\": 773913\n },\ + {\n \"key\": "entent",\n \"value\": 772912\n },\ + {\n \"key\": "entent",\n \"value\": 770910\n },\ + {\n \"key\": "manman",\n \"value\": 779819\n },\ + {\n \"key\": "minmin",\n \"value\": 778818\n },\ + {\n \"key\": "gotgot",\n \"value\": 777817\n },\ + {\n \"key\": "unkunk",\n \"value\": 776816\n },\ + {\n \"key\": "ionion",\n \"value\": 775815\n },\ + {\n \"key\": "kerker",\n \"value\": 773813\n },\ + {\n \"key\": "eltelt",\n \"value\": 772812\n },\ + {\n \"key\": "manman",\n \"value\": 771811\n },\ + {\n \"key\": "ncence",\n \"value\": 770810\n },\ + {\n \"key\": "ernern",\n \"value\": 779719\n },\ + {\n \"key\": "eegeeg",\n \"value\": 778718\n },\ + {\n \"key\": "athath",\n \"value\": 777717\n },\ + {\n \"key\": "daedae",\n \"value\": 776716\n },\ + {\n \"key\": "ionion",\n \"value\": 775715\n },\ + {\n \"key\": "kerker",\n \"value\": 774714\n },\ + {\n \"key\": "terter",\n \"value\": 773713\n },\ + {\n \"key\": "essess",\n \"value\": 772712\n },\ + {\n \"key\": "aneane",\n \"value\": 771711\n },\ + {\n \"key\": "lahlah",\n \"value\": 770710\n },\ + {\n \"key\": "inging",\n \"value\": 779619\n },\ + {\n \"key\": "pilpil",\n \"value\": 778618\n },\ + {\n \"key\": "iseise",\n \"value\": 777617\n },\ + {\n \"key\": "sonson",\n \"value\": 776616\n },\ + {\n \"key\": "ityity",\n \"value\": 775615\n },\ + {\n \"key\": "esaesa",\n \"value\": 774614\n },\ + {\n \"key\": "araara",\n \"value\": 773613\n },\ + {\n \"key\": "perper",\n \"value\": 772612\n },\ + {\n \"key\": "siasia",\n \"value\": 771611\n },\ + {\n \"key\": "bleble",\n \"value\": 770610\n },\ + {\n \"key\": "rumrum",\n \"value\": 779519\n },\ + {\n \"key\": "toltol",\n \"value\": 779519\n },\ + {\n \"key\": "ousous",\n \"value\": 778518\n },\ + {\n \"key\": "ateate",\n \"value\": 777517\n },\ + {\n \"key\": "verver",\n \"value\": 776516\n },\ + {\n \"key\": "psepse",\n \"value\": 775515\n },\ + {\n \"key\": "rkyrky",\n \"value\": 774514\n },\ + {\n \"key\": "uleule",\n \"value\": 773513\n },\ + {\n \"key\": "adaada",\n \"value\": 772512\n },\ + {\n \"key\": "minmin",\n \"value\": 772512\n },\ + {\n \"key\": "amiami",\n \"value\": 771511\n },\ + {\n \"key\": "ulfulf",\n \"value\": 770510\n },\ + {\n \"key\": "rtzrtz",\n \"value\": 779419\n },\ + {\n \"key\": "ockock",\n \"value\": 778418\n },\ + {\n \"key\": "izeize",\n \"value\": 778418\n },\ + {\n \"key\": "oidoid",\n \"value\": 777417\n },\ + {\n \"key\": "bisbis",\n \"value\": 776416\n },\ + {\n \"key\": "nedned",\n \"value\": 775415\n },\ + {\n \"key\": "ralral",\n \"value\": 774414\n },\ + {\n \"key\": "aryary",\n \"value\": 774414\n },\ + {\n \"key\": "ikeike",\n \"value\": 773413\n },\ + {\n \"key\": "terter",\n \"value\": 772412\n },\ + {\n \"key\": "oveove",\n \"value\": 771411\n },\ + {\n \"key\": "ineine",\n \"value\": 771411\n },\ + {\n \"key\": "ebiebi",\n \"value\": 770410\n },\ + {\n \"key\": "iumium",\n \"value\": 779319\n },\ + {\n \"key\": "dgedge",\n \"value\": 779319\n },\ + {\n \"key\": "riaria",\n \"value\": 778318\n },\ + {\n \"key\": "upaupa",\n \"value\": 777317\n },\ + {\n \"key\": "entent",\n \"value\": 776316\n },\ + {\n \"key\": "eneene",\n \"value\": 776316\n },\ + {\n \"key\": "ridrid",\n \"value\": 775315\n },\ + {\n \"key\": "llelle",\n \"value\": 774314\n },\ + {\n \"key\": "dlydly",\n \"value\": 774314\n },\ + {\n \"key\": "angang",\n \"value\": 773313\n },\ + {\n \"key\": "tictic",\n \"value\": 772312\n },\ + {\n \"key\": "ontont",\n \"value\": 772312\n },\ + {\n \"key\": "astast",\n \"value\": 771311\n },\ + {\n \"key\": "suosuo",\n \"value\": 770310\n },\ + {\n \"key\": "essess",\n \"value\": 770310\n },\ + {\n \"key\": "essess",\n \"value\": 779219\n },\ + {\n \"key\": "istist",\n \"value\": 778218\n },\ + {\n \"key\": "inaina",\n \"value\": 778218\n },\ + {\n \"key\": "ewdewd",\n \"value\": 777217\n },\ + {\n \"key\": "verver",\n \"value\": 776216\n },\ + {\n \"key\": "ionion",\n \"value\": 776216\n },\ + {\n \"key\": "ardard",\n \"value\": 775215\n },\ + {\n \"key\": "pidpid",\n \"value\": 775215\n },\ + {\n \"key\": "eltelt",\n \"value\": 774214\n },\ + {\n \"key\": "letlet",\n \"value\": 773213\n },\ + {\n \"key\": "iesies",\n \"value\": 773213\n },\ + {\n \"key\": "ityity",\n \"value\": 772212\n },\ + {\n \"key\": "chacha",\n \"value\": 772212\n },\ + {\n \"key\": "ngenge",\n \"value\": 771211\n },\ + {\n \"key\": "terter",\n \"value\": 770210\n },\ + {\n \"key\": "eanean",\n \"value\": 770210\n },\ + {\n \"key\": "bleble",\n \"value\": 779119\n },\ + {\n \"key\": "llylly",\n \"value\": 779119\n },\ + {\n \"key\": "hiphip",\n \"value\": 778118\n },\ + {\n \"key\": "omaoma",\n \"value\": 778118\n },\ + {\n \"key\": "agoago",\n \"value\": 777117\n },\ + {\n \"key\": "oidoid",\n \"value\": 776116\n },\ + {\n \"key\": "manman",\n \"value\": 776116\n },\ + {\n \"key\": "ismism",\n \"value\": 775115\n },\ + {\n \"key\": "audaud",\n \"value\": 775115\n },\ + {\n \"key\": "ismism",\n \"value\": 774114\n },\ + {\n \"key\": "ionion",\n \"value\": 774114\n },\ + {\n \"key\": "thgthg",\n \"value\": 773113\n },\ + {\n \"key\": "endend",\n \"value\": 773113\n },\ + {\n \"key\": "udeude",\n \"value\": 772112\n },\ + {\n \"key\": "ashash",\n \"value\": 772112\n },\ + {\n \"key\": "ankank",\n \"value\": 771111\n },\ + {\n \"key\": "calcal",\n \"value\": 771111\n },\ + {\n \"key\": "pleple",\n \"value\": 770110\n },\ + {\n \"key\": "hedhed",\n \"value\": 770110\n },\ + {\n \"key\": "bleble",\n \"value\": 779019\n },\ + {\n \"key\": "tictic",\n \"value\": 779019\n },\ + {\n \"key\": "yteyte",\n \"value\": 778018\n },\ + {\n \"key\": "oldold",\n \"value\": 778018\n },\ + {\n \"key\": "steste",\n \"value\": 777017\n },\ + {\n \"key\": "ishish",\n \"value\": 777017\n },\ + {\n \"key\": "ineine",\n \"value\": 776016\n },\ + {\n \"key\": "manman",\n \"value\": 776016\n },\ + {\n \"key\": "miamia",\n \"value\": 775015\n },\ + {\n \"key\": "ifeife",\n \"value\": 775015\n },\ + {\n \"key\": "ssassa",\n \"value\": 774014\n },\ + {\n \"key\": "apeape",\n \"value\": 774014\n },\ + {\n \"key\": "essess",\n \"value\": 773013\n },\ + {\n \"key\": "fowfow",\n \"value\": 773013\n },\ + {\n \"key\": "siasia",\n \"value\": 773013\n },\ + {\n \"key\": "bleble",\n \"value\": 772012\n },\ + {\n \"key\": "eaeeae",\n \"value\": 772012\n },\ + {\n \"key\": "larlar",\n \"value\": 771011\n },\ + {\n \"key\": "tedted",\n \"value\": 771011\n },\ + {\n \"key\": "ralral",\n \"value\": 770010\n },\ + {\n \"key\": "ousous",\n \"value\": 770010\n },\ + {\n \"key\": "hpahpa",\n \"value\": 779999\n },\ + {\n \"key\": "iumium",\n \"value\": 775995\n },\ + {\n \"key\": "reeree",\n \"value\": 770990\n },\ + {\n \"key\": "hinhin",\n \"value\": 776896\n },\ + {\n \"key\": "malmal",\n \"value\": 772892\n },\ + {\n \"key\": "hathat",\n \"value\": 778798\n },\ + {\n \"key\": "dondon",\n \"value\": 774794\n },\ + {\n \"key\": "tictic",\n \"value\": 770790\n },\ + {\n \"key\": "ataata",\n \"value\": 776696\n },\ + {\n \"key\": "ilyily",\n \"value\": 771691\n },\ + {\n \"key\": "assass",\n \"value\": 777597\n },\ + {\n \"key\": "trytry",\n \"value\": 773593\n },\ + {\n \"key\": "essess",\n \"value\": 779499\n },\ + {\n \"key\": "ssesse",\n \"value\": 775495\n },\ + {\n \"key\": "horhor",\n \"value\": 772492\n },\ + {\n \"key\": "ionion",\n \"value\": 778398\n },\ + {\n \"key\": "glygly",\n \"value\": 774394\n },\ + {\n \"key\": "izeize",\n \"value\": 770390\n },\ + {\n \"key\": "essess",\n \"value\": 776296\n },\ + {\n \"key\": "dledle",\n \"value\": 772292\n },\ + {\n \"key\": "calcal",\n \"value\": 778198\n },\ + {\n \"key\": "denden",\n \"value\": 775195\n },\ + {\n \"key\": "ateate",\n \"value\": 771191\n },\ + {\n \"key\": "ylsyls",\n \"value\": 777097\n },\ + {\n \"key\": "oidoid",\n \"value\": 774094\n },\ + {\n \"key\": "llalla",\n \"value\": 770090\n },\ + {\n \"key\": "inging",\n \"value\": 776986\n },\ + {\n \"key\": "omeome",\n \"value\": 773983\n },\ + {\n \"key\": "ttette",\n \"value\": 779889\n },\ + {\n \"key\": "uliuli",\n \"value\": 776886\n },\ + {\n \"key\": "istist",\n \"value\": 772882\n },\ + {\n \"key\": "dlydly",\n \"value\": 778788\n },\ + {\n \"key\": "riaria",\n \"value\": 775785\n },\ + {\n \"key\": "ianian",\n \"value\": 771781\n },\ + {\n \"key\": "deldel",\n \"value\": 778688\n },\ + {\n \"key\": "eaeeae",\n \"value\": 775685\n },\ + {\n \"key\": "gungun",\n \"value\": 771681\n },\ + {\n \"key\": "inging",\n \"value\": 778588\n },\ + {\n \"key\": "noinoi",\n \"value\": 774584\n },\ + {\n \"key\": "serser",\n \"value\": 771581\n },\ + {\n \"key\": "ikeike",\n \"value\": 778488\n },\ + {\n \"key\": "rkyrky",\n \"value\": 774484\n },\ + {\n \"key\": "fulful",\n \"value\": 771481\n },\ + {\n \"key\": "acyacy",\n \"value\": 778388\n },\ + {\n \"key\": "nedned",\n \"value\": 775385\n },\ + {\n \"key\": "icaica",\n \"value\": 771381\n },\ + {\n \"key\": "ousous",\n \"value\": 778288\n },\ + {\n \"key\": "gyegye",\n \"value\": 775285\n },\ + {\n \"key\": "iumium",\n \"value\": 772282\n },\ + {\n \"key\": "ockock",\n \"value\": 779189\n },\ + {\n \"key\": "ushush",\n \"value\": 775185\n },\ + {\n \"key\": "noinoi",\n \"value\": 772182\n },\ + {\n \"key\": "ootoot",\n \"value\": 779089\n },\ + {\n \"key\": "entent",\n \"value\": 776086\n },\ + {\n \"key\": "llylly",\n \"value\": 773083\n },\ + {\n \"key\": "ilyily",\n \"value\": 770080\n },\ + {\n \"key\": "sdrsdr",\n \"value\": 777977\n },\ + {\n \"key\": "ionion",\n \"value\": 774974\n },\ + {\n \"key\": "hlyhly",\n \"value\": 771971\n },\ + {\n \"key\": "adoado",\n \"value\": 778878\n },\ + {\n \"key\": "inkink",\n \"value\": 775875\n },\ + {\n \"key\": "ineine",\n \"value\": 772872\n },\ + {\n \"key\": "ousous",\n \"value\": 779779\n },\ + {\n \"key\": "opeope",\n \"value\": 776776\n },\ + {\n \"key\": "cilcil",\n \"value\": 773773\n },\ + {\n \"key\": "ncyncy",\n \"value\": 771771\n },\ + {\n \"key\": "opyopy",\n \"value\": 778678\n },\ + {\n \"key\": "essess",\n \"value\": 775675\n },\ + {\n \"key\": "ygoygo",\n \"value\": 772672\n },\ + {\n \"key\": "ricric",\n \"value\": 779579\n },\ + {\n \"key\": "inging",\n \"value\": 776576\n },\ + {\n \"key\": "einein",\n \"value\": 774574\n },\ + {\n \"key\": "onaona",\n \"value\": 771571\n },\ + {\n \"key\": "elyely",\n \"value\": 778478\n },\ + {\n \"key\": "auraur",\n \"value\": 775475\n },\ + {\n \"key\": "tortor",\n \"value\": 773473\n },\ + {\n \"key\": "iveive",\n \"value\": 770470\n },\ + {\n \"key\": "taltal",\n \"value\": 777377\n },\ + {\n \"key\": "daedae",\n \"value\": 775375\n },\ + {\n \"key\": "rkarka",\n \"value\": 772372\n },\ + {\n \"key\": "wayway",\n \"value\": 779279\n },\ + {\n \"key\": "ousous",\n \"value\": 777277\n },\ + {\n \"key\": "iveive",\n \"value\": 774274\n },\ + {\n \"key\": "woewoe",\n \"value\": 772272\n },\ + {\n \"key\": "rphrph",\n \"value\": 779179\n },\ + {\n \"key\": "eeteet",\n \"value\": 776176\n },\ + {\n \"key\": "gnigni",\n \"value\": 774174\n },\ + {\n \"key\": "inkink",\n \"value\": 771171\n },\ + {\n \"key\": "terter",\n \"value\": 779079\n },\ + {\n \"key\": "ronron",\n \"value\": 776076\n },\ + {\n \"key\": "ageage",\n \"value\": 774074\n },\ + {\n \"key\": "oeaoea",\n \"value\": 771071\n },\ + {\n \"key\": "geygey",\n \"value\": 779969\n },\ + {\n \"key\": "oryory",\n \"value\": 776966\n },\ + {\n \"key\": "gilgil",\n \"value\": 774964\n },\ + {\n \"key\": "oraora",\n \"value\": 772962\n },\ + {\n \"key\": "tsrtsr",\n \"value\": 779869\n },\ + {\n \"key\": "iteite",\n \"value\": 777867\n },\ + {\n \"key\": "essess",\n \"value\": 774864\n },\ + {\n \"key\": "ashash",\n \"value\": 772862\n },\ + {\n \"key\": "redred",\n \"value\": 770860\n },\ + {\n \"key\": "dnedne",\n \"value\": 777767\n },\ + {\n \"key\": "inging",\n \"value\": 775765\n },\ + {\n \"key\": "eryery",\n \"value\": 773763\n },\ + {\n \"key\": "istist",\n \"value\": 770760\n },\ + {\n \"key\": "essess",\n \"value\": 778668\n },\ + {\n \"key\": "gesges",\n \"value\": 776666\n },\ + {\n \"key\": "odeode",\n \"value\": 773663\n },\ + {\n \"key\": "essess",\n \"value\": 771661\n },\ + {\n \"key\": "detdet",\n \"value\": 779569\n },\ + {\n \"key\": "uleule",\n \"value\": 777567\n },\ + {\n \"key\": "ousous",\n \"value\": 774564\n },\ + {\n \"key\": "hsihsi",\n \"value\": 772562\n },\ + {\n \"key\": "ishish",\n \"value\": 770560\n },\ + {\n \"key\": "esoeso",\n \"value\": 778468\n },\ + {\n \"key\": "eloelo",\n \"value\": 776466\n },\ + {\n \"key\": "outout",\n \"value\": 774464\n },\ + {\n \"key\": "ideide",\n \"value\": 771461\n },\ + {\n \"key\": "eedeed",\n \"value\": 779369\n },\ + {\n \"key\": "oidoid",\n \"value\": 777367\n },\ + {\n \"key\": "oaloal",\n \"value\": 775365\n },\ + {\n \"key\": "namnam",\n \"value\": 773363\n },\ + {\n \"key\": "inging",\n \"value\": 771361\n },\ + {\n \"key\": "inging",\n \"value\": 779269\n },\ + {\n \"key\": "upiupi",\n \"value\": 777267\n },\ + {\n \"key\": "ankank",\n \"value\": 775265\n },\ + {\n \"key\": "kedked",\n \"value\": 772262\n },\ + {\n \"key\": "iseise",\n \"value\": 770260\n },\ + {\n \"key\": "dradra",\n \"value\": 778168\n },\ + {\n \"key\": "ityity",\n \"value\": 776166\n },\ + {\n \"key\": "diadia",\n \"value\": 774164\n },\ + {\n \"key\": "essess",\n \"value\": 772162\n },\ + {\n \"key\": "areare",\n \"value\": 770160\n },\ + {\n \"key\": "ontont",\n \"value\": 778068\n },\ + {\n \"key\": "werwer",\n \"value\": 776066\n },\ + {\n \"key\": "ousous",\n \"value\": 774064\n },\ + {\n \"key\": "manman",\n \"value\": 772062\n },\ + {\n \"key\": "nutnut",\n \"value\": 771061\n },\ + {\n \"key\": "oidoid",\n \"value\": 779959\n },\ + {\n \"key\": "lahlah",\n \"value\": 777957\n },\ + {\n \"key\": "ricric",\n \"value\": 775955\n },\ + {\n \"key\": "ueruer",\n \"value\": 773953\n },\ + {\n \"key\": "naenae",\n \"value\": 771951\n },\ + {\n \"key\": "iteite",\n \"value\": 779859\n },\ + {\n \"key\": "bleble",\n \"value\": 777857\n },\ + {\n \"key\": "terter",\n \"value\": 775855\n },\ + {\n \"key\": "nicnic",\n \"value\": 773853\n },\ + {\n \"key\": "aidaid",\n \"value\": 772852\n },\ + {\n \"key\": "fulful",\n \"value\": 770850\n },\ + {\n \"key\": "essess",\n \"value\": 778758\n },\ + {\n \"key\": "iteite",\n \"value\": 776756\n },\ + {\n \"key\": "glygly",\n \"value\": 774754\n },\ + {\n \"key\": "iseise",\n \"value\": 772752\n },\ + {\n \"key\": "ityity",\n \"value\": 771751\n },\ + {\n \"key\": "essess",\n \"value\": 779659\n },\ + {\n \"key\": "ealeal",\n \"value\": 777657\n },\ + {\n \"key\": "aryary",\n \"value\": 775655\n },\ + {\n \"key\": "ronron",\n \"value\": 774654\n },\ + {\n \"key\": "etaeta",\n \"value\": 772652\n },\ + {\n \"key\": "aveave",\n \"value\": 770650\n },\ + {\n \"key\": "llylly",\n \"value\": 778558\n },\ + {\n \"key\": "iteite",\n \"value\": 777557\n },\ + {\n \"key\": "ianian",\n \"value\": 775555\n },\ + {\n \"key\": "oleole",\n \"value\": 773553\n },\ + {\n \"key\": "ithith",\n \"value\": 771551\n },\ + {\n \"key\": "aryary",\n \"value\": 770550\n },\ + {\n \"key\": "ondond",\n \"value\": 778458\n },\ + {\n \"key\": "oosoos",\n \"value\": 776456\n },\ + {\n \"key\": "hlyhly",\n \"value\": 775455\n },\ + {\n \"key\": "ncence",\n \"value\": 773453\n },\ + {\n \"key\": "eleele",\n \"value\": 771451\n },\ + {\n \"key\": "iotiot",\n \"value\": 770450\n },\ + {\n \"key\": "istist",\n \"value\": 778358\n },\ + {\n \"key\": "nesnes",\n \"value\": 777357\n },\ + {\n \"key\": "izeize",\n \"value\": 775355\n },\ + {\n \"key\": "gusgus",\n \"value\": 773353\n },\ + {\n \"key\": "laylay",\n \"value\": 772352\n },\ + {\n \"key\": "eneene",\n \"value\": 770350\n },\ + {\n \"key\": "eteete",\n \"value\": 779259\n },\ + {\n \"key\": "tictic",\n \"value\": 777257\n },\ + {\n \"key\": "fulful",\n \"value\": 775255\n },\ + {\n \"key\": "toltol",\n \"value\": 774254\n },\ + {\n \"key\": "tictic",\n \"value\": 772252\n },\ + {\n \"key\": "iveive",\n \"value\": 771251\n },\ + {\n \"key\": "manman",\n \"value\": 779159\n },\ + {\n \"key\": "bleble",\n \"value\": 778158\n },\ + {\n \"key\": "oidoid",\n \"value\": 776156\n },\ + {\n \"key\": "salsal",\n \"value\": 775155\n },\ + {\n \"key\": "kalkal",\n \"value\": 773153\n },\ + {\n \"key\": "essess",\n \"value\": 771151\n },\ + {\n \"key\": "omyomy",\n \"value\": 770150\n },\ + {\n \"key\": "oreore",\n \"value\": 778058\n },\ + {\n \"key\": "ionion",\n \"value\": 777057\n },\ + {\n \"key\": "eanean",\n \"value\": 775055\n },\ + {\n \"key\": "ellell",\n \"value\": 774054\n },\ + {\n \"key\": "daldal",\n \"value\": 773053\n },\ + {\n \"key\": "ateate",\n \"value\": 771051\n },\ + {\n \"key\": "ssesse",\n \"value\": 770050\n },\ + {\n \"key\": "deidei",\n \"value\": 778948\n },\ + {\n \"key\": "ousous",\n \"value\": 777947\n },\ + {\n \"key\": "glygly",\n \"value\": 775945\n },\ + {\n \"key\": "sitsit",\n \"value\": 774944\n },\ + {\n \"key\": "sissis",\n \"value\": 772942\n },\ + {\n \"key\": "larlar",\n \"value\": 771941\n },\ + {\n \"key\": "salsal",\n \"value\": 770940\n },\ + {\n \"key\": "herher",\n \"value\": 778848\n },\ + {\n \"key\": "tictic",\n \"value\": 777847\n },\ + {\n \"key\": "lamlam",\n \"value\": 775845\n },\ + {\n \"key\": "ionion",\n \"value\": 774844\n },\ + {\n \"key\": "lumlum",\n \"value\": 773843\n },\ + {\n \"key\": "oleole",\n \"value\": 771841\n },\ + {\n \"key\": "chmchm",\n \"value\": 770840\n },\ + {\n \"key\": "omeome",\n \"value\": 779749\n },\ + {\n \"key\": "eaeeae",\n \"value\": 777747\n },\ + {\n \"key\": "adeade",\n \"value\": 776746\n },\ + {\n \"key\": "hiohio",\n \"value\": 774744\n },\ + {\n \"key\": "lumlum",\n \"value\": 773743\n },\ + {\n \"key\": "hpahpa",\n \"value\": 772742\n },\ + {\n \"key\": "entent",\n \"value\": 770740\n },\ + {\n \"key\": "gusgus",\n \"value\": 779649\n },\ + {\n \"key\": "essess",\n \"value\": 778648\n },\ + {\n \"key\": "ityity",\n \"value\": 777647\n },\ + {\n \"key\": "ousous",\n \"value\": 775645\n },\ + {\n \"key\": "eloelo",\n \"value\": 774644\n },\ + {\n \"key\": "orkork",\n \"value\": 773643\n },\ + {\n \"key\": "otaota",\n \"value\": 771641\n },\ + {\n \"key\": "omyomy",\n \"value\": 770640\n },\ + {\n \"key\": "lislis",\n \"value\": 779549\n },\ + {\n \"key\": "teltel",\n \"value\": 777547\n },\ + {\n \"key\": "ytiyti",\n \"value\": 776546\n },\ + {\n \"key\": "noinoi",\n \"value\": 775545\n },\ + {\n \"key\": "micmic",\n \"value\": 774544\n },\ + {\n \"key\": "rerrer",\n \"value\": 772542\n },\ + {\n \"key\": "ionion",\n \"value\": 771541\n },\ + {\n \"key\": "essess",\n \"value\": 770540\n },\ + {\n \"key\": "larlar",\n \"value\": 779449\n },\ + {\n \"key\": "ionion",\n \"value\": 778448\n },\ + {\n \"key\": "nctnct",\n \"value\": 776446\n },\ + {\n \"key\": "aceace",\n \"value\": 775445\n },\ + {\n \"key\": "terter",\n \"value\": 774444\n },\ + {\n \"key\": "taltal",\n \"value\": 773443\n },\ + {\n \"key\": "hilhil",\n \"value\": 771441\n },\ + {\n \"key\": "oleole",\n \"value\": 770440\n },\ + {\n \"key\": "ileile",\n \"value\": 779349\n },\ + {\n \"key\": "inging",\n \"value\": 778348\n },\ + {\n \"key\": "omyomy",\n \"value\": 777347\n },\ + {\n \"key\": "glegle",\n \"value\": 776346\n },\ + {\n \"key\": "queque",\n \"value\": 774344\n },\ + {\n \"key\": "nainai",\n \"value\": 773343\n },\ + {\n \"key\": "buabua",\n \"value\": 772342\n },\ + {\n \"key\": "bleble",\n \"value\": 771341\n },\ + {\n \"key\": "aboabo",\n \"value\": 770340\n },\ + {\n \"key\": "looloo",\n \"value\": 779249\n },\ + {\n \"key\": "nlynly",\n \"value\": 777247\n },\ + {\n \"key\": "inging",\n \"value\": 776246\n },\ + {\n \"key\": "nahnah",\n \"value\": 775245\n },\ + {\n \"key\": "omaoma",\n \"value\": 774244\n },\ + {\n \"key\": "redred",\n \"value\": 773243\n },\ + {\n \"key\": "nalnal",\n \"value\": 772242\n },\ + {\n \"key\": "useuse",\n \"value\": 771241\n },\ + {\n \"key\": "allall",\n \"value\": 770240\n },\ + {\n \"key\": "laclac",\n \"value\": 778148\n },\ + {\n \"key\": "sumsum",\n \"value\": 777147\n },\ + {\n \"key\": "rerrer",\n \"value\": 776146\n },\ + {\n \"key\": "xisxis",\n \"value\": 775145\n },\ + {\n \"key\": "daedae",\n \"value\": 774144\n },\ + {\n \"key\": "dledle",\n \"value\": 773143\n },\ + {\n \"key\": "riaria",\n \"value\": 772142\n },\ + {\n \"key\": "ityity",\n \"value\": 771141\n },\ + {\n \"key\": "entent",\n \"value\": 770140\n },\ + {\n \"key\": "obeobe",\n \"value\": 779049\n },\ + {\n \"key\": "ierier",\n \"value\": 778048\n },\ + {\n \"key\": "oreore",\n \"value\": 777047\n },\ + {\n \"key\": "ateate",\n \"value\": 776046\n },\ + {\n \"key\": "istist",\n \"value\": 774044\n },\ + {\n \"key\": "oanoan",\n \"value\": 773043\n },\ + {\n \"key\": "intint",\n \"value\": 772042\n },\ + {\n \"key\": "sissis",\n \"value\": 771041\n },\ + {\n \"key\": "inging",\n \"value\": 770040\n },\ + {\n \"key\": "ineine",\n \"value\": 779939\n },\ + {\n \"key\": "eryery",\n \"value\": 778938\n },\ + {\n \"key\": "okooko",\n \"value\": 777937\n },\ + {\n \"key\": "ifyify",\n \"value\": 776936\n },\ + {\n \"key\": "detdet",\n \"value\": 775935\n },\ + {\n \"key\": "augaug",\n \"value\": 774934\n },\ + {\n \"key\": "essess",\n \"value\": 773933\n },\ + {\n \"key\": "ailail",\n \"value\": 772932\n },\ + {\n \"key\": "oonoon",\n \"value\": 771931\n },\ + {\n \"key\": "sissis",\n \"value\": 770930\n },\ + {\n \"key\": "neknek",\n \"value\": 779839\n },\ + {\n \"key\": "doodoo",\n \"value\": 778838\n },\ + {\n \"key\": "llylly",\n \"value\": 777837\n },\ + {\n \"key\": "icsics",\n \"value\": 776836\n },\ + {\n \"key\": "inging",\n \"value\": 775835\n },\ + {\n \"key\": "ratrat",\n \"value\": 774834\n },\ + {\n \"key\": "daldal",\n \"value\": 773833\n },\ + {\n \"key\": "andand",\n \"value\": 772832\n },\ + {\n \"key\": "odeode",\n \"value\": 772832\n },\ + {\n \"key\": "ismism",\n \"value\": 771831\n },\ + {\n \"key\": "anyany",\n \"value\": 770830\n },\ + {\n \"key\": "ageage",\n \"value\": 779739\n },\ + {\n \"key\": "essess",\n \"value\": 778738\n },\ + {\n \"key\": "bleble",\n \"value\": 777737\n },\ + {\n \"key\": "angang",\n \"value\": 776736\n },\ + {\n \"key\": "ionion",\n \"value\": 775735\n },\ + {\n \"key\": "tedted",\n \"value\": 774734\n },\ + {\n \"key\": "ifyify",\n \"value\": 773733\n },\ + {\n \"key\": "istist",\n \"value\": 772732\n },\ + {\n \"key\": "bleble",\n \"value\": 771731\n },\ + {\n \"key\": "ionion",\n \"value\": 770730\n },\ + {\n \"key\": "iveive",\n \"value\": 779639\n },\ + {\n \"key\": "noinoi",\n \"value\": 779639\n },\ + {\n \"key\": "raerae",\n \"value\": 778638\n },\ + {\n \"key\": "gedged",\n \"value\": 777637\n },\ + {\n \"key\": "nalnal",\n \"value\": 776636\n },\ + {\n \"key\": "ierier",\n \"value\": 775635\n },\ + {\n \"key\": "hidhid",\n \"value\": 774634\n },\ + {\n \"key\": "ionion",\n \"value\": 773633\n },\ + {\n \"key\": "irtirt",\n \"value\": 772632\n },\ + {\n \"key\": "glygly",\n \"value\": 771631\n },\ + {\n \"key\": "citcit",\n \"value\": 771631\n },\ + {\n \"key\": "ateate",\n \"value\": 770630\n },\ + {\n \"key\": "ikeike",\n \"value\": 779539\n },\ + {\n \"key\": "ataata",\n \"value\": 778538\n },\ + {\n \"key\": "letlet",\n \"value\": 777537\n },\ + {\n \"key\": "ialial",\n \"value\": 776536\n },\ + {\n \"key\": "sissis",\n \"value\": 775535\n },\ + {\n \"key\": "istist",\n \"value\": 774534\n },\ + {\n \"key\": "anaana",\n \"value\": 774534\n },\ + {\n \"key\": "oidoid",\n \"value\": 773533\n },\ + {\n \"key\": "ormorm",\n \"value\": 772532\n },\ + {\n \"key\": "lexlex",\n \"value\": 771531\n },\ + {\n \"key\": "llylly",\n \"value\": 770530\n },\ + {\n \"key\": "ifeife",\n \"value\": 779439\n },\ + {\n \"key\": "nalnal",\n \"value\": 779439\n },\ + {\n \"key\": "ionion",\n \"value\": 778438\n },\ + {\n \"key\": "hichic",\n \"value\": 777437\n },\ + {\n \"key\": "tootoo",\n \"value\": 776436\n },\ + {\n \"key\": "oryory",\n \"value\": 775435\n },\ + {\n \"key\": "llylly",\n \"value\": 774434\n },\ + {\n \"key\": "naenae",\n \"value\": 774434\n },\ + {\n \"key\": "izeize",\n \"value\": 773433\n },\ + {\n \"key\": "werwer",\n \"value\": 772432\n },\ + {\n \"key\": "oiloil",\n \"value\": 771431\n },\ + {\n \"key\": "luslus",\n \"value\": 770430\n },\ + {\n \"key\": "eneene",\n \"value\": 770430\n },\ + {\n \"key\": "ismism",\n \"value\": 779339\n },\ + {\n \"key\": "ricric",\n \"value\": 778338\n },\ + {\n \"key\": "iveive",\n \"value\": 777337\n },\ + {\n \"key\": "glygly",\n \"value\": 776336\n },\ + {\n \"key\": "manman",\n \"value\": 776336\n },\ + {\n \"key\": "rierie",\n \"value\": 775335\n },\ + {\n \"key\": "llylly",\n \"value\": 774334\n },\ + {\n \"key\": "ithith",\n \"value\": 773333\n },\ + {\n \"key\": "laclac",\n \"value\": 773333\n },\ + {\n \"key\": "ityity",\n \"value\": 772332\n },\ + {\n \"key\": "rezrez",\n \"value\": 771331\n },\ + {\n \"key\": "enyeny",\n \"value\": 770330\n },\ + {\n \"key\": "iedied",\n \"value\": 770330\n },\ + {\n \"key\": "rgerge",\n \"value\": 779239\n },\ + {\n \"key\": "wedwed",\n \"value\": 778238\n },\ + {\n \"key\": "iorior",\n \"value\": 777237\n },\ + {\n \"key\": "ousous",\n \"value\": 777237\n },\ + {\n \"key\": "ricric",\n \"value\": 776236\n },\ + {\n \"key\": "iumium",\n \"value\": 775235\n },\ + {\n \"key\": "neanea",\n \"value\": 774234\n },\ + {\n \"key\": "ionion",\n \"value\": 774234\n },\ + {\n \"key\": "ateate",\n \"value\": 773233\n },\ + {\n \"key\": "ateate",\n \"value\": 772232\n },\ + {\n \"key\": "ismism",\n \"value\": 771231\n },\ + {\n \"key\": "karkar",\n \"value\": 771231\n },\ + {\n \"key\": "essess",\n \"value\": 770230\n },\ + {\n \"key\": "oseose",\n \"value\": 779139\n },\ + {\n \"key\": "siasia",\n \"value\": 778138\n },\ + {\n \"key\": "aryary",\n \"value\": 778138\n },\ + {\n \"key\": "iteite",\n \"value\": 777137\n },\ + {\n \"key\": "bleble",\n \"value\": 776136\n },\ + {\n \"key\": "tustus",\n \"value\": 776136\n },\ + {\n \"key\": "iteite",\n \"value\": 775135\n },\ + {\n \"key\": "ikeike",\n \"value\": 774134\n },\ + {\n \"key\": "berber",\n \"value\": 773133\n },\ + {\n \"key\": "ismism",\n \"value\": 773133\n },\ + {\n \"key\": "rigrig",\n \"value\": 772132\n },\ + {\n \"key\": "yreyre",\n \"value\": 771131\n },\ + {\n \"key\": "ismism",\n \"value\": 771131\n },\ + {\n \"key\": "ismism",\n \"value\": 770130\n },\ + {\n \"key\": "oodood",\n \"value\": 779039\n },\ + {\n \"key\": "amaama",\n \"value\": 779039\n },\ + {\n \"key\": "sissis",\n \"value\": 778038\n },\ + {\n \"key\": "ftyfty",\n \"value\": 777037\n },\ + {\n \"key\": "onyony",\n \"value\": 777037\n },\ + {\n \"key\": "ismism",\n \"value\": 776036\n },\ + {\n \"key\": "iumium",\n \"value\": 775035\n },\ + {\n \"key\": "euseus",\n \"value\": 775035\n },\ + {\n \"key\": "bleble",\n \"value\": 774034\n },\ + {\n \"key\": "istist",\n \"value\": 773033\n },\ + {\n \"key\": "bowbow",\n \"value\": 773033\n },\ + {\n \"key\": "lielie",\n \"value\": 772032\n },\ + {\n \"key\": "ursurs",\n \"value\": 771031\n },\ + {\n \"key\": "hsuhsu",\n \"value\": 771031\n },\ + {\n \"key\": "imiimi",\n \"value\": 770030\n },\ + {\n \"key\": "dgedge",\n \"value\": 779929\n },\ + {\n \"key\": "laglag",\n \"value\": 779929\n },\ + {\n \"key\": "ionion",\n \"value\": 778928\n },\ + {\n \"key\": "fulful",\n \"value\": 777927\n },\ + {\n \"key\": "uedued",\n \"value\": 777927\n },\ + {\n \"key\": "angang",\n \"value\": 776926\n },\ + {\n \"key\": "ertert",\n \"value\": 775925\n },\ + {\n \"key\": "bleble",\n \"value\": 775925\n },\ + {\n \"key\": "tibtib",\n \"value\": 774924\n },\ + {\n \"key\": "iteite",\n \"value\": 773923\n },\ + {\n \"key\": "inging",\n \"value\": 773923\n },\ + {\n \"key\": "ionion",\n \"value\": 772922\n },\ + {\n \"key\": "ngsngs",\n \"value\": 772922\n },\ + {\n \"key\": "ralral",\n \"value\": 771921\n },\ + {\n \"key\": "dlydly",\n \"value\": 770920\n },\ + {\n \"key\": "nerner",\n \"value\": 770920\n },\ + {\n \"key\": "iveive",\n \"value\": 779829\n },\ + {\n \"key\": "istist",\n \"value\": 778828\n },\ + {\n \"key\": "piapia",\n \"value\": 778828\n },\ + {\n \"key\": "ncyncy",\n \"value\": 777827\n },\ + {\n \"key\": "geegee",\n \"value\": 777827\n },\ + {\n \"key\": "tictic",\n \"value\": 776826\n },\ + {\n \"key\": "bitbit",\n \"value\": 775825\n },\ + {\n \"key\": "larlar",\n \"value\": 775825\n },\ + {\n \"key\": "tedted",\n \"value\": 774824\n },\ + {\n \"key\": "ineine",\n \"value\": 774824\n },\ + {\n \"key\": "ateate",\n \"value\": 773823\n },\ + {\n \"key\": "essess",\n \"value\": 772822\n },\ + {\n \"key\": "rdsrds",\n \"value\": 772822\n },\ + {\n \"key\": "laplap",\n \"value\": 771821\n },\ + {\n \"key\": "essess",\n \"value\": 771821\n },\ + {\n \"key\": "siasia",\n \"value\": 770820\n },\ + {\n \"key\": "ousous",\n \"value\": 779729\n },\ + {\n \"key\": "inging",\n \"value\": 779729\n },\ + {\n \"key\": "pirpir",\n \"value\": 778728\n },\ + {\n \"key\": "dlydly",\n \"value\": 778728\n },\ + {\n \"key\": "liclic",\n \"value\": 777727\n },\ + {\n \"key\": "cuscus",\n \"value\": 777727\n },\ + {\n \"key\": "essess",\n \"value\": 776726\n },\ + {\n \"key\": "glygly",\n \"value\": 775725\n },\ + {\n \"key\": "ainain",\n \"value\": 775725\n },\ + {\n \"key\": "etyety",\n \"value\": 774724\n },\ + {\n \"key\": "yllyll",\n \"value\": 774724\n },\ + {\n \"key\": "nusnus",\n \"value\": 773723\n },\ + {\n \"key\": "iidiid",\n \"value\": 773723\n },\ + {\n \"key\": "yonyon",\n \"value\": 772722\n },\ + {\n \"key\": "miamia",\n \"value\": 771721\n },\ + {\n \"key\": "domdom",\n \"value\": 771721\n },\ + {\n \"key\": "ineine",\n \"value\": 770720\n },\ + {\n \"key\": "ayoayo",\n \"value\": 770720\n },\ + {\n \"key\": "essess",\n \"value\": 779629\n },\ + {\n \"key\": "ionion",\n \"value\": 779629\n },\ + {\n \"key\": "aftaft",\n \"value\": 778628\n },\ + {\n \"key\": "tchtch",\n \"value\": 778628\n },\ + {\n \"key\": "rowrow",\n \"value\": 777627\n },\ + {\n \"key\": "euseus",\n \"value\": 776626\n },\ + {\n \"key\": "bleble",\n \"value\": 776626\n },\ + {\n \"key\": "manman",\n \"value\": 775625\n },\ + {\n \"key\": "ianian",\n \"value\": 775625\n },\ + {\n \"key\": "tlytly",\n \"value\": 774624\n },\ + {\n \"key\": "opeope",\n \"value\": 774624\n },\ + {\n \"key\": "parpar",\n \"value\": 773623\n },\ + {\n \"key\": "rumrum",\n \"value\": 773623\n },\ + {\n \"key\": "essess",\n \"value\": 772622\n },\ + {\n \"key\": "hinhin",\n \"value\": 772622\n },\ + {\n \"key\": "istist",\n \"value\": 771621\n },\ + {\n \"key\": "denden",\n \"value\": 771621\n },\ + {\n \"key\": "ualual",\n \"value\": 770620\n },\ + {\n \"key\": "tiatia",\n \"value\": 779529\n },\ + {\n \"key\": "sissis",\n \"value\": 779529\n },\ + {\n \"key\": "slysly",\n \"value\": 778528\n },\ + {\n \"key\": "ameame",\n \"value\": 778528\n },\ + {\n \"key\": "ismism",\n \"value\": 777527\n },\ + {\n \"key\": "ialial",\n \"value\": 777527\n },\ + {\n \"key\": "nerner",\n \"value\": 776526\n },\ + {\n \"key\": "ifyify",\n \"value\": 776526\n },\ + {\n \"key\": "ismism",\n \"value\": 775525\n },\ + {\n \"key\": "legleg",\n \"value\": 775525\n },\ + {\n \"key\": "calcal",\n \"value\": 774524\n },\ + {\n \"key\": "oadoad",\n \"value\": 774524\n },\ + {\n \"key\": "iveive",\n \"value\": 773523\n },\ + {\n \"key\": "micmic",\n \"value\": 773523\n },\ + {\n \"key\": "chychy",\n \"value\": 772522\n },\ + {\n \"key\": "daldal",\n \"value\": 772522\n },\ + {\n \"key\": "ityity",\n \"value\": 771521\n },\ + {\n \"key\": "iadiad",\n \"value\": 771521\n },\ + {\n \"key\": "liclic",\n \"value\": 770520\n },\ + {\n \"key\": "ionion",\n \"value\": 770520\n },\ + {\n \"key\": "micmic",\n \"value\": 779429\n },\ + {\n \"key\": "sissis",\n \"value\": 779429\n },\ + {\n \"key\": "rserse",\n \"value\": 778428\n },\ + {\n \"key\": "iteite",\n \"value\": 778428\n },\ + {\n \"key\": "izeize",\n \"value\": 777427\n },\ + {\n \"key\": "iumium",\n \"value\": 777427\n },\ + {\n \"key\": "panpan",\n \"value\": 776426\n },\ + {\n \"key\": "glygly",\n \"value\": 776426\n },\ + {\n \"key\": "etaeta",\n \"value\": 775425\n },\ + {\n \"key\": "ssesse",\n \"value\": 775425\n },\ + {\n \"key\": "narnar",\n \"value\": 775425\n },\ + {\n \"key\": "setset",\n \"value\": 774424\n },\ + {\n \"key\": "tedted",\n \"value\": 774424\n },\ + {\n \"key\": "oidoid",\n \"value\": 773423\n },\ + {\n \"key\": "ineine",\n \"value\": 773423\n },\ + {\n \"key\": "nedned",\n \"value\": 772422\n },\ + {\n \"key\": "eadead",\n \"value\": 772422\n },\ + {\n \"key\": "ousous",\n \"value\": 771421\n },\ + {\n \"key\": "slysly",\n \"value\": 771421\n },\ + {\n \"key\": "enieni",\n \"value\": 770420\n },\ + {\n \"key\": "essess",\n \"value\": 770420\n },\ + {\n \"key\": "terter",\n \"value\": 779329\n },\ + {\n \"key\": "ntynty",\n \"value\": 779329\n },\ + {\n \"key\": "sinsin",\n \"value\": 778328\n },\ + {\n \"key\": "ismism",\n \"value\": 778328\n },\ + {\n \"key\": "ousous",\n \"value\": 778328\n },\ + {\n \"key\": "aryary",\n \"value\": 777327\n },\ + {\n \"key\": "numnum",\n \"value\": 777327\n },\ + {\n \"key\": "tlytly",\n \"value\": 776326\n },\ + {\n \"key\": "calcal",\n \"value\": 776326\n },\ + {\n \"key\": "slysly",\n \"value\": 775325\n },\ + {\n \"key\": "trytry",\n \"value\": 775325\n },\ + {\n \"key\": "ailail",\n \"value\": 774324\n },\ + {\n \"key\": "nicnic",\n \"value\": 774324\n },\ + {\n \"key\": "ionion",\n \"value\": 773323\n },\ + {\n \"key\": "serser",\n \"value\": 773323\n },\ + {\n \"key\": "essess",\n \"value\": 773323\n },\ + {\n \"key\": "tistis",\n \"value\": 772322\n },\ + {\n \"key\": "otlotl",\n \"value\": 772322\n },\ + {\n \"key\": "ousous",\n \"value\": 771321\n },\ + {\n \"key\": "dehdeh",\n \"value\": 771321\n },\ + {\n \"key\": "essess",\n \"value\": 770320\n },\ + {\n \"key\": "llylly",\n \"value\": 770320\n },\ + {\n \"key\": "evievi",\n \"value\": 770320\n },\ + {\n \"key\": "iteite",\n \"value\": 779229\n },\ + {\n \"key\": "rnerne",\n \"value\": 779229\n },\ + {\n \"key\": "oleole",\n \"value\": 778228\n },\ + {\n \"key\": "oryory",\n \"value\": 778228\n },\ + {\n \"key\": "ionion",\n \"value\": 777227\n },\ + {\n \"key\": "eteete",\n \"value\": 777227\n },\ + {\n \"key\": "ismism",\n \"value\": 777227\n },\ + {\n \"key\": "oidoid",\n \"value\": 776226\n },\ + {\n \"key\": "ismism",\n \"value\": 776226\n },\ + {\n \"key\": "ahtaht",\n \"value\": 775225\n },\ + {\n \"key\": "ousous",\n \"value\": 775225\n },\ + {\n \"key\": "daedae",\n \"value\": 774224\n },\ + {\n \"key\": "nrenre",\n \"value\": 774224\n },\ + {\n \"key\": "daldal",\n \"value\": 774224\n },\ + {\n \"key\": "ngsngs",\n \"value\": 773223\n },\ + {\n \"key\": "zinzin",\n \"value\": 773223\n },\ + {\n \"key\": "tistis",\n \"value\": 772222\n },\ + {\n \"key\": "ikeike",\n \"value\": 772222\n },\ + {\n \"key\": "ithith",\n \"value\": 772222\n },\ + {\n \"key\": "fulful",\n \"value\": 771221\n },\ + {\n \"key\": "evievi",\n \"value\": 771221\n },\ + {\n \"key\": "earear",\n \"value\": 770220\n },\ + {\n \"key\": "aftaft",\n \"value\": 770220\n },\ + {\n \"key\": "eereer",\n \"value\": 770220\n },\ + {\n \"key\": "ousous",\n \"value\": 779129\n },\ + {\n \"key\": "aphaph",\n \"value\": 779129\n },\ + {\n \"key\": "iteite",\n \"value\": 778128\n },\ + {\n \"key\": "gerger",\n \"value\": 778128\n },\ + {\n \"key\": "llylly",\n \"value\": 778128\n },\ + {\n \"key\": "oodood",\n \"value\": 777127\n },\ + {\n \"key\": "araara",\n \"value\": 777127\n },\ + {\n \"key\": "suosuo",\n \"value\": 776126\n },\ + {\n \"key\": "ionion",\n \"value\": 776126\n },\ + {\n \"key\": "ishish",\n \"value\": 776126\n },\ + {\n \"key\": "ynyyny",\n \"value\": 775125\n },\ + {\n \"key\": "akeake",\n \"value\": 775125\n },\ + {\n \"key\": "rawraw",\n \"value\": 774124\n },\ + {\n \"key\": "fidfid",\n \"value\": 774124\n },\ + {\n \"key\": "slysly",\n \"value\": 774124\n },\ + {\n \"key\": "ngyngy",\n \"value\": 773123\n },\ + {\n \"key\": "iteite",\n \"value\": 773123\n },\ + {\n \"key\": "hichic",\n \"value\": 772122\n },\ + {\n \"key\": "warwar",\n \"value\": 772122\n },\ + {\n \"key\": "eziezi",\n \"value\": 772122\n },\ + {\n \"key\": "sissis",\n \"value\": 771121\n },\ + {\n \"key\": "aryary",\n \"value\": 771121\n },\ + {\n \"key\": "trytry",\n \"value\": 771121\n },\ + {\n \"key\": "eltelt",\n \"value\": 770120\n },\ + {\n \"key\": "yteyte",\n \"value\": 770120\n },\ + {\n \"key\": "tictic",\n \"value\": 779029\n },\ + {\n \"key\": "testes",\n \"value\": 779029\n },\ + {\n \"key\": "terter",\n \"value\": 779029\n },\ + {\n \"key\": "antant",\n \"value\": 778028\n },\ + {\n \"key\": "bleble",\n \"value\": 778028\n },\ + {\n \"key\": "ikeike",\n \"value\": 778028\n },\ + {\n \"key\": "ionion",\n \"value\": 777027\n },\ + {\n \"key\": "ycnycn",\n \"value\": 777027\n },\ + {\n \"key\": "ermerm",\n \"value\": 776026\n },\ + {\n \"key\": "istist",\n \"value\": 776026\n },\ + {\n \"key\": "rryrry",\n \"value\": 776026\n },\ + {\n \"key\": "nicnic",\n \"value\": 775025\n },\ + {\n \"key\": "dibdib",\n \"value\": 775025\n },\ + {\n \"key\": "yroyro",\n \"value\": 775025\n },\ + {\n \"key\": "kerker",\n \"value\": 774024\n },\ + {\n \"key\": "zenzen",\n \"value\": 774024\n },\ + {\n \"key\": "llylly",\n \"value\": 774024\n },\ + {\n \"key\": "essess",\n \"value\": 773023\n },\ + {\n \"key\": "iteite",\n \"value\": 773023\n },\ + {\n \"key\": "eraera",\n \"value\": 773023\n },\ + {\n \"key\": "oneone",\n \"value\": 772022\n },\ + {\n \"key\": "saesae",\n \"value\": 772022\n },\ + {\n \"key\": "tortor",\n \"value\": 771021\n },\ + {\n \"key\": "testes",\n \"value\": 771021\n },\ + {\n \"key\": "istist",\n \"value\": 771021\n },\ + {\n \"key\": "tictic",\n \"value\": 770020\n },\ + {\n \"key\": "liclic",\n \"value\": 770020\n },\ + {\n \"key\": "trytry",\n \"value\": 770020\n },\ + {\n \"key\": "ionion",\n \"value\": 779919\n },\ + {\n \"key\": "aosaos",\n \"value\": 779919\n },\ + {\n \"key\": "areare",\n \"value\": 779919\n },\ + {\n \"key\": "ycayca",\n \"value\": 778918\n },\ + {\n \"key\": "dahdah",\n \"value\": 778918\n },\ + {\n \"key\": "eanean",\n \"value\": 778918\n },\ + {\n \"key\": "uleule",\n \"value\": 777917\n },\ + {\n \"key\": "ifyify",\n \"value\": 777917\n },\ + {\n \"key\": "ialial",\n \"value\": 777917\n },\ + {\n \"key\": "ionion",\n \"value\": 776916\n },\ + {\n \"key\": "ronron",\n \"value\": 776916\n },\ + {\n \"key\": "ormorm",\n \"value\": 776916\n },\ + {\n \"key\": "lonlon",\n \"value\": 775915\n },\ + {\n \"key\": "nalnal",\n \"value\": 775915\n },\ + {\n \"key\": "doldol",\n \"value\": 775915\n },\ + {\n \"key\": "arkark",\n \"value\": 774914\n },\ + {\n \"key\": "nirnir",\n \"value\": 774914\n },\ + {\n \"key\": "tumtum",\n \"value\": 774914\n },\ + {\n \"key\": "ineine",\n \"value\": 773913\n },\ + {\n \"key\": "loyloy",\n \"value\": 773913\n },\ + {\n \"key\": "tnetne",\n \"value\": 773913\n },\ + {\n \"key\": "rborbo",\n \"value\": 772912\n },\ + {\n \"key\": "ismism",\n \"value\": 772912\n },\ + {\n \"key\": "ineine",\n \"value\": 772912\n },\ + {\n \"key\": "llylly",\n \"value\": 771911\n },\ + {\n \"key\": "tidtid",\n \"value\": 771911\n },\ + {\n \"key\": "inging",\n \"value\": 771911\n },\ + {\n \"key\": "gnigni",\n \"value\": 770910\n },\ + {\n \"key\": "naenae",\n \"value\": 770910\n },\ + {\n \"key\": "ncence",\n \"value\": 770910\n },\ + {\n \"key\": "ikeike",\n \"value\": 779819\n },\ + {\n \"key\": "pedped",\n \"value\": 779819\n },\ + {\n \"key\": "napnap",\n \"value\": 779819\n },\ + {\n \"key\": "renren",\n \"value\": 778818\n },\ + {\n \"key\": "dedded",\n \"value\": 778818\n },\ + {\n \"key\": "redred",\n \"value\": 778818\n },\ + {\n \"key\": "yltylt",\n \"value\": 777817\n },\ + {\n \"key\": "ylgylg",\n \"value\": 777817\n },\ + {\n \"key\": "oseose",\n \"value\": 777817\n },\ + {\n \"key\": "ytiyti",\n \"value\": 777817\n },\ + {\n \"key\": "etaeta",\n \"value\": 776816\n },\ + {\n \"key\": "oluolu",\n \"value\": 776816\n },\ + {\n \"key\": "ncence",\n \"value\": 776816\n },\ + {\n \"key\": "riaria",\n \"value\": 775815\n },\ + {\n \"key\": "uloulo",\n \"value\": 775815\n },\ + {\n \"key\": "ionion",\n \"value\": 775815\n },\ + {\n \"key\": "llylly",\n \"value\": 774814\n },\ + {\n \"key\": "ninnin",\n \"value\": 774814\n },\ + {\n \"key\": "ughugh",\n \"value\": 774814\n },\ + {\n \"key\": "iveive",\n \"value\": 773813\n },\ + {\n \"key\": "daedae",\n \"value\": 773813\n },\ + {\n \"key\": "bleble",\n \"value\": 773813\n },\ + {\n \"key\": "entent",\n \"value\": 773813\n },\ + {\n \"key\": "budbud",\n \"value\": 772812\n },\ + {\n \"key\": "ledled",\n \"value\": 772812\n },\ + {\n \"key\": "rowrow",\n \"value\": 772812\n },\ + {\n \"key\": "oofoof",\n \"value\": 771811\n },\ + {\n \"key\": "eiteit",\n \"value\": 771811\n },\ + {\n \"key\": "hedhed",\n \"value\": 771811\n },\ + {\n \"key\": "eadead",\n \"value\": 770810\n },\ + {\n \"key\": "ghtght",\n \"value\": 770810\n },\ + {\n \"key\": "ncence",\n \"value\": 770810\n },\ + {\n \"key\": "bleble",\n \"value\": 770810\n },\ + {\n \"key\": "ralral",\n \"value\": 779719\n },\ + {\n \"key\": "entent",\n \"value\": 779719\n },\ + {\n \"key\": "ionion",\n \"value\": 779719\n },\ + {\n \"key\": "hlyhly",\n \"value\": 778718\n },\ + {\n \"key\": "dledle",\n \"value\": 778718\n },\ + {\n \"key\": "oidoid",\n \"value\": 778718\n },\ + {\n \"key\": "ousous",\n \"value\": 778718\n },\ + {\n \"key\": "ineine",\n \"value\": 777717\n },\ + {\n \"key\": "ianian",\n \"value\": 777717\n },\ + {\n \"key\": "gicgic",\n \"value\": 777717\n },\ + {\n \"key\": "mbombo",\n \"value\": 776716\n },\ + {\n \"key\": "tictic",\n \"value\": 776716\n },\ + {\n \"key\": "antant",\n \"value\": 776716\n },\ + {\n \"key\": "nwonwo",\n \"value\": 775715\n },\ + {\n \"key\": "ionion",\n \"value\": 775715\n },\ + {\n \"key\": "inging",\n \"value\": 775715\n },\ + {\n \"key\": "arkark",\n \"value\": 775715\n },\ + {\n \"key\": "nicnic",\n \"value\": 774714\n },\ + {\n \"key\": "ityity",\n \"value\": 774714\n },\ + {\n \"key\": "iveive",\n \"value\": 774714\n },\ + {\n \"key\": "testes",\n \"value\": 774714\n },\ + {\n \"key\": "llylly",\n \"value\": 773713\n },\ + {\n \"key\": "sissis",\n \"value\": 773713\n },\ + {\n \"key\": "ateate",\n \"value\": 773713\n },\ + {\n \"key\": "ledled",\n \"value\": 772712\n },\ + {\n \"key\": "niuniu",\n \"value\": 772712\n },\ + {\n \"key\": "linlin",\n \"value\": 772712\n },\ + {\n \"key\": "omyomy",\n \"value\": 772712\n },\ + {\n \"key\": "nannan",\n \"value\": 771711\n },\ + {\n \"key\": "abeabe",\n \"value\": 771711\n },\ + {\n \"key\": "ssesse",\n \"value\": 771711\n },\ + {\n \"key\": "hlyhly",\n \"value\": 770710\n },\ + {\n \"key\": "llalla",\n \"value\": 770710\n },\ + {\n \"key\": "kinkin",\n \"value\": 770710\n },\ + {\n \"key\": "essess",\n \"value\": 770710\n },\ + {\n \"key\": "essess",\n \"value\": 779619\n },\ + {\n \"key\": "itoito",\n \"value\": 779619\n },\ + {\n \"key\": "entent",\n \"value\": 779619\n },\ + {\n \"key\": "oidoid",\n \"value\": 779619\n },\ + {\n \"key\": "gerger",\n \"value\": 778618\n },\ + {\n \"key\": "moomoo",\n \"value\": 778618\n },\ + {\n \"key\": "ogyogy",\n \"value\": 778618\n },\ + {\n \"key\": "iseise",\n \"value\": 778618\n },\ + {\n \"key\": "ichich",\n \"value\": 777617\n },\ + {\n \"key\": "nedned",\n \"value\": 777617\n },\ + {\n \"key\": "bleble",\n \"value\": 777617\n },\ + {\n \"key\": "tictic",\n \"value\": 777617\n },\ + {\n \"key\": "izeize",\n \"value\": 776616\n },\ + {\n \"key\": "oxyoxy",\n \"value\": 776616\n },\ + {\n \"key\": "daldal",\n \"value\": 776616\n },\ + {\n \"key\": "carcar",\n \"value\": 775615\n },\ + {\n \"key\": "entent",\n \"value\": 775615\n },\ + {\n \"key\": "lezlez",\n \"value\": 775615\n },\ + {\n \"key\": "ikeike",\n \"value\": 775615\n },\ + {\n \"key\": "noinoi",\n \"value\": 774614\n },\ + {\n \"key\": "oftoft",\n \"value\": 774614\n },\ + {\n \"key\": "larlar",\n \"value\": 774614\n },\ + {\n \"key\": "aicaic",\n \"value\": 774614\n },\ + {\n \"key\": "nzonzo",\n \"value\": 773613\n },\ + {\n \"key\": "ianian",\n \"value\": 773613\n },\ + {\n \"key\": "hlyhly",\n \"value\": 773613\n },\ + {\n \"key\": "manman",\n \"value\": 773613\n },\ + {\n \"key\": "iteite",\n \"value\": 772612\n },\ + {\n \"key\": "eryery",\n \"value\": 772612\n },\ + {\n \"key\": "ttotto",\n \"value\": 772612\n },\ + {\n \"key\": "nylnyl",\n \"value\": 772612\n },\ + {\n \"key\": "ariari",\n \"value\": 771611\n },\ + {\n \"key\": "ssesse",\n \"value\": 771611\n },\ + {\n \"key\": "warwar",\n \"value\": 771611\n },\ + {\n \"key\": "ousous",\n \"value\": 771611\n },\ + {\n \"key\": "oreore",\n \"value\": 770610\n },\ + {\n \"key\": "ionion",\n \"value\": 770610\n },\ + {\n \"key\": "nornor",\n \"value\": 770610\n },\ + {\n \"key\": "niania",\n \"value\": 770610\n },\ + {\n \"key\": "niania",\n \"value\": 779519\n },\ + {\n \"key\": "boxbox",\n \"value\": 779519\n },\ + {\n \"key\": "aabaab",\n \"value\": 779519\n },\ + {\n \"key\": "miamia",\n \"value\": 779519\n },\ + {\n \"key\": "untunt",\n \"value\": 778518\n },\ + {\n \"key\": "ogyogy",\n \"value\": 778518\n },\ + {\n \"key\": "ousous",\n \"value\": 778518\n },\ + {\n \"key\": "ialial",\n \"value\": 778518\n },\ + {\n \"key\": "lialia",\n \"value\": 777517\n },\ + {\n \"key\": "etyety",\n \"value\": 777517\n },\ + {\n \"key\": "ionion",\n \"value\": 777517\n },\ + {\n \"key\": "ionion",\n \"value\": 777517\n },\ + {\n \"key\": "eateat",\n \"value\": 777517\n },\ + {\n \"key\": "bitbit",\n \"value\": 776516\n },\ + {\n \"key\": "ishish",\n \"value\": 776516\n },\ + {\n \"key\": "calcal",\n \"value\": 776516\n },\ + {\n \"key\": "ikeike",\n \"value\": 776516\n },\ + {\n \"key\": "cincin",\n \"value\": 775515\n },\ + {\n \"key\": "niknik",\n \"value\": 775515\n },\ + {\n \"key\": "oneone",\n \"value\": 775515\n },\ + {\n \"key\": "roiroi",\n \"value\": 775515\n },\ + {\n \"key\": "ricric",\n \"value\": 774514\n },\ + {\n \"key\": "ideide",\n \"value\": 774514\n },\ + {\n \"key\": "nrynry",\n \"value\": 774514\n },\ + {\n \"key\": "roiroi",\n \"value\": 775515\n },\ + {\n \"key\": "ricric",\n \"value\": 774514\n },\ + {\n \"key\": "ideide",\n \"value\": 774514\n },\ + {\n \"key\": "nrynry",\n \"value\": 774514\n },\ + {\n \"key\": "lialia",\n \"value\": 777517\n },\ + {\n \"key\": "etyety",\n \"value\": 777517\n },\ + {\n \"key\": "ionion",\n \"value\": 777517\n },\ + {\n \"key\": "ionion",\n \"value\": 777517\n },\ + {\n \"key\": "eateat",\n \"value\": 777517\n },\ + {\n \"key\": "bitbit",\n \"value\": 776516\n },\ + {\n \"key\": "ishish",\n \"value\": 776516\n },\ + {\n \"key\": "calcal",\n \"value\": 776516\n },\ + {\n \"key\": "ikeike",\n \"value\": 776516\n },\ + {\n \"key\": "cincin",\n \"value\": 775515\n },\ + {\n \"key\": "niknik",\n \"value\": 775515\n },\ + {\n \"key\": "oneone",\n \"value\": 775515\n },\ + {\n \"key\": "roiroi",\n \"value\": 775515\n },\ + {\n \"key\": "ricric",\n \"value\": 774514\n },\ + {\n \"key\": "ideide",\n \"value\": 774514\n },\ + {\n \"key\": "nrynry",\n \"value\": 774514\n },\ + {\n \"key\": "roiroi",\n \"value\": 775515\n },\ + {\n \"key\": "ricric",\n \"value\": 774514\n },\ + {\n \"key\": "ideide",\n \"value\": 774514\n },\ + {\n \"key\": "nrynry",\n \"value\": 774514\n },\ + {\n \"key\": "ralral",\n \"value\": 779049\n }]'; + +kvJSON.frob(); diff --git a/deps/v8/test/mjsunit/harmony/array-concat.js b/deps/v8/test/mjsunit/harmony/array-concat.js index c1ff92c8c3..71b6790bc7 100644 --- a/deps/v8/test/mjsunit/harmony/array-concat.js +++ b/deps/v8/test/mjsunit/harmony/array-concat.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-arrays --harmony-classes +// Flags: --harmony-concat-spreadable (function testArrayConcatArity() { "use strict"; @@ -194,6 +194,15 @@ assertThrows(function() { (function testConcatArraySubclass() { "use strict"; + // If @@isConcatSpreadable is not used, the value of IsArray(O) + // is used to determine the spreadable property. + class A extends Array {} + var obj = [].concat(new A(1, 2, 3), new A(4, 5, 6), new A(7, 8, 9)); + assertEquals(9, obj.length); + for (var i = 0; i < obj.length; ++i) { + assertEquals(i + 1, obj[i]); + } + // TODO(caitp): when concat is called on instances of classes which extend // Array, they should: // @@ -203,6 +212,19 @@ assertThrows(function() { })(); +(function testConcatArraySubclassOptOut() { + "use strict"; + class A extends Array { + get [Symbol.isConcatSpreadable]() { return false; } + } + var obj = [].concat(new A(1, 2, 3), new A(4, 5, 6), new A(7, 8, 9)); + assertEquals(3, obj.length); + assertEquals(3, obj[0].length); + assertEquals(3, obj[1].length); + assertEquals(3, obj[2].length); +})(); + + (function testConcatNonArray() { "use strict"; class NonArray { diff --git a/deps/v8/test/mjsunit/harmony/array-find.js b/deps/v8/test/mjsunit/harmony/array-find.js index eb32082277..44fc78292a 100644 --- a/deps/v8/test/mjsunit/harmony/array-find.js +++ b/deps/v8/test/mjsunit/harmony/array-find.js @@ -201,7 +201,7 @@ assertEquals(22, a.find(function(val) { return 22 === val; }), undefined); // -// Test predicate is only called for existing elements +// Test predicate is called for holes // (function() { var a = new Array(30); @@ -211,7 +211,27 @@ assertEquals(22, a.find(function(val) { return 22 === val; }), undefined); var count = 0; a.find(function() { count++; return false; }); - assertEquals(3, count); + assertEquals(30, count); +})(); + + +(function() { + var a = [0, 1, , 3]; + var count = 0; + var found = a.find(function(val) { return val === undefined; }); + assertEquals(undefined, found); +})(); + + +(function() { + var a = [0, 1, , 3]; + a.__proto__ = { + __proto__: Array.prototype, + 2: 42, + }; + var count = 0; + var found = a.find(function(val) { return val === 42; }); + assertEquals(42, found); })(); diff --git a/deps/v8/test/mjsunit/harmony/array-findindex.js b/deps/v8/test/mjsunit/harmony/array-findindex.js index a5df05a05c..7068a9cb40 100644 --- a/deps/v8/test/mjsunit/harmony/array-findindex.js +++ b/deps/v8/test/mjsunit/harmony/array-findindex.js @@ -201,7 +201,7 @@ assertEquals(3, a.findIndex(function(val) { return 24 === val; })); // -// Test predicate is only called for existing elements +// Test predicate is called for holes // (function() { var a = new Array(30); @@ -211,7 +211,27 @@ assertEquals(3, a.findIndex(function(val) { return 24 === val; })); var count = 0; a.findIndex(function() { count++; return false; }); - assertEquals(3, count); + assertEquals(30, count); +})(); + + +(function() { + var a = [0, 1, , 3]; + var count = 0; + var index = a.findIndex(function(val) { return val === undefined; }); + assertEquals(2, index); +})(); + + +(function() { + var a = [0, 1, , 3]; + a.__proto__ = { + __proto__: Array.prototype, + 2: 42, + }; + var count = 0; + var index = a.findIndex(function(val) { return val === 42; }); + assertEquals(2, index); })(); diff --git a/deps/v8/test/mjsunit/harmony/array-from.js b/deps/v8/test/mjsunit/harmony/array-from.js index c294786c46..2b7f2902f8 100644 --- a/deps/v8/test/mjsunit/harmony/array-from.js +++ b/deps/v8/test/mjsunit/harmony/array-from.js @@ -148,4 +148,32 @@ testArrayFrom(Math.cos, Array); testArrayFrom(Math.cos.bind(Math), Array); testArrayFrom(boundFn, boundFn); +// Assert that [[DefineOwnProperty]] is used in ArrayFrom, meaning a +// setter isn't called, and a failed [[DefineOwnProperty]] will throw. +var setterCalled = 0; +function exotic() { + Object.defineProperty(this, '0', { + get: function() { return 2; }, + set: function() { setterCalled++; } + }); +} +// Non-configurable properties can't be overwritten with DefineOwnProperty +assertThrows(function () { Array.from.call(exotic, [1]); }, TypeError); +// The setter wasn't called +assertEquals(0, setterCalled); + +// Check that array properties defined are writable, enumerable, configurable +function ordinary() { } +var x = Array.from.call(ordinary, [2]); +var xlength = Object.getOwnPropertyDescriptor(x, 'length'); +assertEquals(1, xlength.value); +assertEquals(true, xlength.writable); +assertEquals(true, xlength.enumerable); +assertEquals(true, xlength.configurable); +var x0 = Object.getOwnPropertyDescriptor(x, 0); +assertEquals(2, x0.value); +assertEquals(true, xlength.writable); +assertEquals(true, xlength.enumerable); +assertEquals(true, xlength.configurable); + })(); diff --git a/deps/v8/test/mjsunit/harmony/array-of.js b/deps/v8/test/mjsunit/harmony/array-of.js index adf7cb547c..7fd5eeaf61 100644 --- a/deps/v8/test/mjsunit/harmony/array-of.js +++ b/deps/v8/test/mjsunit/harmony/array-of.js @@ -182,3 +182,33 @@ assertThrows(function() { new Array.of() }, TypeError); // not a constructor assertEquals(instance instanceof boundFn, true); assertEquals(Array.isArray(instance), false); })(); + +(function testDefinesOwnProperty() { + // Assert that [[DefineOwnProperty]] is used in ArrayFrom, meaning a + // setter isn't called, and a failed [[DefineOwnProperty]] will throw. + var setterCalled = 0; + function exotic() { + Object.defineProperty(this, '0', { + get: function() { return 2; }, + set: function() { setterCalled++; } + }); + } + // Non-configurable properties can't be overwritten with DefineOwnProperty + assertThrows(function () { Array.of.call(exotic, 1); }, TypeError); + // The setter wasn't called + assertEquals(0, setterCalled); + + // Check that array properties defined are writable, enumerable, configurable + function ordinary() { } + var x = Array.of.call(ordinary, 2); + var xlength = Object.getOwnPropertyDescriptor(x, 'length'); + assertEquals(1, xlength.value); + assertEquals(true, xlength.writable); + assertEquals(true, xlength.enumerable); + assertEquals(true, xlength.configurable); + var x0 = Object.getOwnPropertyDescriptor(x, 0); + assertEquals(2, x0.value); + assertEquals(true, xlength.writable); + assertEquals(true, xlength.enumerable); + assertEquals(true, xlength.configurable); +})(); diff --git a/deps/v8/test/mjsunit/harmony/arrow-functions-lexical-arguments.js b/deps/v8/test/mjsunit/harmony/arrow-functions-lexical-arguments.js index e8511051ae..b2498d78dc 100644 --- a/deps/v8/test/mjsunit/harmony/arrow-functions-lexical-arguments.js +++ b/deps/v8/test/mjsunit/harmony/arrow-functions-lexical-arguments.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-arrow-functions --harmony-classes +// Flags: --harmony-arrow-functions (function testInFunctionDeclaration() { diff --git a/deps/v8/test/mjsunit/harmony/arrow-functions-this.js b/deps/v8/test/mjsunit/harmony/arrow-functions-this.js new file mode 100644 index 0000000000..2c2ad075d2 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/arrow-functions-this.js @@ -0,0 +1,81 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-arrow-functions + +var object = {}; +var global = this; +var call = Function.call.bind(Function.call); + +var globalSloppyArrow = () => this; +var globalStrictArrow = () => { "use strict"; return this; }; +var globalSloppyArrowEval = (s) => eval(s); +var globalStrictArrowEval = (s) => { "use strict"; return eval(s); }; + +var sloppyFunctionArrow = function() { + return (() => this)(); +}; +var strictFunctionArrow = function() { + "use strict"; + return (() => this)(); +}; +var sloppyFunctionEvalArrow = function() { + return eval("(() => this)()"); +}; +var strictFunctionEvalArrow = function() { + "use strict"; + return eval("(() => this)()"); +}; +var sloppyFunctionArrowEval = function(s) { + return (() => eval(s))(); +}; +var strictFunctionArrowEval = function(s) { + "use strict"; + return (() => eval(s))(); +}; + +var withObject = { 'this': object } +var arrowInsideWith, arrowInsideWithEval; +with (withObject) { + arrowInsideWith = () => this; + arrowInsideWithEval = (s) => eval(s); +} + +assertEquals(global, call(globalSloppyArrow, object)); +assertEquals(global, call(globalStrictArrow, object)); +assertEquals(global, call(globalSloppyArrowEval, object, "this")); +assertEquals(global, call(globalStrictArrowEval, object, "this")); +assertEquals(global, call(globalSloppyArrowEval, object, "(() => this)()")); +assertEquals(global, call(globalStrictArrowEval, object, "(() => this)()")); + +assertEquals(object, call(sloppyFunctionArrow, object)); +assertEquals(global, call(sloppyFunctionArrow, undefined)); +assertEquals(object, call(strictFunctionArrow, object)); +assertEquals(undefined, call(strictFunctionArrow, undefined)); + +assertEquals(object, call(sloppyFunctionEvalArrow, object)); +assertEquals(global, call(sloppyFunctionEvalArrow, undefined)); +assertEquals(object, call(strictFunctionEvalArrow, object)); +assertEquals(undefined, call(strictFunctionEvalArrow, undefined)); + +assertEquals(object, call(sloppyFunctionArrowEval, object, "this")); +assertEquals(global, call(sloppyFunctionArrowEval, undefined, "this")); +assertEquals(object, call(strictFunctionArrowEval, object, "this")); +assertEquals(undefined, call(strictFunctionArrowEval, undefined, "this")); + +assertEquals(object, + call(sloppyFunctionArrowEval, object, "(() => this)()")); +assertEquals(global, + call(sloppyFunctionArrowEval, undefined, "(() => this)()")); +assertEquals(object, + call(strictFunctionArrowEval, object, "(() => this)()")); +assertEquals(undefined, + call(strictFunctionArrowEval, undefined, "(() => this)()")); + +assertEquals(global, call(arrowInsideWith, undefined)); +assertEquals(global, call(arrowInsideWith, object)); +assertEquals(global, call(arrowInsideWithEval, undefined, "this")); +assertEquals(global, call(arrowInsideWithEval, object, "this")); +assertEquals(global, call(arrowInsideWithEval, undefined, "(() => this)()")); +assertEquals(global, call(arrowInsideWithEval, object, "(() => this)()")); diff --git a/deps/v8/test/mjsunit/harmony/arrow-rest-params.js b/deps/v8/test/mjsunit/harmony/arrow-rest-params.js new file mode 100644 index 0000000000..b1e8dcc1b9 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/arrow-rest-params.js @@ -0,0 +1,142 @@ +// 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. + +// Flags: --harmony-rest-parameters --harmony-arrow-functions + +(function testRestIndex() { + assertEquals(5, ((...args) => args.length)(1,2,3,4,5)); + assertEquals(4, ((a, ...args) => args.length)(1,2,3,4,5)); + assertEquals(3, ((a, b, ...args) => args.length)(1,2,3,4,5)); + assertEquals(2, ((a, b, c, ...args) => args.length)(1,2,3,4,5)); + assertEquals(1, ((a, b, c, d, ...args) => args.length)(1,2,3,4,5)); + assertEquals(0, ((a, b, c, d, e, ...args) => args.length)(1,2,3,4,5)); +})(); + +// strictTest and sloppyTest should be called with descending natural +// numbers, as in: +// +// strictTest(6,5,4,3,2,1) +// +var strictTest = (a, b, ...c) => { + "use strict"; + assertEquals(Array, c.constructor); + assertTrue(Array.isArray(c)); + + var expectedLength = (a === undefined) ? 0 : a - 2; + assertEquals(expectedLength, c.length); + + for (var i = 2; i < a; ++i) { + assertEquals(c[i - 2], a - i); + } +} + +var sloppyTest = (a, b, ...c) => { + assertEquals(Array, c.constructor); + assertTrue(Array.isArray(c)); + + var expectedLength = (a === undefined) ? 0 : a - 2; + assertEquals(expectedLength, c.length); + + for (var i = 2; i < a; ++i) { + assertEquals(c[i - 2], a - i); + } +} + + +var O = { + strict: strictTest, + sloppy: sloppyTest +}; + +(function testStrictRestParamArity() { + assertEquals(2, strictTest.length); + assertEquals(2, O.strict.length); +})(); + + +(function testRestParamsStrictMode() { + strictTest(); + strictTest(2, 1); + strictTest(6, 5, 4, 3, 2, 1); + strictTest(3, 2, 1); + O.strict(); + O.strict(2, 1); + O.strict(6, 5, 4, 3, 2, 1); + O.strict(3, 2, 1); +})(); + + +(function testRestParamsStrictModeApply() { + strictTest.apply(null, []); + strictTest.apply(null, [2, 1]); + strictTest.apply(null, [6, 5, 4, 3, 2, 1]); + strictTest.apply(null, [3, 2, 1]); + O.strict.apply(O, []); + O.strict.apply(O, [2, 1]); + O.strict.apply(O, [6, 5, 4, 3, 2, 1]); + O.strict.apply(O, [3, 2, 1]); +})(); + + +(function testRestParamsStrictModeCall() { + strictTest.call(null); + strictTest.call(null, 2, 1); + strictTest.call(null, 6, 5, 4, 3, 2, 1); + strictTest.call(null, 3, 2, 1); + O.strict.call(O); + O.strict.call(O, 2, 1); + O.strict.call(O, 6, 5, 4, 3, 2, 1); + O.strict.call(O, 3, 2, 1); +})(); + + +(function testsloppyRestParamArity() { + assertEquals(2, sloppyTest.length); + assertEquals(2, O.sloppy.length); +})(); + + +(function testRestParamssloppyMode() { + sloppyTest(); + sloppyTest(2, 1); + sloppyTest(6, 5, 4, 3, 2, 1); + sloppyTest(3, 2, 1); + O.sloppy(); + O.sloppy(2, 1); + O.sloppy(6, 5, 4, 3, 2, 1); + O.sloppy(3, 2, 1); +})(); + + +(function testRestParamssloppyModeApply() { + sloppyTest.apply(null, []); + sloppyTest.apply(null, [2, 1]); + sloppyTest.apply(null, [6, 5, 4, 3, 2, 1]); + sloppyTest.apply(null, [3, 2, 1]); + O.sloppy.apply(O, []); + O.sloppy.apply(O, [2, 1]); + O.sloppy.apply(O, [6, 5, 4, 3, 2, 1]); + O.sloppy.apply(O, [3, 2, 1]); +})(); + + +(function testRestParamssloppyModeCall() { + sloppyTest.call(null); + sloppyTest.call(null, 2, 1); + sloppyTest.call(null, 6, 5, 4, 3, 2, 1); + sloppyTest.call(null, 3, 2, 1); + O.sloppy.call(O); + O.sloppy.call(O, 2, 1); + O.sloppy.call(O, 6, 5, 4, 3, 2, 1); + O.sloppy.call(O, 3, 2, 1); +})(); + + +(function testUnmappedArguments() { + // Normal functions make their arguments object unmapped, but arrow + // functions don't have an arguments object anyway. Check that the + // right thing happens for arguments in arrow functions with rest + // parameters. + assertSame(arguments, ((...rest) => arguments)()); +})(); diff --git a/deps/v8/test/mjsunit/harmony/atomics.js b/deps/v8/test/mjsunit/harmony/atomics.js new file mode 100644 index 0000000000..ff403b8bd1 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/atomics.js @@ -0,0 +1,444 @@ +// 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. + +// Flags: --harmony-atomics --harmony-sharedarraybuffer +// + +function toRangeWrapped(value) { + var range = this.max - this.min + 1; + while (value < this.min) { + value += range; + } + while (value > this.max) { + value -= range; + } + return value; +} + +function toRangeClamped(value) { + if (value < this.min) return this.min; + if (value > this.max) return this.max; + return value; +} + +function makeConstructorObject(constr, min, max, toRange) { + var o = {constr: constr, min: min, max: max}; + o.toRange = toRange.bind(o); + return o; +} + +var IntegerTypedArrayConstructors = [ + makeConstructorObject(Int8Array, -128, 127, toRangeWrapped), + makeConstructorObject(Int16Array, -32768, 32767, toRangeWrapped), + makeConstructorObject(Int32Array, -0x80000000, 0x7fffffff, toRangeWrapped), + makeConstructorObject(Uint8Array, 0, 255, toRangeWrapped), + makeConstructorObject(Uint8ClampedArray, 0, 255, toRangeClamped), + makeConstructorObject(Uint16Array, 0, 65535, toRangeWrapped), + makeConstructorObject(Uint32Array, 0, 0xffffffff, toRangeWrapped), +]; + +var TypedArrayConstructors = IntegerTypedArrayConstructors.concat([ + {constr: Float32Array}, + {constr: Float64Array}, +]); + +(function TestBadArray() { + var ab = new ArrayBuffer(16); + var u32a = new Uint32Array(16); + var sab = new SharedArrayBuffer(128); + var sf32a = new Float32Array(sab); + var sf64a = new Float64Array(sab); + + // Atomic ops required shared typed arrays + [undefined, 1, 'hi', 3.4, ab, u32a, sab].forEach(function(o) { + assertThrows(function() { Atomics.compareExchange(o, 0, 0, 0); }, + TypeError); + assertThrows(function() { Atomics.load(o, 0); }, TypeError); + assertThrows(function() { Atomics.store(o, 0, 0); }, TypeError); + assertThrows(function() { Atomics.add(o, 0, 0); }, TypeError); + assertThrows(function() { Atomics.sub(o, 0, 0); }, TypeError); + assertThrows(function() { Atomics.and(o, 0, 0); }, TypeError); + assertThrows(function() { Atomics.or(o, 0, 0); }, TypeError); + assertThrows(function() { Atomics.xor(o, 0, 0); }, TypeError); + assertThrows(function() { Atomics.exchange(o, 0, 0); }, TypeError); + }); + + // Arithmetic atomic ops require integer shared arrays + [sab, sf32a, sf64a].forEach(function(o) { + assertThrows(function() { Atomics.add(o, 0, 0); }, TypeError); + assertThrows(function() { Atomics.sub(o, 0, 0); }, TypeError); + assertThrows(function() { Atomics.and(o, 0, 0); }, TypeError); + assertThrows(function() { Atomics.or(o, 0, 0); }, TypeError); + assertThrows(function() { Atomics.xor(o, 0, 0); }, TypeError); + assertThrows(function() { Atomics.exchange(o, 0, 0); }, TypeError); + }); +})(); + +function testAtomicOp(op, ia, index, expectedIndex, name) { + for (var i = 0; i < ia.length; ++i) + ia[i] = 22; + + ia[expectedIndex] = 0; + assertEquals(0, op(ia, index, 0, 0), name); + assertEquals(0, ia[expectedIndex], name); + + for (var i = 0; i < ia.length; ++i) { + if (i == expectedIndex) continue; + assertEquals(22, ia[i], name); + } +} + +(function TestBadIndex() { + var sab = new SharedArrayBuffer(8); + var si32a = new Int32Array(sab); + + // Non-integer indexes are converted to an integer first, so they should all + // operate on index 0. + [undefined, null, false, 'hi', {}].forEach(function(i) { + var name = String(i); + + testAtomicOp(Atomics.compareExchange, si32a, i, 0, name); + testAtomicOp(Atomics.load, si32a, i, 0, name); + testAtomicOp(Atomics.store, si32a, i, 0, name); + testAtomicOp(Atomics.add, si32a, i, 0, name); + testAtomicOp(Atomics.sub, si32a, i, 0, name); + testAtomicOp(Atomics.and, si32a, i, 0, name); + testAtomicOp(Atomics.or, si32a, i, 0, name); + testAtomicOp(Atomics.xor, si32a, i, 0, name); + testAtomicOp(Atomics.exchange, si32a, i, 0, name); + }); + + // Out-of-bounds indexes should return undefined. + // TODO(binji): Should these throw RangeError instead? + [-1, 2, 100].forEach(function(i) { + var name = String(i); + assertEquals(undefined, Atomics.compareExchange(si32a, i, 0, 0), name); + assertEquals(undefined, Atomics.load(si32a, i), name); + assertEquals(undefined, Atomics.store(si32a, i, 0), name); + assertEquals(undefined, Atomics.add(si32a, i, 0), name); + assertEquals(undefined, Atomics.sub(si32a, i, 0), name); + assertEquals(undefined, Atomics.and(si32a, i, 0), name); + assertEquals(undefined, Atomics.or(si32a, i, 0), name); + assertEquals(undefined, Atomics.xor(si32a, i, 0), name); + assertEquals(undefined, Atomics.exchange(si32a, i, 0), name); + }); +})(); + +(function TestGoodIndex() { + var sab = new SharedArrayBuffer(64); + var si32a = new Int32Array(sab); + + var valueOf = {valueOf: function(){ return 3;}}; + var toString = {toString: function(){ return '3';}}; + + [3, 3.5, '3', '3.5', valueOf, toString].forEach(function(i) { + var name = String(i); + + testAtomicOp(Atomics.compareExchange, si32a, i, 3, name); + testAtomicOp(Atomics.load, si32a, i, 3, name); + testAtomicOp(Atomics.store, si32a, i, 3, name); + testAtomicOp(Atomics.add, si32a, i, 3, name); + testAtomicOp(Atomics.sub, si32a, i, 3, name); + testAtomicOp(Atomics.and, si32a, i, 3, name); + testAtomicOp(Atomics.or, si32a, i, 3, name); + testAtomicOp(Atomics.xor, si32a, i, 3, name); + testAtomicOp(Atomics.exchange, si32a, i, 3, name); + }); +})(); + +(function TestCompareExchange() { + TypedArrayConstructors.forEach(function(t) { + var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT); + var sta = new t.constr(sab); + var name = Object.prototype.toString.call(sta); + for (var i = 0; i < 10; ++i) { + // sta[i] == 0, CAS will store + assertEquals(0, Atomics.compareExchange(sta, i, 0, 50), name); + assertEquals(50, sta[i], name); + + // sta[i] == 50, CAS will not store + assertEquals(50, Atomics.compareExchange(sta, i, 0, 100), name); + assertEquals(50, sta[i], name); + } + }); + + // * Exact float values should be OK + // * Infinity, -Infinity should be OK (has exact representation) + // * NaN is not OK, it has many representations, cannot ensure successful CAS + // because it does a bitwise compare + [1.5, 4.25, -1e8, -Infinity, Infinity].forEach(function(v) { + var sab = new SharedArrayBuffer(10 * Float32Array.BYTES_PER_ELEMENT); + var sf32a = new Float32Array(sab); + sf32a[0] = 0; + assertEquals(0, Atomics.compareExchange(sf32a, 0, 0, v)); + assertEquals(v, sf32a[0]); + assertEquals(v, Atomics.compareExchange(sf32a, 0, v, 0)); + assertEquals(0, sf32a[0]); + + var sab2 = new SharedArrayBuffer(10 * Float64Array.BYTES_PER_ELEMENT); + var sf64a = new Float64Array(sab2); + sf64a[0] = 0; + assertEquals(0, Atomics.compareExchange(sf64a, 0, 0, v)); + assertEquals(v, sf64a[0]); + assertEquals(v, Atomics.compareExchange(sf64a, 0, v, 0)); + assertEquals(0, sf64a[0]); + }); +})(); + +(function TestLoad() { + TypedArrayConstructors.forEach(function(t) { + var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT); + var sta = new t.constr(sab); + var name = Object.prototype.toString.call(sta); + for (var i = 0; i < 10; ++i) { + sta[i] = 0; + assertEquals(0, Atomics.load(sta, i), name); + sta[i] = 50; + assertEquals(50, Atomics.load(sta, i), name); + } + }); +})(); + +(function TestStore() { + TypedArrayConstructors.forEach(function(t) { + var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT); + var sta = new t.constr(sab); + var name = Object.prototype.toString.call(sta); + for (var i = 0; i < 10; ++i) { + assertEquals(50, Atomics.store(sta, i, 50), name); + assertEquals(50, sta[i], name); + + assertEquals(100, Atomics.store(sta, i, 100), name); + assertEquals(100, sta[i], name); + } + }); + + [1.5, 4.25, -1e8, -Infinity, Infinity, NaN].forEach(function(v) { + var sab = new SharedArrayBuffer(10 * Float32Array.BYTES_PER_ELEMENT); + var sf32a = new Float32Array(sab); + sf32a[0] = 0; + assertEquals(v, Atomics.store(sf32a, 0, v)); + assertEquals(v, sf32a[0]); + + var sab2 = new SharedArrayBuffer(10 * Float64Array.BYTES_PER_ELEMENT); + var sf64a = new Float64Array(sab2); + sf64a[0] = 0; + assertEquals(v, Atomics.store(sf64a, 0, v)); + assertEquals(v, sf64a[0]); + }); +})(); + +(function TestAdd() { + IntegerTypedArrayConstructors.forEach(function(t) { + var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT); + var sta = new t.constr(sab); + var name = Object.prototype.toString.call(sta); + for (var i = 0; i < 10; ++i) { + assertEquals(0, Atomics.add(sta, i, 50), name); + assertEquals(50, sta[i], name); + + assertEquals(50, Atomics.add(sta, i, 70), name); + assertEquals(120, sta[i], name); + } + }); +})(); + +(function TestSub() { + IntegerTypedArrayConstructors.forEach(function(t) { + var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT); + var sta = new t.constr(sab); + var name = Object.prototype.toString.call(sta); + for (var i = 0; i < 10; ++i) { + sta[i] = 120; + assertEquals(120, Atomics.sub(sta, i, 50), name); + assertEquals(70, sta[i], name); + + assertEquals(70, Atomics.sub(sta, i, 70), name); + assertEquals(0, sta[i], name); + } + }); +})(); + +(function TestAnd() { + IntegerTypedArrayConstructors.forEach(function(t) { + var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT); + var sta = new t.constr(sab); + var name = Object.prototype.toString.call(sta); + for (var i = 0; i < 10; ++i) { + sta[i] = 0x3f; + assertEquals(0x3f, Atomics.and(sta, i, 0x30), name); + assertEquals(0x30, sta[i], name); + + assertEquals(0x30, Atomics.and(sta, i, 0x20), name); + assertEquals(0x20, sta[i], name); + } + }); +})(); + +(function TestOr() { + IntegerTypedArrayConstructors.forEach(function(t) { + var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT); + var sta = new t.constr(sab); + var name = Object.prototype.toString.call(sta); + for (var i = 0; i < 10; ++i) { + sta[i] = 0x30; + assertEquals(0x30, Atomics.or(sta, i, 0x1c), name); + assertEquals(0x3c, sta[i], name); + + assertEquals(0x3c, Atomics.or(sta, i, 0x09), name); + assertEquals(0x3d, sta[i], name); + } + }); +})(); + +(function TestXor() { + IntegerTypedArrayConstructors.forEach(function(t) { + var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT); + var sta = new t.constr(sab); + var name = Object.prototype.toString.call(sta); + for (var i = 0; i < 10; ++i) { + sta[i] = 0x30; + assertEquals(0x30, Atomics.xor(sta, i, 0x1c), name); + assertEquals(0x2c, sta[i], name); + + assertEquals(0x2c, Atomics.xor(sta, i, 0x09), name); + assertEquals(0x25, sta[i], name); + } + }); +})(); + +(function TestExchange() { + IntegerTypedArrayConstructors.forEach(function(t) { + var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT); + var sta = new t.constr(sab); + var name = Object.prototype.toString.call(sta); + for (var i = 0; i < 10; ++i) { + sta[i] = 0x30; + assertEquals(0x30, Atomics.exchange(sta, i, 0x1c), name); + assertEquals(0x1c, sta[i], name); + + assertEquals(0x1c, Atomics.exchange(sta, i, 0x09), name); + assertEquals(0x09, sta[i], name); + } + }); +})(); + +(function TestIsLockFree() { + // For all platforms we support, 1, 2 and 4 bytes should be lock-free. + assertEquals(true, Atomics.isLockFree(1)); + assertEquals(true, Atomics.isLockFree(2)); + assertEquals(true, Atomics.isLockFree(4)); + + // Sizes that aren't equal to a typedarray BYTES_PER_ELEMENT always return + // false. + var validSizes = {}; + TypedArrayConstructors.forEach(function(t) { + validSizes[t.constr.BYTES_PER_ELEMENT] = true; + }); + + for (var i = 0; i < 1000; ++i) { + if (!validSizes[i]) { + assertEquals(false, Atomics.isLockFree(i)); + } + } +})(); + +(function TestWrapping() { + IntegerTypedArrayConstructors.forEach(function(t) { + var sab = new SharedArrayBuffer(10 * t.constr.BYTES_PER_ELEMENT); + var sta = new t.constr(sab); + var name = Object.prototype.toString.call(sta); + var range = t.max - t.min + 1; + var offset; + var operand; + var val, newVal; + var valWrapped, newValWrapped; + + for (offset = -range; offset <= range; offset += range) { + // CompareExchange + sta[0] = val = 0; + newVal = val + offset + 1; + newValWrapped = t.toRange(newVal); + assertEquals(val, Atomics.compareExchange(sta, 0, val, newVal), name); + assertEquals(newValWrapped, sta[0], name); + + sta[0] = val = t.min; + newVal = val + offset - 1; + newValWrapped = t.toRange(newVal); + assertEquals(val, Atomics.compareExchange(sta, 0, val, newVal), name); + assertEquals(newValWrapped, sta[0], name); + + // Store + sta[0] = 0; + val = t.max + offset + 1; + valWrapped = t.toRange(val); + assertEquals(val, Atomics.store(sta, 0, val), name); + assertEquals(valWrapped, sta[0], name); + + sta[0] = val = t.min + offset - 1; + valWrapped = t.toRange(val); + assertEquals(val, Atomics.store(sta, 0, val), name); + assertEquals(valWrapped, sta[0], name); + + // Add + sta[0] = val = t.max; + operand = offset + 1; + valWrapped = t.toRange(val + operand); + assertEquals(val, Atomics.add(sta, 0, operand), name); + assertEquals(valWrapped, sta[0], name); + + sta[0] = val = t.min; + operand = offset - 1; + valWrapped = t.toRange(val + operand); + assertEquals(val, Atomics.add(sta, 0, operand), name); + assertEquals(valWrapped, sta[0], name); + + // Sub + sta[0] = val = t.max; + operand = offset - 1; + valWrapped = t.toRange(val - operand); + assertEquals(val, Atomics.sub(sta, 0, operand), name); + assertEquals(valWrapped, sta[0], name); + + sta[0] = val = t.min; + operand = offset + 1; + valWrapped = t.toRange(val - operand); + assertEquals(val, Atomics.sub(sta, 0, operand), name); + assertEquals(valWrapped, sta[0], name); + + // There's no way to wrap results with logical operators, just test that + // using an out-of-range value is properly wrapped/clamped when written + // to memory. + + // And + sta[0] = val = 0xf; + operand = 0x3 + offset; + valWrapped = t.toRange(val & operand); + assertEquals(val, Atomics.and(sta, 0, operand), name); + assertEquals(valWrapped, sta[0], name); + + // Or + sta[0] = val = 0x12; + operand = 0x22 + offset; + valWrapped = t.toRange(val | operand); + assertEquals(val, Atomics.or(sta, 0, operand), name); + assertEquals(valWrapped, sta[0], name); + + // Xor + sta[0] = val = 0x12; + operand = 0x22 + offset; + valWrapped = t.toRange(val ^ operand); + assertEquals(val, Atomics.xor(sta, 0, operand), name); + assertEquals(valWrapped, sta[0], name); + + // Exchange + sta[0] = val = 0x12; + operand = 0x22 + offset; + valWrapped = t.toRange(operand); + assertEquals(val, Atomics.exchange(sta, 0, operand), name); + assertEquals(valWrapped, sta[0], name); + } + + }); +})(); diff --git a/deps/v8/test/mjsunit/harmony/class-computed-property-names-super.js b/deps/v8/test/mjsunit/harmony/class-computed-property-names-super.js index 5a5db67d48..a68b53c18f 100644 --- a/deps/v8/test/mjsunit/harmony/class-computed-property-names-super.js +++ b/deps/v8/test/mjsunit/harmony/class-computed-property-names-super.js @@ -3,7 +3,7 @@ // found in the LICENSE file. // Flags: --harmony-computed-property-names --harmony-sloppy -// Flags: --harmony-classes --allow-natives-syntax +// Flags: --allow-natives-syntax function ID(x) { diff --git a/deps/v8/test/mjsunit/harmony/computed-property-names-classes.js b/deps/v8/test/mjsunit/harmony/computed-property-names-classes.js index e8cae460a5..46a9e9ec2d 100644 --- a/deps/v8/test/mjsunit/harmony/computed-property-names-classes.js +++ b/deps/v8/test/mjsunit/harmony/computed-property-names-classes.js @@ -4,7 +4,7 @@ 'use strict'; -// Flags: --harmony-computed-property-names --harmony-classes +// Flags: --harmony-computed-property-names function ID(x) { diff --git a/deps/v8/test/mjsunit/harmony/computed-property-names-deopt.js b/deps/v8/test/mjsunit/harmony/computed-property-names-deopt.js new file mode 100644 index 0000000000..1f0b0585fc --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/computed-property-names-deopt.js @@ -0,0 +1,30 @@ +// 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. + +// Flags: --harmony-computed-property-names --allow-natives-syntax + + +(function TestProtoDeopt() { + var proto = {}; + + function deoptMe() { + %DeoptimizeFunction(f); + return proto; + } + + function checkObject(name, value, o) { + assertSame(proto, Object.getPrototypeOf(o)); + assertTrue(o.hasOwnProperty(name)); + assertEquals(value, o[name]); + } + + function f(name, value) { + return { [name]: value, __proto__: deoptMe() }; + } + + checkObject("a", 1, f("a", 1)); + checkObject("b", 2, f("b", 2)); + %OptimizeFunctionOnNextCall(f); + checkObject("c", 3, f("c", 3)); +})(); diff --git a/deps/v8/test/mjsunit/harmony/computed-property-names-object-literals-methods.js b/deps/v8/test/mjsunit/harmony/computed-property-names-object-literals-methods.js index 135d09854e..7ba15aca92 100644 --- a/deps/v8/test/mjsunit/harmony/computed-property-names-object-literals-methods.js +++ b/deps/v8/test/mjsunit/harmony/computed-property-names-object-literals-methods.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-computed-property-names --harmony-object-literals +// Flags: --harmony-computed-property-names function ID(x) { diff --git a/deps/v8/test/mjsunit/harmony/computed-property-names-super.js b/deps/v8/test/mjsunit/harmony/computed-property-names-super.js index 096e010317..bfc31c668f 100644 --- a/deps/v8/test/mjsunit/harmony/computed-property-names-super.js +++ b/deps/v8/test/mjsunit/harmony/computed-property-names-super.js @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-computed-property-names --harmony-object-literals -// Flags: --harmony-classes --allow-natives-syntax +// Flags: --harmony-computed-property-names --allow-natives-syntax function ID(x) { diff --git a/deps/v8/test/mjsunit/harmony/destructuring-parameters-literalcount-nolazy.js b/deps/v8/test/mjsunit/harmony/destructuring-parameters-literalcount-nolazy.js new file mode 100644 index 0000000000..fdf1233f90 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/destructuring-parameters-literalcount-nolazy.js @@ -0,0 +1,41 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-destructuring --harmony-computed-property-names +// Flags: --harmony-arrow-functions --no-lazy --allow-natives-syntax + + +var t1 = [1]; +var t2 = [2]; +var t3 = [3]; +var t4 = [4]; +var t5 = [5]; +function g({x = {a:10,b:20}}, + {y = [1,2,3], + n = [], + p = /abc/}) { + assertSame(10, x.a); + assertSame(20, x.b); + assertSame(2, y[1]); + assertSame(0, n.length); + assertTrue(p.test("abc")); +} +g({},{}); +%OptimizeFunctionOnNextCall(g); +g({},{}); + + +var h = ({x = {a:10,b:20}}, + {y = [1,2,3], + n = [], + p = /abc/ }) => { + assertSame(10, x.a); + assertSame(20, x.b); + assertSame(2, y[1]); + assertSame(0, n.length); + assertTrue(p.test("abc")); + }; +h({},{}); +%OptimizeFunctionOnNextCall(h); +h({},{}); diff --git a/deps/v8/test/mjsunit/harmony/destructuring-parameters-literalcount.js b/deps/v8/test/mjsunit/harmony/destructuring-parameters-literalcount.js new file mode 100644 index 0000000000..85a45ea822 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/destructuring-parameters-literalcount.js @@ -0,0 +1,41 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-destructuring --harmony-computed-property-names +// Flags: --harmony-arrow-functions --allow-natives-syntax + + +var t1 = [1]; +var t2 = [2]; +var t3 = [3]; +var t4 = [4]; +var t5 = [5]; +function g({x = {a:10,b:20}}, + {y = [1,2,3], + n = [], + p = /abc/}) { + assertSame(10, x.a); + assertSame(20, x.b); + assertSame(2, y[1]); + assertSame(0, n.length); + assertTrue(p.test("abc")); +} +g({},{}); +%OptimizeFunctionOnNextCall(g); +g({},{}); + + +var h = ({x = {a:10,b:20}}, + {y = [1,2,3], + n = [], + p = /abc/ }) => { + assertSame(10, x.a); + assertSame(20, x.b); + assertSame(2, y[1]); + assertSame(0, n.length); + assertTrue(p.test("abc")); + }; +h({},{}); +%OptimizeFunctionOnNextCall(h); +h({},{}); diff --git a/deps/v8/test/mjsunit/harmony/destructuring.js b/deps/v8/test/mjsunit/harmony/destructuring.js new file mode 100644 index 0000000000..198d4c0257 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/destructuring.js @@ -0,0 +1,738 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --harmony-destructuring --harmony-computed-property-names +// Flags: --harmony-arrow-functions + +(function TestObjectLiteralPattern() { + var { x : x, y : y } = { x : 1, y : 2 }; + assertEquals(1, x); + assertEquals(2, y); + + var {z} = { z : 3 }; + assertEquals(3, z); + + + var sum = 0; + for (var {z} = { z : 3 }; z != 0; z--) { + sum += z; + } + assertEquals(6, sum); + + + var log = []; + var o = { + get x() { + log.push("x"); + return 0; + }, + get y() { + log.push("y"); + return { + get z() { log.push("z"); return 1; } + } + } + }; + var { x : x0, y : { z : z1 }, x : x1 } = o; + assertSame(0, x0); + assertSame(1, z1); + assertSame(0, x1); + assertArrayEquals(["x", "y", "z", "x"], log); +}()); + + +(function TestObjectLiteralPatternInitializers() { + var { x : x, y : y = 2 } = { x : 1 }; + assertEquals(1, x); + assertEquals(2, y); + + var {z = 3} = {}; + assertEquals(3, z); + + var sum = 0; + for (var {z = 3} = {}; z != 0; z--) { + sum += z; + } + assertEquals(6, sum); + + var log = []; + var o = { + get x() { + log.push("x"); + return undefined; + }, + get y() { + log.push("y"); + return { + get z() { log.push("z"); return undefined; } + } + } + }; + var { x : x0 = 0, y : { z : z1 = 1}, x : x1 = 0} = o; + assertSame(0, x0); + assertSame(1, z1); + assertSame(0, x1); + assertArrayEquals(["x", "y", "z", "x"], log); +}()); + + +(function TestObjectLiteralPatternLexicalInitializers() { + 'use strict'; + let { x : x, y : y = 2 } = { x : 1 }; + assertEquals(1, x); + assertEquals(2, y); + + let {z = 3} = {}; + assertEquals(3, z); + + let log = []; + let o = { + get x() { + log.push("x"); + return undefined; + }, + get y() { + log.push("y"); + return { + get z() { log.push("z"); return undefined; } + } + } + }; + + let { x : x0 = 0, y : { z : z1 = 1 }, x : x1 = 5} = o; + assertSame(0, x0); + assertSame(1, z1); + assertSame(5, x1); + assertArrayEquals(["x", "y", "z", "x"], log); + + let sum = 0; + for (let {x = 0, z = 3} = {}; z != 0; z--) { + assertEquals(0, x); + sum += z; + } + assertEquals(6, sum); +}()); + + +(function TestObjectLiteralPatternLexical() { + 'use strict'; + let { x : x, y : y } = { x : 1, y : 2 }; + assertEquals(1, x); + assertEquals(2, y); + + let {z} = { z : 3 }; + assertEquals(3, z); + + let log = []; + let o = { + get x() { + log.push("x"); + return 0; + }, + get y() { + log.push("y"); + return { + get z() { log.push("z"); return 1; } + } + } + }; + let { x : x0, y : { z : z1 }, x : x1 } = o; + assertSame(0, x0); + assertSame(1, z1); + assertSame(0, x1); + assertArrayEquals(["x", "y", "z", "x"], log); + + let sum = 0; + for (let {x, z} = { x : 0, z : 3 }; z != 0; z--) { + assertEquals(0, x); + sum += z; + } + assertEquals(6, sum); +}()); + + +(function TestObjectLiteralPatternLexicalConst() { + 'use strict'; + const { x : x, y : y } = { x : 1, y : 2 }; + assertEquals(1, x); + assertEquals(2, y); + + assertThrows(function() { x++; }, TypeError); + assertThrows(function() { y++; }, TypeError); + + const {z} = { z : 3 }; + assertEquals(3, z); + + for (const {x, z} = { x : 0, z : 3 }; z != 3 || x != 0;) { + assertTrue(false); + } +}()); + + +(function TestFailingMatchesSloppy() { + var {x, y} = {}; + assertSame(undefined, x); + assertSame(undefined, y); + + var { x : { z1 }, y2} = { x : {}, y2 : 42 } + assertSame(undefined, z1); + assertSame(42, y2); +}()); + + +(function TestFailingMatchesStrict() { + 'use strict'; + var {x, y} = {}; + assertSame(undefined, x); + assertSame(undefined, y); + + var { x : { z1 }, y2} = { x : {}, y2 : 42 } + assertSame(undefined, z1); + assertSame(42, y2); + + { + let {x1,y1} = {}; + assertSame(undefined, x1); + assertSame(undefined, y1); + + let { x : { z1 }, y2} = { x : {}, y2 : 42 } + assertSame(undefined, z1); + assertSame(42, y2); + } +}()); + + +(function TestTDZInIntializers() { + 'use strict'; + { + let {x, y = x} = {x : 42, y : 27}; + assertSame(42, x); + assertSame(27, y); + } + + { + let {x, y = x + 1} = { x : 42 }; + assertSame(42, x); + assertSame(43, y); + } + assertThrows(function() { + let {x = y, y} = { y : 42 }; + }, ReferenceError); + + { + let {x, y = eval("x+1")} = {x:42}; + assertEquals(42, x); + assertEquals(43, y); + } + + { + let {x = function() {return y+1;}, y} = {y:42}; + assertEquals(43, x()); + assertEquals(42, y); + } + { + let {x = function() {return eval("y+1");}, y} = {y:42}; + assertEquals(43, x()); + assertEquals(42, y); + } +}()); + + +(function TestSideEffectsInInitializers() { + var callCount = 0; + function f(v) { callCount++; return v; } + + callCount = 0; + var { x = f(42) } = { x : 27 }; + assertSame(27, x); + assertEquals(0, callCount); + + callCount = 0; + var { x = f(42) } = {}; + assertSame(42, x); + assertEquals(1, callCount); +}()); + + +(function TestMultipleAccesses() { + assertThrows( + "'use strict';"+ + "const {x,x} = {x:1};", + SyntaxError); + + assertThrows( + "'use strict';"+ + "let {x,x} = {x:1};", + SyntaxError); + + (function() { + var {x,x = 2} = {x : 1}; + assertSame(1, x); + }()); + + assertThrows(function () { + 'use strict'; + let {x = (function() { x = 2; }())} = {}; + }, ReferenceError); + + (function() { + 'use strict'; + let {x = (function() { x = 2; }())} = {x:1}; + assertSame(1, x); + }()); +}()); + + +(function TestComputedNames() { + var x = 1; + var {[x]:y} = {1:2}; + assertSame(2, y); + + (function(){ + 'use strict'; + let {[x]:y} = {1:2}; + assertSame(2, y); + }()); + + var callCount = 0; + function foo(v) { callCount++; return v; } + + (function() { + callCount = 0; + var {[foo("abc")]:x} = {abc:42}; + assertSame(42, x); + assertEquals(1, callCount); + }()); + + (function() { + 'use strict'; + callCount = 0; + let {[foo("abc")]:x} = {abc:42}; + assertSame(42, x); + assertEquals(1, callCount); + }()); + + (function() { + callCount = 0; + var {[foo("abc")]:x} = {}; + assertSame(undefined, x); + assertEquals(1, callCount); + }()); + + (function() { + 'use strict'; + callCount = 0; + let {[foo("abc")]:x} = {}; + assertSame(undefined, x); + assertEquals(1, callCount); + }()); + + for (val of [null, undefined]) { + callCount = 0; + assertThrows(function() { + var {[foo()]:x} = val; + }, TypeError); + assertEquals(0, callCount); + + callCount = 0; + assertThrows(function() { + 'use strict'; + let {[foo()]:x} = val; + }, TypeError); + assertEquals(0, callCount); + } + + var log = []; + var o = { + get x() { log.push("get x"); return 1; }, + get y() { log.push("get y"); return 2; } + } + function f(v) { log.push("f " + v); return v; } + + (function() { + log = []; + var { [f('x')]:x, [f('y')]:y } = o; + assertSame(1, x); + assertSame(2, y); + assertArrayEquals(["f x", "get x", "f y", "get y"], log); + }()); + + (function() { + 'use strict'; + log = []; + let { [f('x')]:x, [f('y')]:y } = o; + assertSame(1, x); + assertSame(2, y); + assertArrayEquals(["f x", "get x", "f y", "get y"], log); + }()); + + (function() { + 'use strict'; + log = []; + const { [f('x')]:x, [f('y')]:y } = o; + assertSame(1, x); + assertSame(2, y); + assertArrayEquals(["f x", "get x", "f y", "get y"], log); + }()); +}()); + + +(function TestExceptions() { + for (var val of [null, undefined]) { + assertThrows(function() { var {} = val; }, TypeError); + assertThrows(function() { var {x} = val; }, TypeError); + assertThrows(function() { var { x : {} } = { x : val }; }, TypeError); + assertThrows(function() { 'use strict'; let {} = val; }, TypeError); + assertThrows(function() { 'use strict'; let {x} = val; }, TypeError); + assertThrows(function() { 'use strict'; let { x : {} } = { x : val }; }, + TypeError); + } +}()); + + +(function TestArrayLiteral() { + var [a, b, c] = [1, 2, 3]; + assertSame(1, a); + assertSame(2, b); + assertSame(3, c); +}()); + +(function TestIterators() { + var log = []; + function* f() { + log.push("1"); + yield 1; + log.push("2"); + yield 2; + log.push("3"); + yield 3; + log.push("done"); + }; + + (function() { + log = []; + var [a, b, c] = f(); + assertSame(1, a); + assertSame(2, b); + assertSame(3, c); + assertArrayEquals(["1", "2", "3"], log); + }()); + + (function() { + log = []; + var [a, b, c, d] = f(); + assertSame(1, a); + assertSame(2, b); + assertSame(3, c); + assertSame(undefined, d); + assertArrayEquals(["1", "2", "3", "done"], log); + }()); + + (function() { + log = []; + var [a, , c] = f(); + assertSame(1, a); + assertSame(3, c); + assertArrayEquals(["1", "2", "3"], log); + }()); + + (function() { + log = []; + var [a, , c, d] = f(); + assertSame(1, a); + assertSame(3, c); + assertSame(undefined, d); + assertArrayEquals(["1", "2", "3", "done"], log); + }()); + + (function() { + log = []; + // last comma is not an elision. + var [a, b,] = f(); + assertSame(1, a); + assertSame(2, b); + assertArrayEquals(["1", "2"], log); + }()); + + (function() { + log = []; + // last comma is not an elision, but the comma before the last is. + var [a, b, ,] = f(); + assertSame(1, a); + assertSame(2, b); + assertArrayEquals(["1", "2", "3"], log); + }()); + + (function() { + log = []; + var [a, ...rest] = f(); + assertSame(1, a); + assertArrayEquals([2,3], rest); + assertArrayEquals(["1", "2", "3", "done"], log); + }()); + + (function() { + log = []; + var [a, b, c, ...rest] = f(); + assertSame(1, a); + assertSame(2, b); + assertSame(3, c); + assertArrayEquals([], rest); + assertArrayEquals(["1", "2", "3", "done"], log); + }()); + + (function() { + log = []; + var [a, b, c, d, ...rest] = f(); + assertSame(1, a); + assertSame(2, b); + assertSame(3, c); + assertSame(undefined, d); + assertArrayEquals([], rest); + assertArrayEquals(["1", "2", "3", "done"], log); + }()); +}()); + + +(function TestIteratorsLexical() { + 'use strict'; + var log = []; + function* f() { + log.push("1"); + yield 1; + log.push("2"); + yield 2; + log.push("3"); + yield 3; + log.push("done"); + }; + + (function() { + log = []; + let [a, b, c] = f(); + assertSame(1, a); + assertSame(2, b); + assertSame(3, c); + assertArrayEquals(["1", "2", "3"], log); + }()); + + (function() { + log = []; + let [a, b, c, d] = f(); + assertSame(1, a); + assertSame(2, b); + assertSame(3, c); + assertSame(undefined, d); + assertArrayEquals(["1", "2", "3", "done"], log); + }()); + + (function() { + log = []; + let [a, , c] = f(); + assertSame(1, a); + assertSame(3, c); + assertArrayEquals(["1", "2", "3"], log); + }()); + + (function() { + log = []; + let [a, , c, d] = f(); + assertSame(1, a); + assertSame(3, c); + assertSame(undefined, d); + assertArrayEquals(["1", "2", "3", "done"], log); + }()); + + (function() { + log = []; + // last comma is not an elision. + let [a, b,] = f(); + assertSame(1, a); + assertSame(2, b); + assertArrayEquals(["1", "2"], log); + }()); + + (function() { + log = []; + // last comma is not an elision, but the comma before the last is. + let [a, b, ,] = f(); + assertSame(1, a); + assertSame(2, b); + assertArrayEquals(["1", "2", "3"], log); + }()); + + (function() { + log = []; + let [a, ...rest] = f(); + assertSame(1, a); + assertArrayEquals([2,3], rest); + assertArrayEquals(["1", "2", "3", "done"], log); + }()); + + (function() { + log = []; + let [a, b, c, ...rest] = f(); + assertSame(1, a); + assertSame(2, b); + assertSame(3, c); + assertArrayEquals([], rest); + assertArrayEquals(["1", "2", "3", "done"], log); + }()); + + (function() { + log = []; + let [a, b, c, d, ...rest] = f(); + assertSame(1, a); + assertSame(2, b); + assertSame(3, c); + assertSame(undefined, d); + assertArrayEquals([], rest); + assertArrayEquals(["1", "2", "3", "done"], log); + }()); +}()); + +(function TestIteratorsRecursive() { + var log = []; + function* f() { + log.push("1"); + yield {x : 1, y : 2}; + log.push("2"); + yield [42, 27, 30]; + log.push("3"); + yield "abc"; + log.push("done"); + }; + + (function() { + var [{x, y}, [a, b]] = f(); + assertSame(1, x); + assertSame(2, y); + assertSame(42, a); + assertSame(27, b); + assertArrayEquals(["1", "2"], log); + }()); + + (function() { + 'use strict'; + log = []; + let [{x, y}, [a, b]] = f(); + assertSame(1, x); + assertSame(2, y); + assertSame(42, a); + assertSame(27, b); + assertArrayEquals(["1", "2"], log); + }()); +}()); + + +(function TestForEachLexical() { + 'use strict'; + let a = [{x:1, y:-1}, {x:2,y:-2}, {x:3,y:-3}]; + let sumX = 0; + let sumY = 0; + let fs = []; + for (let {x,y} of a) { + sumX += x; + sumY += y; + fs.push({fx : function() { return x; }, fy : function() { return y }}); + } + assertSame(6, sumX); + assertSame(-6, sumY); + assertSame(3, fs.length); + for (let i = 0; i < fs.length; i++) { + let {fx,fy} = fs[i]; + assertSame(i+1, fx()); + assertSame(-(i+1), fy()); + } + + var o = { __proto__:null, 'a1':1, 'b2':2 }; + let sx = ''; + let sy = ''; + for (let [x,y] in o) { + sx += x; + sy += y; + } + assertEquals('ab', sx); + assertEquals('12', sy); +}()); + + +(function TestForEachVars() { + var a = [{x:1, y:-1}, {x:2,y:-2}, {x:3,y:-3}]; + var sumX = 0; + var sumY = 0; + var fs = []; + for (var {x,y} of a) { + sumX += x; + sumY += y; + fs.push({fx : function() { return x; }, fy : function() { return y }}); + } + assertSame(6, sumX); + assertSame(-6, sumY); + assertSame(3, fs.length); + for (var i = 0; i < fs.length; i++) { + var {fx,fy} = fs[i]; + assertSame(3, fx()); + assertSame(-3, fy()); + } + + var o = { __proto__:null, 'a1':1, 'b2':2 }; + var sx = ''; + var sy = ''; + for (var [x,y] in o) { + sx += x; + sy += y; + } + assertEquals('ab', sx); + assertEquals('12', sy); +}()); + + +(function TestParameters() { + function f({a, b}) { return a - b; } + assertEquals(1, f({a : 6, b : 5})); + + function f1(c, {a, b}) { return c + a - b; } + assertEquals(8, f1(7, {a : 6, b : 5})); + + function f2({c, d}, {a, b}) { return c - d + a - b; } + assertEquals(7, f2({c : 7, d : 1}, {a : 6, b : 5})); + + function f3([{a, b}]) { return a - b; } + assertEquals(1, f3([{a : 6, b : 5}])); + + var g = ({a, b}) => { return a - b; }; + assertEquals(1, g({a : 6, b : 5})); + + var g1 = (c, {a, b}) => { return c + a - b; }; + assertEquals(8, g1(7, {a : 6, b : 5})); + + var g2 = ({c, d}, {a, b}) => { return c - d + a - b; }; + assertEquals(7, g2({c : 7, d : 1}, {a : 6, b : 5})); + + var g3 = ([{a, b}]) => { return a - b; }; + assertEquals(1, g3([{a : 6, b : 5}])); +}()); + + +(function TestDuplicatesInParameters() { + assertThrows("'use strict';function f(x,x){}", SyntaxError); + assertThrows("'use strict';function f({x,x}){}", SyntaxError); + assertThrows("'use strict';function f(x, {x}){}", SyntaxError); + assertThrows("'use strict';var f = (x,x) => {};", SyntaxError); + assertThrows("'use strict';var f = ({x,x}) => {};", SyntaxError); + assertThrows("'use strict';var f = (x, {x}) => {};", SyntaxError); + + function ok(x) { var x; }; ok(); + assertThrows("function f({x}) { var x; }; f({});", SyntaxError); + assertThrows("'use strict'; function f({x}) { let x = 0; }; f({});", SyntaxError); +}()); + + +(function TestForInOfTDZ() { + assertThrows("'use strict'; let x = {}; for (let [x, y] of {x});", ReferenceError); + assertThrows("'use strict'; let x = {}; for (let [y, x] of {x});", ReferenceError); + assertThrows("'use strict'; let x = {}; for (let [x, y] in {x});", ReferenceError); + assertThrows("'use strict'; let x = {}; for (let [y, x] in {x});", ReferenceError); +}()); diff --git a/deps/v8/test/mjsunit/harmony/new-target.js b/deps/v8/test/mjsunit/harmony/new-target.js new file mode 100644 index 0000000000..587461a958 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/new-target.js @@ -0,0 +1,370 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-classes --harmony-new-target --harmony-reflect +// Flags: --harmony-rest-parameters --harmony-arrow-functions + + +(function TestClass() { + 'use strict'; + + var calls = 0; + class Base { + constructor(_) { + assertEquals(Base, new.target); + calls++; + } + } + assertInstanceof(new Base(1), Base); + assertInstanceof(new Base(1, 2), Base); + assertInstanceof(new Base(), Base); + assertEquals(3, calls); +})(); + + +(function TestDerivedClass() { + 'use strict'; + + var calls = 0; + class Base { + constructor(expected) { + assertEquals(expected, new.target); + } + } + class Derived extends Base { + constructor(expected) { + super(expected); + assertEquals(expected, new.target); + calls++; + } + } + new Derived(Derived, 'extra'); + new Derived(Derived); + assertEquals(2, calls); + + class Derived2 extends Derived {} + calls = 0; + new Derived2(Derived2); + new Derived2(Derived2, 'extra'); + assertEquals(2, calls); +})(); + + +(function TestFunctionCall() { + var calls; + function f(expected) { + calls++; + assertEquals(expected, new.target); + } + + calls = 0; + f(undefined); + f(undefined, 'extra'); + f(); + assertEquals(3, calls); + + calls = 0; + f.call({}, undefined); + f.call({}, undefined, 'extra'); + f.call({}); + assertEquals(3, calls); + + calls = 0; + f.apply({}, [undefined]); + f.apply({}, [undefined, 'extra']); + f.apply({}, []); + assertEquals(3, calls); +})(); + + +(function TestFunctionConstruct() { + var calls; + function f(expected) { + calls++; + assertEquals(expected, new.target); + } + + calls = 0; + new f(f); + new f(f, 'extra'); + assertEquals(2, calls); +})(); + + +(function TestClassExtendsFunction() { + 'use strict'; + + var calls = 0; + function f(expected) { + assertEquals(expected, new.target); + } + class Derived extends f { + constructor(expected) { + super(expected); + assertEquals(expected, new.target); + calls++; + } + } + + new Derived(Derived); + new Derived(Derived, 'extra'); + assertEquals(2, calls); +})(); + + +(function TestFunctionReturnObject() { + function f(expected) { + assertEquals(expected, new.target); + return /abc/; + } + + assertInstanceof(new f(f), RegExp); + assertInstanceof(new f(f, 'extra'), RegExp); + + assertInstanceof(f(undefined), RegExp); + assertInstanceof(f(), RegExp); + assertInstanceof(f(undefined, 'extra'), RegExp); +})(); + + +(function TestClassReturnObject() { + 'use strict'; + + class Base { + constructor(expected) { + assertEquals(expected, new.target); + return /abc/; + } + } + + assertInstanceof(new Base(Base), RegExp); + assertInstanceof(new Base(Base, 'extra'), RegExp); + + class Derived extends Base {} + assertInstanceof(new Derived(Derived), RegExp); + assertInstanceof(new Derived(Derived, 'extra'), RegExp); + + class Derived2 extends Base { + constructor(expected) { + super(expected); + assertInstanceof(this, RegExp); + } + } + assertInstanceof(new Derived2(Derived2), RegExp); + assertInstanceof(new Derived2(Derived2, 'extra'), RegExp); +})(); + + +(function TestReflectConstruct() { + var calls = 0; + function f(expected) { + calls++; + assertEquals(expected, new.target); + } + + var o = Reflect.construct(f, [f]); + assertEquals(Object.getPrototypeOf(o), f.prototype); + o = Reflect.construct(f, [f, 'extra']); + assertEquals(Object.getPrototypeOf(o), f.prototype); + assertEquals(2, calls); + + calls = 0; + o = Reflect.construct(f, [f], f); + assertEquals(Object.getPrototypeOf(o), f.prototype); + o = Reflect.construct(f, [f, 'extra'], f); + assertEquals(Object.getPrototypeOf(o), f.prototype); + assertEquals(2, calls); + + + function g() {} + calls = 0; + o = Reflect.construct(f, [g], g); + assertEquals(Object.getPrototypeOf(o), g.prototype); + o = Reflect.construct(f, [g, 'extra'], g); + assertEquals(Object.getPrototypeOf(o), g.prototype); + assertEquals(2, calls); +})(); + + +(function TestRestParametersFunction() { + function f(...rest) { + assertEquals(rest[0], new.target); + } + + assertInstanceof(new f(f), f); + assertInstanceof(new f(f, 'extra'), f); +})(); + + +(function TestRestParametersClass() { + 'use strict'; + + class Base { + constructor(...rest) { + assertEquals(rest[0], new.target); + } + } + + assertInstanceof(new Base(Base), Base); + assertInstanceof(new Base(Base, 'extra'), Base); + + class Derived extends Base {} + + assertInstanceof(new Derived(Derived), Derived); + assertInstanceof(new Derived(Derived, 'extra'), Derived); +})(); + + +(function TestArrowFunction() { + function f(expected) { + (() => { + assertEquals(expected, new.target); + })(); + } + + assertInstanceof(new f(f), f); + assertInstanceof(new f(f, 'extra'), f); +})(); + + +(function TestRestParametersClass() { + 'use strict'; + + class Base { + constructor(expected) { + (() => { + assertEquals(expected, new.target); + })(); + } + } + + assertInstanceof(new Base(Base), Base); + assertInstanceof(new Base(Base, 'extra'), Base); + + class Derived extends Base {} + + assertInstanceof(new Derived(Derived), Derived); + assertInstanceof(new Derived(Derived, 'extra'), Derived); +})(); + + +(function TestSloppyArguments() { + var length, a0, a1, a2, nt; + function f(x) { + assertEquals(length, arguments.length); + assertEquals(a0, arguments[0]); + assertEquals(a1, arguments[1]); + assertEquals(a2, arguments[2]); + assertEquals(nt, new.target); + + if (length > 0) { + x = 42; + assertEquals(42, x); + assertEquals(42, arguments[0]); + + arguments[0] = 33; + assertEquals(33, x); + assertEquals(33, arguments[0]); + } + } + + nt = f; + length = 0; + new f(); + + length = 1; + a0 = 1; + new f(1); + + length = 2; + a0 = 1; + a1 = 2; + new f(1, 2); + + length = 3; + a0 = 1; + a1 = 2; + a2 = 3; + new f(1, 2, 3); + + nt = undefined; + a0 = a1 = a2 = undefined; + length = 0; + f(); + + length = 1; + a0 = 1; + f(1); + + length = 2; + a0 = 1; + a1 = 2; + f(1, 2); + + length = 3; + a0 = 1; + a1 = 2; + a2 = 3; + f(1, 2, 3); +})(); + + +(function TestStrictArguments() { + var length, a0, a1, a2, nt; + function f(x) { + 'use strict'; + assertEquals(length, arguments.length); + assertEquals(a0, arguments[0]); + assertEquals(a1, arguments[1]); + assertEquals(a2, arguments[2]); + assertEquals(nt, new.target); + + if (length > 0) { + x = 42; + assertEquals(a0, arguments[0]); + + arguments[0] = 33; + assertEquals(33, arguments[0]); + } + } + + nt = f; + length = 0; + new f(); + + length = 1; + a0 = 1; + new f(1); + + length = 2; + a0 = 1; + a1 = 2; + new f(1, 2); + + length = 3; + a0 = 1; + a1 = 2; + a2 = 3; + new f(1, 2, 3); + + nt = undefined; + a0 = a1 = a2 = undefined; + length = 0; + f(); + + length = 1; + a0 = 1; + f(1); + + length = 2; + a0 = 1; + a1 = 2; + f(1, 2); + + length = 3; + a0 = 1; + a1 = 2; + a2 = 3; + f(1, 2, 3); +})(); diff --git a/deps/v8/test/mjsunit/harmony/object-literals-super.js b/deps/v8/test/mjsunit/harmony/object-literals-super.js index c2d456c877..c6fb6334de 100644 --- a/deps/v8/test/mjsunit/harmony/object-literals-super.js +++ b/deps/v8/test/mjsunit/harmony/object-literals-super.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-classes --allow-natives-syntax +// Flags: --harmony-arrow-functions --allow-natives-syntax (function TestHomeObject() { @@ -131,3 +131,52 @@ assertEquals(42, o.g().next().value); })(); + + +(function TestSuperPropertyInEval() { + var y = 3; + var p = { + m() { return 1; }, + get x() { return 2; } + }; + var o = { + __proto__: p, + evalM() { + assertEquals(1, eval('super.m()')); + }, + evalX() { + assertEquals(2, eval('super.x')); + }, + globalEval1() { + assertThrows('super.x', SyntaxError); + assertThrows('super.m()', SyntaxError); + }, + globalEval2() { + super.x; + assertThrows('super.x', SyntaxError); + assertThrows('super.m()', SyntaxError); + } + }; + o.evalM(); + o.evalX(); + o.globalEval1(); + o.globalEval2(); +})(); + + +(function TestSuperPropertyInArrow() { + var y = 3; + var p = { + m() { return 1; }, + get x() { return 2; } + }; + var o = { + __proto__: p, + arrow() { + assertSame(super.x, (() => super.x)()); + assertSame(super.m(), (() => super.m())()); + return (() => super.m())(); + } + }; + assertSame(1, o.arrow()); +})(); diff --git a/deps/v8/test/mjsunit/harmony/private.js b/deps/v8/test/mjsunit/harmony/private.js index c08daf1050..0adbb13b21 100644 --- a/deps/v8/test/mjsunit/harmony/private.js +++ b/deps/v8/test/mjsunit/harmony/private.js @@ -241,7 +241,8 @@ function TestKeyGet(obj) { var obj2 = Object.create(obj) for (var i in symbols) { assertEquals(i|0, obj[symbols[i]]) - assertEquals(i|0, obj2[symbols[i]]) + // Private symbols key own-properties. + assertEquals(undefined, obj2[symbols[i]]) } } @@ -352,3 +353,52 @@ function TestSealAndFreeze(freeze) { TestSealAndFreeze(Object.seal) TestSealAndFreeze(Object.freeze) TestSealAndFreeze(Object.preventExtensions) + + +var s = %CreatePrivateSymbol("s"); +var s1 = %CreatePrivateSymbol("s1"); + +function TestSimple() { + var p = {} + p[s] = "moo"; + + var o = Object.create(p); + + assertEquals(undefined, o[s]); + assertEquals("moo", p[s]); + + o[s] = "bow-wow"; + assertEquals("bow-wow", o[s]); + assertEquals("moo", p[s]); +} +TestSimple(); + + +function TestICs() { + var p = {} + p[s] = "moo"; + + + var o = Object.create(p); + o[s1] = "bow-wow"; + function checkNonOwn(o) { + assertEquals(undefined, o[s]); + assertEquals("bow-wow", o[s1]); + } + + checkNonOwn(o); + + // Test monomorphic/optimized. + for (var i = 0; i < 1000; i++) { + checkNonOwn(o); + } + + // Test non-monomorphic. + for (var i = 0; i < 1000; i++) { + var oNew = Object.create(p); + oNew["s" + i] = i; + oNew[s1] = "bow-wow"; + checkNonOwn(oNew); + } +} +TestICs(); diff --git a/deps/v8/test/mjsunit/harmony/proxies-for.js b/deps/v8/test/mjsunit/harmony/proxies-for.js index d0f2a022fd..e98c34afe5 100644 --- a/deps/v8/test/mjsunit/harmony/proxies-for.js +++ b/deps/v8/test/mjsunit/harmony/proxies-for.js @@ -165,4 +165,19 @@ TestForInThrow(Proxy.create({ get: function(pr, pk) { return function() { throw "myexn" } } -})) +})); + +(function() { + var p = Proxy.create({enumerate:function() { return [0]; }}); + var o = [0]; + o.__proto__ = p; + var keys = []; + for (var k in o) { keys.push(k); }; + assertEquals(["0"], keys); +})(); + +(function () { + var p = Proxy.create({getOwnPropertyNames: + function() { return [1, Symbol(), 2] }}); + assertEquals(["1","2"], Object.getOwnPropertyNames(p)); +})(); diff --git a/deps/v8/test/mjsunit/harmony/proxies.js b/deps/v8/test/mjsunit/harmony/proxies.js index 2500ecca85..585574eb43 100644 --- a/deps/v8/test/mjsunit/harmony/proxies.js +++ b/deps/v8/test/mjsunit/harmony/proxies.js @@ -29,8 +29,7 @@ // test enters an infinite recursion which goes through the runtime and we // overflow the system stack before the simulator stack. -// Flags: --harmony-proxies --sim-stack-size=500 --turbo-deoptimization -// Flags: --allow-natives-syntax +// Flags: --harmony-proxies --sim-stack-size=500 --allow-natives-syntax // Helper. diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-4160.js b/deps/v8/test/mjsunit/harmony/regress/regress-4160.js new file mode 100644 index 0000000000..b02daeed40 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/regress/regress-4160.js @@ -0,0 +1,29 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-arrow-functions --allow-natives-syntax + +(function(x) { + (function(x) { + var boom = (() => eval(x)); + assertEquals(23, boom()); + assertEquals(23, boom()); + %OptimizeFunctionOnNextCall(boom); + assertEquals(23, boom()); + assertEquals("23", x); + })("23"); + assertEquals("42", x); +})("42"); + +(function(x) { + (function(x) { + var boom = (() => (eval("var x = 66"), x)); + assertEquals(66, boom()); + assertEquals(66, boom()); + %OptimizeFunctionOnNextCall(boom); + assertEquals(66, boom()); + assertEquals("23", x); + })("23"); + assertEquals("42", x); +})("42"); diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-arrow-duplicate-params.js b/deps/v8/test/mjsunit/harmony/regress/regress-arrow-duplicate-params.js new file mode 100644 index 0000000000..a43f022c02 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/regress/regress-arrow-duplicate-params.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-arrow-functions + +assertThrows("(x, x, y) => 10;", SyntaxError); diff --git a/deps/v8/test/mjsunit/harmony/regress/regress-crbug-451770.js b/deps/v8/test/mjsunit/harmony/regress/regress-crbug-451770.js index 942814a316..eaf1d1961f 100644 --- a/deps/v8/test/mjsunit/harmony/regress/regress-crbug-451770.js +++ b/deps/v8/test/mjsunit/harmony/regress/regress-crbug-451770.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-computed-property-names --harmony-classes --harmony-sloppy +// Flags: --harmony-computed-property-names --harmony-sloppy assertThrows(function f() { var t = { toString: function() { throw new Error(); } }; diff --git a/deps/v8/test/mjsunit/harmony/rest-params-lazy-parsing.js b/deps/v8/test/mjsunit/harmony/rest-params-lazy-parsing.js index ba8e3008b9..b50a990f5c 100644 --- a/deps/v8/test/mjsunit/harmony/rest-params-lazy-parsing.js +++ b/deps/v8/test/mjsunit/harmony/rest-params-lazy-parsing.js @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-rest-parameters --min-preparse-length=0 +// Flags: --harmony-rest-parameters --harmony-arrow-functions +// Flags: --min-preparse-length=0 function variadic(co, ...values) { var sum = 0; @@ -12,6 +13,21 @@ function variadic(co, ...values) { return sum; } +var arrowVariadic = (co, ...values) => { + var sum = 0; + while (values.length) { + sum += co * values.pop(); + } + return sum; +} + +assertEquals(1, variadic.length); +assertEquals(1, arrowVariadic.length); + assertEquals(90, variadic(2, 1, 2, 3, 4, 5, 6, 7, 8, 9)); assertEquals(74, variadic(2, 1, 2, 3, 4, 5, 6, 7, 9)); assertEquals(110, variadic(2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); + +assertEquals(90, arrowVariadic(2, 1, 2, 3, 4, 5, 6, 7, 8, 9)); +assertEquals(74, arrowVariadic(2, 1, 2, 3, 4, 5, 6, 7, 9)); +assertEquals(110, arrowVariadic(2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); diff --git a/deps/v8/test/mjsunit/harmony/rest-params.js b/deps/v8/test/mjsunit/harmony/rest-params.js index 341cb33087..fe7ee2adb8 100644 --- a/deps/v8/test/mjsunit/harmony/rest-params.js +++ b/deps/v8/test/mjsunit/harmony/rest-params.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-rest-parameters --harmony-classes +// Flags: --harmony-rest-parameters (function testRestIndex() { assertEquals(5, (function(...args) { return args.length; })(1,2,3,4,5)); diff --git a/deps/v8/test/mjsunit/harmony/set-prototype-of.js b/deps/v8/test/mjsunit/harmony/set-prototype-of.js index e06215a0ed..e92a0c37bc 100644 --- a/deps/v8/test/mjsunit/harmony/set-prototype-of.js +++ b/deps/v8/test/mjsunit/harmony/set-prototype-of.js @@ -139,6 +139,24 @@ function TestSetPrototypeOfNonExtensibleObject() { TestSetPrototypeOfNonExtensibleObject(); +function TestSetPrototypeCyclic() { + var objects = [ + Object.prototype, {}, + Array.prototype, [], + Error.prototype, new TypeError, + // etc ... + ]; + for (var i = 0; i < objects.length; i += 2) { + var object = objects[i]; + var value = objects[i + 1]; + assertThrows(function() { + Object.setPrototypeOf(object, value); + }, TypeError); + } +} +TestSetPrototypeCyclic(); + + function TestLookup() { var object = {}; assertFalse('x' in object); diff --git a/deps/v8/test/mjsunit/harmony/sharedarraybuffer.js b/deps/v8/test/mjsunit/harmony/sharedarraybuffer.js new file mode 100644 index 0000000000..bac42681ab --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/sharedarraybuffer.js @@ -0,0 +1,577 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --harmony-sharedarraybuffer --harmony-tostring + + +// SharedArrayBuffer + +function TestByteLength(param, expectedByteLength) { + var sab = new SharedArrayBuffer(param); + assertSame(expectedByteLength, sab.byteLength); +} + +function TestArrayBufferCreation() { + TestByteLength(1, 1); + TestByteLength(256, 256); + TestByteLength(2.567, 2); + + TestByteLength("abc", 0); + + TestByteLength(0, 0); + + assertThrows(function() { new SharedArrayBuffer(-10); }, RangeError); + assertThrows(function() { new SharedArrayBuffer(-2.567); }, RangeError); + +/* TODO[dslomov]: Reenable the test + assertThrows(function() { + var ab1 = new SharedArrayBuffer(0xFFFFFFFFFFFF) + }, RangeError); +*/ + + var sab = new SharedArrayBuffer(); + assertSame(0, sab.byteLength); + assertEquals("[object SharedArrayBuffer]", + Object.prototype.toString.call(sab)); +} + +TestArrayBufferCreation(); + +function TestByteLengthNotWritable() { + var sab = new SharedArrayBuffer(1024); + assertSame(1024, sab.byteLength); + + assertThrows(function() { "use strict"; sab.byteLength = 42; }, TypeError); +} + +TestByteLengthNotWritable(); + +function TestArrayBufferNoSlice() { + var sab = new SharedArrayBuffer(10); + assertEquals(undefined, sab.slice); +} + +TestArrayBufferNoSlice(); + +// Typed arrays using SharedArrayBuffers + +// TODO(binji): how many of these tests are necessary if there are no new +// TypedArray types? + +function MakeSharedTypedArray(constr, numElements) { + var sab = new SharedArrayBuffer(constr.BYTES_PER_ELEMENT * numElements); + return new constr(sab); +} + +function TestTypedArray(constr, elementSize, typicalElement) { + assertSame(elementSize, constr.BYTES_PER_ELEMENT); + + var sab = new SharedArrayBuffer(256*elementSize); + + var a0 = new constr(30); + assertEquals("[object " + constr.name + "]", + Object.prototype.toString.call(a0)); + + // TODO(binji): Should this return false here? It is a view, but it doesn't + // view a SharedArrayBuffer... + assertTrue(SharedArrayBuffer.isView(a0)); + assertSame(elementSize, a0.BYTES_PER_ELEMENT); + assertSame(30, a0.length); + assertSame(30*elementSize, a0.byteLength); + assertSame(0, a0.byteOffset); + assertSame(30*elementSize, a0.buffer.byteLength); + + var aOverBufferLen0 = new constr(sab, 128*elementSize, 0); + assertSame(sab, aOverBufferLen0.buffer); + assertSame(elementSize, aOverBufferLen0.BYTES_PER_ELEMENT); + assertSame(0, aOverBufferLen0.length); + assertSame(0, aOverBufferLen0.byteLength); + assertSame(128*elementSize, aOverBufferLen0.byteOffset); + + var a1 = new constr(sab, 128*elementSize, 128); + assertSame(sab, a1.buffer); + assertSame(elementSize, a1.BYTES_PER_ELEMENT); + assertSame(128, a1.length); + assertSame(128*elementSize, a1.byteLength); + assertSame(128*elementSize, a1.byteOffset); + + + var a2 = new constr(sab, 64*elementSize, 128); + assertSame(sab, a2.buffer); + assertSame(elementSize, a2.BYTES_PER_ELEMENT); + assertSame(128, a2.length); + assertSame(128*elementSize, a2.byteLength); + assertSame(64*elementSize, a2.byteOffset); + + var a3 = new constr(sab, 192*elementSize); + assertSame(sab, a3.buffer); + assertSame(64, a3.length); + assertSame(64*elementSize, a3.byteLength); + assertSame(192*elementSize, a3.byteOffset); + + var a4 = new constr(sab); + assertSame(sab, a4.buffer); + assertSame(256, a4.length); + assertSame(256*elementSize, a4.byteLength); + assertSame(0, a4.byteOffset); + + + var i; + for (i = 0; i < 128; i++) { + a1[i] = typicalElement; + } + + for (i = 0; i < 128; i++) { + assertSame(typicalElement, a1[i]); + } + + for (i = 0; i < 64; i++) { + assertSame(0, a2[i]); + } + + for (i = 64; i < 128; i++) { + assertSame(typicalElement, a2[i]); + } + + for (i = 0; i < 64; i++) { + assertSame(typicalElement, a3[i]); + } + + for (i = 0; i < 128; i++) { + assertSame(0, a4[i]); + } + + for (i = 128; i < 256; i++) { + assertSame(typicalElement, a4[i]); + } + + var aAtTheEnd = new constr(sab, 256*elementSize); + assertSame(elementSize, aAtTheEnd.BYTES_PER_ELEMENT); + assertSame(0, aAtTheEnd.length); + assertSame(0, aAtTheEnd.byteLength); + assertSame(256*elementSize, aAtTheEnd.byteOffset); + + assertThrows(function () { new constr(sab, 257*elementSize); }, RangeError); + assertThrows( + function () { new constr(sab, 128*elementSize, 192); }, + RangeError); + + if (elementSize !== 1) { + assertThrows(function() { new constr(sab, 128*elementSize - 1, 10); }, + RangeError); + var unalignedArrayBuffer = new SharedArrayBuffer(10*elementSize + 1); + var goodArray = new constr(unalignedArrayBuffer, 0, 10); + assertSame(10, goodArray.length); + assertSame(10*elementSize, goodArray.byteLength); + assertThrows(function() { new constr(unalignedArrayBuffer)}, RangeError); + assertThrows(function() { new constr(unalignedArrayBuffer, 5*elementSize)}, + RangeError); + } + + var abLen0 = new SharedArrayBuffer(0); + var aOverAbLen0 = new constr(abLen0); + assertSame(abLen0, aOverAbLen0.buffer); + assertSame(elementSize, aOverAbLen0.BYTES_PER_ELEMENT); + assertSame(0, aOverAbLen0.length); + assertSame(0, aOverAbLen0.byteLength); + assertSame(0, aOverAbLen0.byteOffset); + + var a = new constr(sab, 64*elementSize, 128); + assertEquals("[object " + constr.name + "]", + Object.prototype.toString.call(a)); + var desc = Object.getOwnPropertyDescriptor( + constr.prototype, Symbol.toStringTag); + assertTrue(desc.configurable); + assertFalse(desc.enumerable); + assertFalse(!!desc.writable); + assertFalse(!!desc.set); + assertEquals("function", typeof desc.get); +} + +TestTypedArray(Uint8Array, 1, 0xFF); +TestTypedArray(Int8Array, 1, -0x7F); +TestTypedArray(Uint16Array, 2, 0xFFFF); +TestTypedArray(Int16Array, 2, -0x7FFF); +TestTypedArray(Uint32Array, 4, 0xFFFFFFFF); +TestTypedArray(Int32Array, 4, -0x7FFFFFFF); +TestTypedArray(Float32Array, 4, 0.5); +TestTypedArray(Float64Array, 8, 0.5); +TestTypedArray(Uint8ClampedArray, 1, 0xFF); + + +function SubarrayTestCase(constructor, item, expectedResultLen, + expectedStartIndex, initialLen, start, end) { + var a = MakeSharedTypedArray(constructor, initialLen); + var s = a.subarray(start, end); + assertSame(constructor, s.constructor); + assertSame(expectedResultLen, s.length); + if (s.length > 0) { + s[0] = item; + assertSame(item, a[expectedStartIndex]); + } +} + +function TestSubArray(constructor, item) { + SubarrayTestCase(constructor, item, 512, 512, 1024, 512, 1024); + SubarrayTestCase(constructor, item, 512, 512, 1024, 512); + + SubarrayTestCase(constructor, item, 0, undefined, 0, 1, 20); + SubarrayTestCase(constructor, item, 100, 0, 100, 0, 100); + SubarrayTestCase(constructor, item, 100, 0, 100, 0, 1000); + SubarrayTestCase(constructor, item, 0, undefined, 100, 5, 1); + + SubarrayTestCase(constructor, item, 1, 89, 100, -11, -10); + SubarrayTestCase(constructor, item, 9, 90, 100, -10, 99); + SubarrayTestCase(constructor, item, 0, undefined, 100, -10, 80); + SubarrayTestCase(constructor, item, 10,80, 100, 80, -10); + + SubarrayTestCase(constructor, item, 10,90, 100, 90, "100"); + SubarrayTestCase(constructor, item, 10,90, 100, "90", "100"); + + SubarrayTestCase(constructor, item, 0, undefined, 100, 90, "abc"); + SubarrayTestCase(constructor, item, 10,0, 100, "abc", 10); + + SubarrayTestCase(constructor, item, 10,0, 100, 0.96, 10.96); + SubarrayTestCase(constructor, item, 10,0, 100, 0.96, 10.01); + SubarrayTestCase(constructor, item, 10,0, 100, 0.01, 10.01); + SubarrayTestCase(constructor, item, 10,0, 100, 0.01, 10.96); + + + SubarrayTestCase(constructor, item, 10,90, 100, 90); + SubarrayTestCase(constructor, item, 10,90, 100, -10); +} + +TestSubArray(Uint8Array, 0xFF); +TestSubArray(Int8Array, -0x7F); +TestSubArray(Uint16Array, 0xFFFF); +TestSubArray(Int16Array, -0x7FFF); +TestSubArray(Uint32Array, 0xFFFFFFFF); +TestSubArray(Int32Array, -0x7FFFFFFF); +TestSubArray(Float32Array, 0.5); +TestSubArray(Float64Array, 0.5); +TestSubArray(Uint8ClampedArray, 0xFF); + +function TestTypedArrayOutOfRange(constructor, value, result) { + var a = MakeSharedTypedArray(constructor, 1); + a[0] = value; + assertSame(result, a[0]); +} + +TestTypedArrayOutOfRange(Uint8Array, 0x1FA, 0xFA); +TestTypedArrayOutOfRange(Uint8Array, -1, 0xFF); + +TestTypedArrayOutOfRange(Int8Array, 0x1FA, 0x7A - 0x80); + +TestTypedArrayOutOfRange(Uint16Array, 0x1FFFA, 0xFFFA); +TestTypedArrayOutOfRange(Uint16Array, -1, 0xFFFF); +TestTypedArrayOutOfRange(Int16Array, 0x1FFFA, 0x7FFA - 0x8000); + +TestTypedArrayOutOfRange(Uint32Array, 0x1FFFFFFFA, 0xFFFFFFFA); +TestTypedArrayOutOfRange(Uint32Array, -1, 0xFFFFFFFF); +TestTypedArrayOutOfRange(Int32Array, 0x1FFFFFFFA, 0x7FFFFFFA - 0x80000000); + +TestTypedArrayOutOfRange(Uint8ClampedArray, 0x1FA, 0xFF); +TestTypedArrayOutOfRange(Uint8ClampedArray, -1, 0); + +var typedArrayConstructors = [ + Uint8Array, + Int8Array, + Uint16Array, + Int16Array, + Uint32Array, + Int32Array, + Uint8ClampedArray, + Float32Array, + Float64Array]; + +function TestPropertyTypeChecks(constructor) { + function CheckProperty(name) { + var d = Object.getOwnPropertyDescriptor(constructor.prototype, name); + var o = {}; + assertThrows(function() {d.get.call(o);}, TypeError); + for (var i = 0; i < typedArrayConstructors.length; i++) { + var ctor = typedArrayConstructors[i]; + var a = MakeSharedTypedArray(ctor, 10); + if (ctor === constructor) { + d.get.call(a); // shouldn't throw + } else { + assertThrows(function() {d.get.call(a);}, TypeError); + } + } + } + + CheckProperty("buffer"); + CheckProperty("byteOffset"); + CheckProperty("byteLength"); + CheckProperty("length"); +} + +for(i = 0; i < typedArrayConstructors.length; i++) { + TestPropertyTypeChecks(typedArrayConstructors[i]); +} + +function TestTypedArraySet() { + // Test array.set in different combinations. + + function assertArrayPrefix(expected, array) { + for (var i = 0; i < expected.length; ++i) { + assertEquals(expected[i], array[i]); + } + } + + // SharedTypedArrays don't allow initialization via array-like + function initializeFromArray(constructor, array) { + var buffer = MakeSharedTypedArray(constructor, array.length); + for (var i = 0; i < array.length; ++i) { + buffer[i] = array[i]; + } + return buffer; + } + + var a11 = initializeFromArray(Int16Array, [1, 2, 3, 4, 0, -1]) + var a12 = MakeSharedTypedArray(Uint16Array, 15); + a12.set(a11, 3) + assertArrayPrefix([0, 0, 0, 1, 2, 3, 4, 0, 0xffff, 0, 0], a12) + assertThrows(function(){ a11.set(a12) }) + + var a21 = [1, undefined, 10, NaN, 0, -1, {valueOf: function() {return 3}}] + var a22 = MakeSharedTypedArray(Int32Array, 12) + a22.set(a21, 2) + assertArrayPrefix([0, 0, 1, 0, 10, 0, 0, -1, 3, 0], a22) + + var a31 = initializeFromArray(Float32Array, [2, 4, 6, 8, 11, NaN, 1/0, -3]) + var a32 = a31.subarray(2, 6) + a31.set(a32, 4) + assertArrayPrefix([2, 4, 6, 8, 6, 8, 11, NaN], a31) + assertArrayPrefix([6, 8, 6, 8], a32) + + var a4 = initializeFromArray(Uint8ClampedArray, [3,2,5,6]) + a4.set(a4) + assertArrayPrefix([3, 2, 5, 6], a4) + + // Cases with overlapping backing store but different element sizes. + var b = new SharedArrayBuffer(4) + var a5 = new Int16Array(b) + var a50 = new Int8Array(b) + var a51 = new Int8Array(b, 0, 2) + var a52 = new Int8Array(b, 1, 2) + var a53 = new Int8Array(b, 2, 2) + + a5.set([0x5050, 0x0a0a]) + assertArrayPrefix([0x50, 0x50, 0x0a, 0x0a], a50) + assertArrayPrefix([0x50, 0x50], a51) + assertArrayPrefix([0x50, 0x0a], a52) + assertArrayPrefix([0x0a, 0x0a], a53) + + a50.set([0x50, 0x50, 0x0a, 0x0a]) + a51.set(a5) + assertArrayPrefix([0x50, 0x0a, 0x0a, 0x0a], a50) + + a50.set([0x50, 0x50, 0x0a, 0x0a]) + a52.set(a5) + assertArrayPrefix([0x50, 0x50, 0x0a, 0x0a], a50) + + a50.set([0x50, 0x50, 0x0a, 0x0a]) + a53.set(a5) + assertArrayPrefix([0x50, 0x50, 0x50, 0x0a], a50) + + a50.set([0x50, 0x51, 0x0a, 0x0b]) + a5.set(a51) + assertArrayPrefix([0x0050, 0x0051], a5) + + a50.set([0x50, 0x51, 0x0a, 0x0b]) + a5.set(a52) + assertArrayPrefix([0x0051, 0x000a], a5) + + a50.set([0x50, 0x51, 0x0a, 0x0b]) + a5.set(a53) + assertArrayPrefix([0x000a, 0x000b], a5) + + // Mixed types of same size. + var a61 = initializeFromArray(Float32Array, [1.2, 12.3]) + var a62 = MakeSharedTypedArray(Int32Array, 2) + a62.set(a61) + assertArrayPrefix([1, 12], a62) + a61.set(a62) + assertArrayPrefix([1, 12], a61) + + // Invalid source + var a = MakeSharedTypedArray(Uint16Array, 50); + var expected = []; + for (i = 0; i < 50; i++) { + a[i] = i; + expected.push(i); + } + a.set({}); + assertArrayPrefix(expected, a); + assertThrows(function() { a.set.call({}) }, TypeError); + assertThrows(function() { a.set.call([]) }, TypeError); + + assertThrows(function() { a.set(0); }, TypeError); + assertThrows(function() { a.set(0, 1); }, TypeError); +} + +TestTypedArraySet(); + +function TestTypedArraysWithIllegalIndices() { + var a = MakeSharedTypedArray(Int32Array, 100); + + a[-10] = 10; + assertEquals(undefined, a[-10]); + a["-10"] = 10; + assertEquals(undefined, a["-10"]); + + var s = " -10"; + a[s] = 10; + assertEquals(10, a[s]); + var s1 = " -10 "; + a[s] = 10; + assertEquals(10, a[s]); + + a["-1e2"] = 10; + assertEquals(10, a["-1e2"]); + assertEquals(undefined, a[-1e2]); + + a["-0"] = 256; + var s2 = " -0"; + a[s2] = 255; + assertEquals(undefined, a["-0"]); + assertEquals(255, a[s2]); + assertEquals(0, a[-0]); + + /* Chromium bug: 424619 + * a[-Infinity] = 50; + * assertEquals(undefined, a[-Infinity]); + */ + a[1.5] = 10; + assertEquals(undefined, a[1.5]); + var nan = Math.sqrt(-1); + a[nan] = 5; + assertEquals(undefined, a[nan]); + + var x = 0; + var y = -0; + assertEquals(Infinity, 1/x); + assertEquals(-Infinity, 1/y); + a[x] = 5; + a[y] = 27; + assertEquals(27, a[x]); + assertEquals(27, a[y]); +} + +TestTypedArraysWithIllegalIndices(); + +function TestTypedArraysWithIllegalIndicesStrict() { + 'use strict'; + var a = MakeSharedTypedArray(Int32Array, 100); + + a[-10] = 10; + assertEquals(undefined, a[-10]); + a["-10"] = 10; + assertEquals(undefined, a["-10"]); + + var s = " -10"; + a[s] = 10; + assertEquals(10, a[s]); + var s1 = " -10 "; + a[s] = 10; + assertEquals(10, a[s]); + + a["-1e2"] = 10; + assertEquals(10, a["-1e2"]); + assertEquals(undefined, a[-1e2]); + + a["-0"] = 256; + var s2 = " -0"; + a[s2] = 255; + assertEquals(undefined, a["-0"]); + assertEquals(255, a[s2]); + assertEquals(0, a[-0]); + + /* Chromium bug: 424619 + * a[-Infinity] = 50; + * assertEquals(undefined, a[-Infinity]); + */ + a[1.5] = 10; + assertEquals(undefined, a[1.5]); + var nan = Math.sqrt(-1); + a[nan] = 5; + assertEquals(undefined, a[nan]); + + var x = 0; + var y = -0; + assertEquals(Infinity, 1/x); + assertEquals(-Infinity, 1/y); + a[x] = 5; + a[y] = 27; + assertEquals(27, a[x]); + assertEquals(27, a[y]); +} + +TestTypedArraysWithIllegalIndicesStrict(); + +// General tests for properties + +// Test property attribute [[Enumerable]] +function TestEnumerable(func, obj) { + function props(x) { + var array = []; + for (var p in x) array.push(p); + return array.sort(); + } + assertArrayEquals([], props(func)); + assertArrayEquals([], props(func.prototype)); + if (obj) + assertArrayEquals([], props(obj)); +} +TestEnumerable(ArrayBuffer, new SharedArrayBuffer()); +for(i = 0; i < typedArrayConstructors.length; i++) { + TestEnumerable(typedArrayConstructors[i]); +} + +// Test arbitrary properties on ArrayBuffer +function TestArbitrary(m) { + function TestProperty(map, property, value) { + map[property] = value; + assertEquals(value, map[property]); + } + for (var i = 0; i < 20; i++) { + TestProperty(m, 'key' + i, 'val' + i); + TestProperty(m, 'foo' + i, 'bar' + i); + } +} +TestArbitrary(new SharedArrayBuffer(256)); +for(i = 0; i < typedArrayConstructors.length; i++) { + TestArbitrary(MakeSharedTypedArray(typedArrayConstructors[i], 10)); +} + +// Test direct constructor call +assertThrows(function() { SharedArrayBuffer(); }, TypeError); +for(i = 0; i < typedArrayConstructors.length; i++) { + assertThrows(function(i) { typedArrayConstructors[i](); }.bind(this, i), + TypeError); +} diff --git a/deps/v8/test/mjsunit/harmony/spread-array.js b/deps/v8/test/mjsunit/harmony/spread-array.js new file mode 100644 index 0000000000..18b72a28c5 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/spread-array.js @@ -0,0 +1,179 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-spread-arrays --allow-natives-syntax + +(function TestBasics() { + var a = [1, 2]; + var b = [...a]; + assertArrayEquals([1, 2], b) + + assertArrayEquals(['a', 'b', 'c', 'd', 'e', 'f'], + ['a', ...'bc', 'd', ...'ef']) +})(); + + +var log = []; + +function* gen(n) { + log.push(n, 1); + yield 1; + log.push(n, 2); + yield 2; + log.push(n, 3); + yield 3; + log.push(n, 'done'); +} + +function id(v) { + log.push(v); + return v; +} + + +(function TestGenerator() { + assertArrayEquals([1, 2, 3], [...gen('a')]); + assertArrayEquals(['x', 1, 2, 3, 'y', 1, 2, 3, 'z'], + ['x', ...gen('a'), 'y', ...gen('b'), 'z']); +})(); + + +(function TestOrderOfExecution() { + log = []; + assertArrayEquals(['x', 1, 2, 3, 'y', 1, 2, 3, 'z'], + [id('x'), ...gen('a'), id('y'), ...gen('b'), id('z')]); + assertArrayEquals([ + 'x', 'a', 1, 'a', 2, 'a', 3, 'a', 'done', + 'y', 'b', 1, 'b', 2, 'b', 3, 'b', 'done', + 'z' + ], log); +})(); + + +(function TestNotIterable() { + var a; + assertThrows(function() { + a = [...42]; + }, TypeError); + assertSame(undefined, a); + + +})(); + + +(function TestInvalidIterator() { + var iter = { + [Symbol.iterator]: 42 + }; + var a; + assertThrows(function() { + a = [...iter]; + }, TypeError); + assertSame(undefined, a); +})(); + + +(function TestIteratorNotAnObject() { + var iter = { + [Symbol.iterator]() { + return 42; + } + }; + var a; + assertThrows(function() { + a = [...iter]; + }, TypeError); + assertSame(undefined, a); +})(); + + +(function TestIteratorNoNext() { + var iter = { + [Symbol.iterator]() { + return {}; + } + }; + var a; + assertThrows(function() { + a = [...iter]; + }, TypeError); + assertSame(undefined, a); +})(); + + +(function TestIteratorResultDoneThrows() { + function MyError() {} + var iter = { + [Symbol.iterator]() { + return { + next() { + return { + get done() { + throw new MyError(); + } + } + } + }; + } + }; + var a; + assertThrows(function() { + a = [...iter]; + }, MyError); + assertSame(undefined, a); +})(); + + +(function TestIteratorResultValueThrows() { + function MyError() {} + var iter = { + [Symbol.iterator]() { + return { + next() { + return { + done: false, + get value() { + throw new MyError(); + } + } + } + }; + } + }; + var a; + assertThrows(function() { + a = [...iter]; + }, MyError); + assertSame(undefined, a); +})(); + + +(function TestOptimize() { + function f() { + return [...'abc']; + } + assertArrayEquals(['a', 'b', 'c'], f()); + %OptimizeFunctionOnNextCall(f); + assertArrayEquals(['a', 'b', 'c'], f()); +})(); + + +(function TestDeoptimize() { + var iter = { + [Symbol.iterator]() { + var i = 0; + return { + next() { + $DeoptimizeFunction(f); + return {value: ++i, done: i === 3}; + } + }; + } + }; + function f() { + return [0, ...iter]; + } + + assertArrayEquals([0, 1, 2], f()); +}); diff --git a/deps/v8/test/mjsunit/harmony/spread-call-super-property.js b/deps/v8/test/mjsunit/harmony/spread-call-super-property.js new file mode 100644 index 0000000000..cdf6f2e242 --- /dev/null +++ b/deps/v8/test/mjsunit/harmony/spread-call-super-property.js @@ -0,0 +1,20 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-spreadcalls --harmony-sloppy --harmony-rest-parameters + +(function testCallSuperProperty() { + class BaseClass { + strict_method(...args) { "use strict"; return [this].concat(args); } + sloppy_method(...args) { return [this].concat(args); } + } + class SubClass extends BaseClass { + strict_m(...args) { return super.strict_method(...args); } + sloppy_m(...args) { return super.sloppy_method(...args); } + } + + var c = new SubClass(); + assertEquals([c, 1, 2, 3, 4, 5], c.strict_m(1, 2, 3, 4, 5)); + assertEquals([c, 1, 2, 3, 4, 5], c.sloppy_m(1, 2, 3, 4, 5)); +})(); diff --git a/deps/v8/test/mjsunit/harmony/super.js b/deps/v8/test/mjsunit/harmony/super.js index 988cef22e2..21b31d96c9 100644 --- a/deps/v8/test/mjsunit/harmony/super.js +++ b/deps/v8/test/mjsunit/harmony/super.js @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-classes --allow-natives-syntax +// Flags: --harmony-arrow-functions --allow-natives-syntax +// Flags: --harmony-spreadcalls (function TestSuperNamedLoads() { function Base() { } @@ -2053,6 +2054,7 @@ TestKeyedSetterCreatingOwnPropertiesNonConfigurable(42, 43, 44); assertInstanceof(f, Number); }()); + (function TestSuperCallErrorCases() { 'use strict'; class T extends Object { @@ -2064,3 +2066,150 @@ TestKeyedSetterCreatingOwnPropertiesNonConfigurable(42, 43, 44); T.__proto__ = null; assertThrows(function() { new T(); }, TypeError); }()); + + +(function TestSuperPropertyInEval() { + 'use strict'; + let y = 3; + class Base { + m() { return 1; } + get x() { return 2; } + } + class Derived extends Base { + evalM() { + assertEquals(1, eval('super.m()')); + } + evalX() { + assertEquals(2, eval('super.x')); + } + globalEval1() { + assertThrows('super.x', SyntaxError); + assertThrows('super.m()', SyntaxError); + } + globalEval2() { + super.x; + assertThrows('super.x', SyntaxError); + assertThrows('super.m()', SyntaxError); + } + } + let d = new Derived(); + d.globalEval1(); + d.globalEval2(); + d.evalM(); + d.evalX(); +})(); + + +(function TestSuperPropertyInArrow() { + 'use strict'; + let y = 3; + class Base { + m() { return 1; } + get x() { return 2; } + } + class Derived extends Base { + arrow() { + assertSame(super.x, (() => super.x)()); + assertSame(super.m(), (() => super.m())()); + return (() => super.m())(); + } + } + let d = new Derived(); + assertSame(1, d.arrow()); +})(); + + +(function TestSuperCallInEval() { + 'use strict'; + class Base { + constructor(x) { + this.x = x; + } + } + class Derived extends Base { + constructor(x) { + eval('super(x)'); + } + } + let d = new Derived(42); + assertSame(42, d.x); +})(); + + +(function TestSuperCallInArrow() { + 'use strict'; + class Base { + constructor(x) { + this.x = x; + } + } + class Derived extends Base { + constructor(x) { + (() => super(x))(); + } + } + let d = new Derived(42); + assertSame(42, d.x); +})(); + + +(function TestSuperCallEscapes() { + 'use strict'; + class Base { + constructor(x) { + this.x = x; + } + } + + let f; + class Derived extends Base { + constructor() { + f = () => super(2); + } + } + assertThrows(function() { + new Derived(); + }, ReferenceError); + + let o = f(); + assertEquals(2, o.x); + assertInstanceof(o, Derived); + + assertThrows(function() { + f(); + }, ReferenceError); +})(); + + +(function TestSuperCallSpreadInEval() { + 'use strict'; + class Base { + constructor(x) { + this.x = x; + } + } + class Derived extends Base { + constructor(x) { + eval('super(...[x])'); + } + } + let d = new Derived(42); + assertSame(42, d.x); +})(); + + +(function TestSuperCallSpreadInArrow() { + 'use strict'; + class Base { + constructor(x) { + this.x = x; + } + } + class Derived extends Base { + constructor(x) { + (() => super(...[x]))(); + } + } + let d = new Derived(42); + assertSame(42, d.x); +})(); diff --git a/deps/v8/test/mjsunit/has-own-property-evaluation-order.js b/deps/v8/test/mjsunit/has-own-property-evaluation-order.js new file mode 100644 index 0000000000..ae02180396 --- /dev/null +++ b/deps/v8/test/mjsunit/has-own-property-evaluation-order.js @@ -0,0 +1,13 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function MyError() {} + +assertThrows(function() { + Object.prototype.hasOwnProperty.call(null, { + toString() { + throw new MyError(); + } + }); +}, MyError); diff --git a/deps/v8/test/mjsunit/json-replacer-number-wrapper-tostring.js b/deps/v8/test/mjsunit/json-replacer-number-wrapper-tostring.js new file mode 100644 index 0000000000..b4ef7923cf --- /dev/null +++ b/deps/v8/test/mjsunit/json-replacer-number-wrapper-tostring.js @@ -0,0 +1,20 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// http://ecma-international.org/ecma-262/6.0/#sec-json.stringify +// Step 4.b.iii.5.f.i + +var calls = 0; + +var num = new Number; +num.toString = function() { + calls++; + return ''; +}; +num.valueOf = function() { + assertUnreachable(); +}; + +JSON.stringify('', [num]); +assertEquals(1, calls); diff --git a/deps/v8/test/mjsunit/json-replacer-order.js b/deps/v8/test/mjsunit/json-replacer-order.js new file mode 100644 index 0000000000..8cb64414e7 --- /dev/null +++ b/deps/v8/test/mjsunit/json-replacer-order.js @@ -0,0 +1,26 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// http://ecma-international.org/ecma-262/6.0/#sec-json.stringify +// Step 4.b.iii.5.f.i + +var log = []; + +var replacer = Object.defineProperty([], 0, { + get() { + log.push('get 0'); + } +}); +var space = Object.defineProperty(new String, 'toString', { + value() { + log.push('toString'); + return ''; + } +}); + +JSON.stringify('', replacer, space); + +assertEquals(2, log.length); +assertEquals('get 0', log[0]); +assertEquals('toString', log[1]); diff --git a/deps/v8/test/mjsunit/math-abs.js b/deps/v8/test/mjsunit/math-abs.js index b90ae0917c..4fb72baaa9 100644 --- a/deps/v8/test/mjsunit/math-abs.js +++ b/deps/v8/test/mjsunit/math-abs.js @@ -120,3 +120,19 @@ assertEquals(1, foo2()); assertEquals(1, foo2()); %OptimizeFunctionOnNextCall(foo2); assertEquals(1, foo2()); + +// Regression test for Integer input of Math.abs on mips64. +function absHalf(bits) { + var x = 1 << (bits - 1); + var half = Math.abs(x); + return half; + +} + +// Create minimum integer input for abs() using bitwise operations +// that should overflow. +bits = 32; +assertEquals(2147483648, absHalf(bits)); +assertEquals(2147483648, absHalf(bits)); +%OptimizeFunctionOnNextCall(absHalf); +assertEquals(2147483648, absHalf(bits)); diff --git a/deps/v8/test/mjsunit/math-floor-negative.js b/deps/v8/test/mjsunit/math-floor-negative.js index 4cabff577e..e39d5ade4b 100644 --- a/deps/v8/test/mjsunit/math-floor-negative.js +++ b/deps/v8/test/mjsunit/math-floor-negative.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --noenable_sse4_1 --allow-natives-syntax +// Flags: --noenable-sse4-1 --allow-natives-syntax function test1() { // Trigger overflow when converting/truncating double to integer. diff --git a/deps/v8/test/mjsunit/math-floor-of-div-minus-zero.js b/deps/v8/test/mjsunit/math-floor-of-div-minus-zero.js index 269e96f50b..de0e90bcec 100644 --- a/deps/v8/test/mjsunit/math-floor-of-div-minus-zero.js +++ b/deps/v8/test/mjsunit/math-floor-of-div-minus-zero.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --allow-natives-syntax --nouse_inlining +// Flags: --allow-natives-syntax --nouse-inlining // Test for negative zero that doesn't need bail out diff --git a/deps/v8/test/mjsunit/math-floor-of-div-nosudiv.js b/deps/v8/test/mjsunit/math-floor-of-div-nosudiv.js index 3ce966cb29..bf7a4ce38a 100644 --- a/deps/v8/test/mjsunit/math-floor-of-div-nosudiv.js +++ b/deps/v8/test/mjsunit/math-floor-of-div-nosudiv.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --allow-natives-syntax --nouse_inlining --noenable_sudiv +// Flags: --allow-natives-syntax --nouse-inlining --noenable-sudiv // Use this function as reference. Make sure it is not inlined. function div(a, b) { diff --git a/deps/v8/test/mjsunit/math-floor-of-div.js b/deps/v8/test/mjsunit/math-floor-of-div.js index 707f65714e..9769561c1c 100644 --- a/deps/v8/test/mjsunit/math-floor-of-div.js +++ b/deps/v8/test/mjsunit/math-floor-of-div.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --allow-natives-syntax --nouse_inlining --enable_sudiv +// Flags: --allow-natives-syntax --nouse-inlining --enable-sudiv // Use this function as reference. Make sure it is not inlined. function div(a, b) { diff --git a/deps/v8/test/mjsunit/messages.js b/deps/v8/test/mjsunit/messages.js index 73cc15ac40..c30e59f3e1 100644 --- a/deps/v8/test/mjsunit/messages.js +++ b/deps/v8/test/mjsunit/messages.js @@ -3,7 +3,7 @@ // found in the LICENSE file. // Flags: --stack-size=100 --harmony --harmony-reflect --harmony-arrays -// Flags: --harmony-regexps +// Flags: --harmony-regexps --strong-mode function test(f, expected, type) { try { @@ -62,11 +62,30 @@ test(function() { Array.prototype.shift.call(null); }, "Array.prototype.shift called on null or undefined", TypeError); +// kCannotPreventExtExternalArray +test(function() { + Object.preventExtensions(new Uint16Array(1)); +}, "Cannot prevent extension of an object with external array elements", TypeError); + +// kConstAssign +test(function() { + "use strict"; + const a = 1; + a = 2; +}, "Assignment to constant variable.", TypeError); + // kCannotConvertToPrimitive test(function() { [].join(Object(Symbol(1))); }, "Cannot convert object to primitive value", TypeError); +// kCircularStructure +test(function() { + var o = {}; + o.o = o; + JSON.stringify(o); +}, "Converting circular structure to JSON", TypeError); + // kConstructorNotFunction test(function() { Uint16Array(1); @@ -160,6 +179,11 @@ test(function() { new Symbol(); }, "Symbol is not a constructor", TypeError); +// kNotDateObject +test(function() { + Date.prototype.setHours.call(1); +}, "this is not a Date object.", TypeError); + // kNotGeneric test(function() { String.prototype.toString.call(1); @@ -204,6 +228,14 @@ test(function() { Object.defineProperty({}, "x", { get: 1 }); }, "Getter must be a function: 1", TypeError); +// kObjectNotExtensible +test(function() { + "use strict"; + var o = {}; + Object.freeze(o); + o.a = 1; +}, "Can't add property a, object is not extensible", TypeError); + // kObjectSetterExpectingFunction test(function() { ({}).__defineSetter__("x", 0); @@ -248,6 +280,34 @@ test(function() { new Promise(1); }, "Promise resolver 1 is not a function", TypeError); +// kStrictDeleteProperty +test(function() { + "use strict"; + var o = {}; + Object.defineProperty(o, "p", { value: 1, writable: false }); + delete o.p; +}, "Cannot delete property 'p' of #<Object>", TypeError); + +// kStrictPoisonPill +test(function() { + "use strict"; + arguments.callee; +}, "'caller', 'callee', and 'arguments' properties may not be accessed on " + + "strict mode functions or the arguments objects for calls to them", + TypeError); + +// kStrictReadOnlyProperty +test(function() { + "use strict"; + (1).a = 1; +}, "Cannot assign to read only property 'a' of 1", TypeError); + +// kStrongImplicitCast +test(function() { + "use strong"; + "a" + 1; +}, "In strong mode, implicit conversions are deprecated", TypeError); + // kSymbolToPrimitive test(function() { 1 + Object(Symbol()); @@ -293,15 +353,47 @@ test(function() { }, "Reflect.construct: Arguments list has wrong type", TypeError); -//=== SyntaxError === +// === SyntaxError === + +// kInvalidRegExpFlags +test(function() { + /a/x.test("a"); +}, "Invalid flags supplied to RegExp constructor 'x'", SyntaxError); + +// kMalformedRegExp +test(function() { + /(/.test("a"); +}, "Invalid regular expression: /(/: Unterminated group", SyntaxError); +// kParenthesisInArgString test(function() { new Function(")", ""); }, "Function arg string contains parenthesis", SyntaxError); +// kUnexpectedEOS +test(function() { + JSON.parse("{") +}, "Unexpected end of input", SyntaxError); + +// kUnexpectedToken +test(function() { + JSON.parse("/") +}, "Unexpected token /", SyntaxError); + +// kUnexpectedTokenNumber +test(function() { + JSON.parse("{ 1") +}, "Unexpected number", SyntaxError); + +// kUnexpectedTokenString +test(function() { + JSON.parse('"""') +}, "Unexpected string", SyntaxError); + // === ReferenceError === +// kNotDefined test(function() { "use strict"; o; @@ -313,7 +405,7 @@ test(function() { test(function() { "use strict"; Object.defineProperty([], "length", { value: 1E100 }); -}, "defineProperty() array length out of range", RangeError); +}, "Invalid array length", RangeError); // kInvalidArrayBufferLength test(function() { diff --git a/deps/v8/test/mjsunit/migrations.js b/deps/v8/test/mjsunit/migrations.js index 6a2ea64a7a..288bc61031 100644 --- a/deps/v8/test/mjsunit/migrations.js +++ b/deps/v8/test/mjsunit/migrations.js @@ -278,18 +278,6 @@ var migrations = [ migr: function(o, i) { Object.observe(o, function(){}); }, }, { - name: "%EnableAccessChecks", - migr: function(o, i) { - if (typeof (o) !== 'function') %EnableAccessChecks(o); - }, - }, - { - name: "%DisableAccessChecks", - migr: function(o, i) { - if ((typeof (o) !== 'function') && (o !== global)) %DisableAccessChecks(o); - }, - }, - { name: "seal", migr: function(o, i) { Object.seal(o); }, }, diff --git a/deps/v8/test/mjsunit/mjsunit.status b/deps/v8/test/mjsunit/mjsunit.status index 71a7de4ec7..6c6a9b9755 100644 --- a/deps/v8/test/mjsunit/mjsunit.status +++ b/deps/v8/test/mjsunit/mjsunit.status @@ -118,6 +118,8 @@ 'regress/regress-crbug-107996': [PASS, NO_VARIANTS], 'regress/regress-crbug-171715': [PASS, NO_VARIANTS], 'regress/regress-crbug-222893': [PASS, NO_VARIANTS], + 'regress/regress-crbug-323936': [PASS, NO_VARIANTS], + 'regress/regress-crbug-491943': [PASS, NO_VARIANTS], 'regress/regress-325676': [PASS, NO_VARIANTS], 'debug-evaluate-closure': [PASS, NO_VARIANTS], 'debug-evaluate-with': [PASS, NO_VARIANTS], @@ -168,18 +170,20 @@ ############################################################################## # Only RegExp stuff tested, no need for extensive optimizing compiler tests. 'regexp-global': [PASS, NO_VARIANTS], - 'third_party/regexp-pcre': [PASS, NO_VARIANTS], + 'third_party/regexp-pcre/regexp-pcre': [PASS, NO_VARIANTS], ############################################################################## # No need to waste time for this test. 'd8-performance-now': [PASS, NO_VARIANTS], + 'regress/regress-crbug-491062': [PASS, NO_VARIANTS], # Issue 488: this test sometimes times out. 'array-constructor': [PASS, TIMEOUT], # Very slow on ARM and MIPS, contains no architecture dependent code. - 'unicode-case-overoptimization': [PASS, NO_VARIANTS, ['arch == arm or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips', TIMEOUT]], - 'regress/regress-3976': [PASS, NO_VARIANTS, ['arch == arm or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips', SKIP]], + 'unicode-case-overoptimization': [PASS, NO_VARIANTS, ['arch == arm or arch == arm64 or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips', TIMEOUT]], + 'regress/regress-3976': [PASS, NO_VARIANTS, ['arch == arm or arch == arm64 or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips', SKIP]], + 'regress/regress-crbug-482998': [PASS, NO_VARIANTS, ['arch == arm or arch == arm64 or arch == android_arm or arch == android_arm64 or arch == mipsel or arch == mips64el or arch == mips', SKIP]], ############################################################################## # This test expects to reach a certain recursion depth, which may not work @@ -242,6 +246,13 @@ 'regress/regress-3116': [PASS, ['isolates', FLAKY]], }], # ALWAYS +['novfp3 == True', { + 'asm/embenchen/box2d': [SKIP], + 'asm/embenchen/zlib': [SKIP], + 'asm/embenchen/memops': [SKIP], + 'asm/embenchen/lua_binarytrees': [SKIP], +}], # novfp3 == True + ############################################################################## ['gc_stress == True', { # Skip tests not suitable for GC stress. @@ -293,8 +304,8 @@ # Issue 478788. 'es7/object-observe': [SKIP], - # Issue 3803. - 'es6/generators-iteration': [PASS, FLAKY], + # BUG(v8:4237) + 'regress/regress-3976': [SKIP], }], # 'gc_stress == True' ############################################################################## @@ -343,9 +354,6 @@ 'regress/regress-2185-2': [PASS, TIMEOUT], 'whitespaces': [PASS, TIMEOUT, SLOW], - # BUG(v8:3147). It works on other architectures by accident. - 'regress/regress-conditional-position': [FAIL], - # BUG(v8:3457). 'deserialize-reference': [PASS, FAIL], @@ -408,6 +416,9 @@ 'big-array-literal': [SKIP], 'big-object-literal': [SKIP], 'regress/regress-crbug-178790': [SKIP], + + # Exception thrown during bootstrapping on ASAN builds, see issue 4236. + 'regress/regress-1132': [SKIP], }], # 'asan == True' ############################################################################## @@ -630,12 +641,6 @@ }], # 'arch == nacl_ia32 or arch == nacl_x64' ############################################################################## -['arch == x87', { - # Currently Turbofan is not supported by x87. - 'compiler/opt-next-call-turbo': [SKIP], -}], # 'arch == x87' - -############################################################################## ['deopt_fuzzer == True', { # Skip tests that are not suitable for deoptimization fuzzing. diff --git a/deps/v8/test/mjsunit/own-symbols.js b/deps/v8/test/mjsunit/own-symbols.js deleted file mode 100644 index 588a032aa8..0000000000 --- a/deps/v8/test/mjsunit/own-symbols.js +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2014 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Flags: --allow-natives-syntax - -var s = %CreatePrivateOwnSymbol("s"); -var s1 = %CreatePrivateOwnSymbol("s1"); - -function TestSimple() { - var p = {} - p[s] = "moo"; - - var o = Object.create(p); - - assertEquals(undefined, o[s]); - assertEquals("moo", p[s]); - - o[s] = "bow-wow"; - assertEquals("bow-wow", o[s]); - assertEquals("moo", p[s]); -} - -TestSimple(); - - -function TestICs() { - var p = {} - p[s] = "moo"; - - - var o = Object.create(p); - o[s1] = "bow-wow"; - function checkNonOwn(o) { - assertEquals(undefined, o[s]); - assertEquals("bow-wow", o[s1]); - } - - checkNonOwn(o); - - // Test monomorphic/optimized. - for (var i = 0; i < 1000; i++) { - checkNonOwn(o); - } - - // Test non-monomorphic. - for (var i = 0; i < 1000; i++) { - var oNew = Object.create(p); - oNew["s" + i] = i; - oNew[s1] = "bow-wow"; - checkNonOwn(oNew); - } -} - -TestICs(); diff --git a/deps/v8/test/mjsunit/proto-accessor.js b/deps/v8/test/mjsunit/proto-accessor.js index 513a044023..690b10b5f1 100644 --- a/deps/v8/test/mjsunit/proto-accessor.js +++ b/deps/v8/test/mjsunit/proto-accessor.js @@ -29,6 +29,24 @@ this.Symbol = typeof Symbol != 'undefined' ? Symbol : String; +function TestSetProtoValueCyclic() { + var objects = [ + Object.prototype, {}, + Array.prototype, [], + Error.prototype, new TypeError, + // etc ... + ]; + for (var i = 0; i < objects.length; i += 2) { + var object = objects[i]; + var value = objects[i + 1]; + assertThrows(function() { + object.__proto__ = value; + }, TypeError); + } +}; +TestSetProtoValueCyclic(); + + var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); var getProto = desc.get; var setProto = desc.set; diff --git a/deps/v8/test/mjsunit/regexp-sort.js b/deps/v8/test/mjsunit/regexp-sort.js new file mode 100644 index 0000000000..57d50701cd --- /dev/null +++ b/deps/v8/test/mjsunit/regexp-sort.js @@ -0,0 +1,48 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function Test(lower, upper) { + var lx = lower + "x"; + var ux = upper + "x"; + var lp = lower + "|"; + var uxp = upper + "x|"; + assertEquals(lx, new RegExp(uxp + lp + lower + "cat", "i").exec(lx) + ""); + assertEquals(ux, new RegExp(uxp + lp + lower + "cat", "i").exec(ux) + ""); + assertEquals(lower, new RegExp(lp + uxp + lower + "cat", "i").exec(lx) + ""); + assertEquals(upper, new RegExp(lp + uxp + lower + "cat", "i").exec(ux) + ""); +} + +function TestFail(lower, upper) { + var lx = lower + "x"; + var ux = upper + "x"; + var lp = lower + "|"; + var uxp = upper + "x|"; + assertEquals(lower, new RegExp(uxp + lp + lower + "cat", "i").exec(lx) + ""); + assertEquals(ux, new RegExp(uxp + lp + lower + "cat", "i").exec(ux) + ""); + assertEquals(lower, new RegExp(lp + uxp + lower + "cat", "i").exec(lx) + ""); + assertEquals(ux, new RegExp(lp + uxp + lower + "cat", "i").exec(ux) + ""); +} + +Test("a", "A"); +Test("0", "0"); +TestFail("a", "b"); +// Small and capital o-umlaut +Test(String.fromCharCode(0xf6), String.fromCharCode(0xd6)); +// Small and capital kha. +Test(String.fromCharCode(0x445), String.fromCharCode(0x425)); +// Small and capital y-umlaut. +Test(String.fromCharCode(0xff), String.fromCharCode(0x178)); +// Small and large Greek mu. +Test(String.fromCharCode(0x3bc), String.fromCharCode(0x39c)); +// Micron and large Greek mu. +Test(String.fromCharCode(0xb5), String.fromCharCode(0x39c)); +// Micron and small Greek mu. +Test(String.fromCharCode(0xb5), String.fromCharCode(0x3bc)); +// German double s and capital S. These are not equivalent since one is double. +TestFail(String.fromCharCode(0xdf), "S"); +// Small i and Turkish capital dotted I. These are not equivalent due to +// 21.2.2.8.2 section 3g. One is below 128 and the other is above 127. +TestFail("i", String.fromCharCode(0x130)); +// Small dotless i and I. These are not equivalent either. +TestFail(String.fromCharCode(0x131), "I"); diff --git a/deps/v8/test/mjsunit/regress/poly_count_operation.js b/deps/v8/test/mjsunit/regress/poly_count_operation.js index 99f041b6f1..a8a1ed2ebc 100644 --- a/deps/v8/test/mjsunit/regress/poly_count_operation.js +++ b/deps/v8/test/mjsunit/regress/poly_count_operation.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --allow-natives-syntax --turbo-deoptimization +// Flags: --allow-natives-syntax var o1 = {x:1}; var o2 = {}; diff --git a/deps/v8/test/mjsunit/regress/regress-1119.js b/deps/v8/test/mjsunit/regress/regress-1119.js index 5fd8f369b1..24ab49aa95 100644 --- a/deps/v8/test/mjsunit/regress/regress-1119.js +++ b/deps/v8/test/mjsunit/regress/regress-1119.js @@ -28,7 +28,7 @@ // Test runtime declaration of properties with var which are intercepted // by JS accessors. -// Flags: --es52_globals +// Flags: --es52-globals this.__defineSetter__("x", function() { hasBeenInvoked = true; }); this.__defineSetter__("y", function() { throw 'exception'; }); diff --git a/deps/v8/test/mjsunit/regress/regress-1130.js b/deps/v8/test/mjsunit/regress/regress-1130.js index 07d5e3d467..6ba430b04f 100644 --- a/deps/v8/test/mjsunit/regress/regress-1130.js +++ b/deps/v8/test/mjsunit/regress/regress-1130.js @@ -35,6 +35,6 @@ try { eval("(function() { const x; var x })")(); } catch (e) { exception = true; - assertTrue(e instanceof TypeError); + assertTrue(e instanceof SyntaxError); } assertTrue(exception); diff --git a/deps/v8/test/mjsunit/regress/regress-1132.js b/deps/v8/test/mjsunit/regress/regress-1132.js index 3314db8572..a5cb0a1d5f 100644 --- a/deps/v8/test/mjsunit/regress/regress-1132.js +++ b/deps/v8/test/mjsunit/regress/regress-1132.js @@ -28,7 +28,7 @@ // Test the case when exception is thrown from the parser when lazy // compiling a function. -// Flags: --stack_size=32 +// Flags: --stack-size=46 // NOTE: stack size constant above has been empirically chosen. // If the test starts to fail in Genesis, consider increasing this constant. diff --git a/deps/v8/test/mjsunit/regress/regress-115452.js b/deps/v8/test/mjsunit/regress/regress-115452.js index dc711581e9..d95bba893c 100644 --- a/deps/v8/test/mjsunit/regress/regress-115452.js +++ b/deps/v8/test/mjsunit/regress/regress-115452.js @@ -27,7 +27,7 @@ // Test that a function declaration cannot overwrite a read-only property. -// Flags: --es52_globals +// Flags: --es52-globals function foobl() {} assertTrue(typeof this.foobl == "function"); diff --git a/deps/v8/test/mjsunit/regress/regress-1170187.js b/deps/v8/test/mjsunit/regress/regress-1170187.js index 3621bc44a8..6aa2896751 100644 --- a/deps/v8/test/mjsunit/regress/regress-1170187.js +++ b/deps/v8/test/mjsunit/regress/regress-1170187.js @@ -26,7 +26,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug -// Flags: --turbo-deoptimization // Make sure that the retreival of local variables are performed correctly even // when an adapter frame is present. diff --git a/deps/v8/test/mjsunit/regress/regress-119609.js b/deps/v8/test/mjsunit/regress/regress-119609.js index 0c85063ac7..99041adaf4 100644 --- a/deps/v8/test/mjsunit/regress/regress-119609.js +++ b/deps/v8/test/mjsunit/regress/regress-119609.js @@ -26,7 +26,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug -// Flags: --turbo-deoptimization Debug = debug.Debug; diff --git a/deps/v8/test/mjsunit/regress/regress-1199637.js b/deps/v8/test/mjsunit/regress/regress-1199637.js index 397aeb8762..f77eead315 100644 --- a/deps/v8/test/mjsunit/regress/regress-1199637.js +++ b/deps/v8/test/mjsunit/regress/regress-1199637.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --allow-natives-syntax --es52_globals +// Flags: --allow-natives-syntax --es52-globals // Make sure that we can introduce global variables (using // both var and const) that shadow even READ_ONLY variables diff --git a/deps/v8/test/mjsunit/regress/regress-131994.js b/deps/v8/test/mjsunit/regress/regress-131994.js index 3de3813eac..7f600959da 100644 --- a/deps/v8/test/mjsunit/regress/regress-131994.js +++ b/deps/v8/test/mjsunit/regress/regress-131994.js @@ -26,7 +26,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug -// Flags: --turbo-deoptimization // Test that a variable in the local scope that shadows a context-allocated // variable is correctly resolved when being evaluated in the debugger. diff --git a/deps/v8/test/mjsunit/regress/regress-1419.js b/deps/v8/test/mjsunit/regress/regress-1419.js index 98a8b76b57..55bcd7ccaa 100644 --- a/deps/v8/test/mjsunit/regress/regress-1419.js +++ b/deps/v8/test/mjsunit/regress/regress-1419.js @@ -44,4 +44,12 @@ assertEquals(1, f1.length); var desc = Object.getOwnPropertyDescriptor(f1, 'length'); assertEquals(false, desc.writable); assertEquals(false, desc.enumerable); -assertEquals(false, desc.configurable); +assertEquals(true, desc.configurable); + +Object.defineProperty(f1, 'length', { + value: 'abc', + writable: true +}); +assertEquals('abc', f1.length); +f1.length = 42; +assertEquals(42, f1.length); diff --git a/deps/v8/test/mjsunit/regress/regress-1586.js b/deps/v8/test/mjsunit/regress/regress-1586.js index b15e2f2432..9c805a7a4b 100644 --- a/deps/v8/test/mjsunit/regress/regress-1586.js +++ b/deps/v8/test/mjsunit/regress/regress-1586.js @@ -43,8 +43,6 @@ function f() { // Get the Debug object exposed from the debug context global object. Debug = debug.Debug -// Set breakpoint on line 6. -var bp = Debug.setBreakPoint(f, 6); function listener(event, exec_state, event_data, data) { if (event == Debug.DebugEvent.Break) { @@ -54,6 +52,10 @@ function listener(event, exec_state, event_data, data) { // Add the debug event listener. Debug.setListener(listener); + +//Set breakpoint on line 6. +var bp = Debug.setBreakPoint(f, 6); + result = -1; f(); assertEquals(1, result); diff --git a/deps/v8/test/mjsunit/regress/regress-166553.js b/deps/v8/test/mjsunit/regress/regress-166553.js index acaf34f4e0..38fc0b5e76 100644 --- a/deps/v8/test/mjsunit/regress/regress-166553.js +++ b/deps/v8/test/mjsunit/regress/regress-166553.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose_gc +// Flags: --expose-gc JSON.stringify(String.fromCharCode(1, -11).toString()) gc(); diff --git a/deps/v8/test/mjsunit/regress/regress-2318.js b/deps/v8/test/mjsunit/regress/regress-2318.js index e31e0f904e..771d195212 100644 --- a/deps/v8/test/mjsunit/regress/regress-2318.js +++ b/deps/v8/test/mjsunit/regress/regress-2318.js @@ -56,11 +56,12 @@ function f() { }; Debug = debug.Debug; -var bp = Debug.setBreakPoint(f, 0); function listener(event, exec_state, event_data, data) { result = exec_state.frame().evaluate("i").value(); }; Debug.setListener(listener); +var bp = Debug.setBreakPoint(f, 0); + assertThrows(function() { f(); }, RangeError); diff --git a/deps/v8/test/mjsunit/regress/regress-2593.js b/deps/v8/test/mjsunit/regress/regress-2593.js index b51b41c27e..b9e497f67f 100644 --- a/deps/v8/test/mjsunit/regress/regress-2593.js +++ b/deps/v8/test/mjsunit/regress/regress-2593.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose_gc +// Flags: --expose-gc p1 = { }; p2 = { }; diff --git a/deps/v8/test/mjsunit/regress/regress-2653.js b/deps/v8/test/mjsunit/regress/regress-2653.js index eb0c6315e6..8864df7553 100644 --- a/deps/v8/test/mjsunit/regress/regress-2653.js +++ b/deps/v8/test/mjsunit/regress/regress-2653.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --allow-natives-syntax --deopt_every_n_garbage_collections=1 +// Flags: --allow-natives-syntax --deopt-every-n-garbage-collections=1 function foo(a, b) { var l = a.length; diff --git a/deps/v8/test/mjsunit/regress/regress-325676.js b/deps/v8/test/mjsunit/regress/regress-325676.js index 7450a6d12c..427bbc38dc 100644 --- a/deps/v8/test/mjsunit/regress/regress-325676.js +++ b/deps/v8/test/mjsunit/regress/regress-325676.js @@ -26,7 +26,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug -// Flags: --turbo-deoptimization // If a function parameter is forced to be context allocated, // debug evaluate need to resolve it to a context slot instead of diff --git a/deps/v8/test/mjsunit/regress/regress-360733.js b/deps/v8/test/mjsunit/regress/regress-360733.js index 28f73ea446..d9abece30d 100644 --- a/deps/v8/test/mjsunit/regress/regress-360733.js +++ b/deps/v8/test/mjsunit/regress/regress-360733.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --stack_size=150 +// Flags: --stack-size=150 function f(a) { f(a + 1); diff --git a/deps/v8/test/mjsunit/regress/regress-370384.js b/deps/v8/test/mjsunit/regress/regress-370384.js index 28aea69216..e07cc06082 100644 --- a/deps/v8/test/mjsunit/regress/regress-370384.js +++ b/deps/v8/test/mjsunit/regress/regress-370384.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --deopt-every-n-times=1 --no-enable_sse4_1 +// Flags: --deopt-every-n-times=1 --no-enable-sse4-1 function g(f, x, name) { var v2 = f(x); diff --git a/deps/v8/test/mjsunit/regress/regress-3718.js b/deps/v8/test/mjsunit/regress/regress-3718.js new file mode 100644 index 0000000000..26d96d448d --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-3718.js @@ -0,0 +1,21 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +"use strict"; + +function getTypeName(receiver) { + Error.prepareStackTrace = function(e, stack) { return stack; } + var stack = (function() { return new Error().stack; }).call(receiver); + Error.prepareStackTrace = undefined; + return stack[0].getTypeName(); +} + +assertNull(getTypeName(undefined)); +assertNull(getTypeName(null)); +assertEquals("Number", getTypeName(1)); +assertEquals("String", getTypeName("")); +assertEquals("Boolean", getTypeName(false)); +assertEquals("Object", getTypeName({})); +assertEquals("Array", getTypeName([])); +assertEquals("Custom", getTypeName(new (function Custom(){})())); diff --git a/deps/v8/test/mjsunit/regress/regress-3960.js b/deps/v8/test/mjsunit/regress/regress-3960.js index 4aaab0b067..3bd2dc200d 100644 --- a/deps/v8/test/mjsunit/regress/regress-3960.js +++ b/deps/v8/test/mjsunit/regress/regress-3960.js @@ -4,7 +4,7 @@ // Flags: --allow-natives-syntax -// Test that setting break point is works correctly when the debugger is +// Test that setting break point works correctly when the debugger is // activated late, which leads to duplicate shared function infos. (function() { diff --git a/deps/v8/test/mjsunit/regress/regress-4121.js b/deps/v8/test/mjsunit/regress/regress-4121.js index 3d777c26b3..bef0b47ee5 100644 --- a/deps/v8/test/mjsunit/regress/regress-4121.js +++ b/deps/v8/test/mjsunit/regress/regress-4121.js @@ -53,3 +53,6 @@ assertTrue(%HasFastObjectElements(second_object_array)); assertFalse(%HasFastSmiElements(second_object_array)); assertTrue(%HaveSameMap(first_object_array, second_object_array)); assertFalse(%HaveSameMap(first_smi_array, second_object_array)); + +%ClearFunctionTypeFeedback(Loader); +%ClearFunctionTypeFeedback(Migrator); diff --git a/deps/v8/test/mjsunit/regress/regress-4169.js b/deps/v8/test/mjsunit/regress/regress-4169.js new file mode 100644 index 0000000000..df2de03984 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-4169.js @@ -0,0 +1,9 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +with ({}) { + eval("var x = 23"); + assertEquals(23, x); +} +assertEquals(23, x); diff --git a/deps/v8/test/mjsunit/regress/regress-417709a.js b/deps/v8/test/mjsunit/regress/regress-417709a.js index 7c4d4f728e..d210c10429 100644 --- a/deps/v8/test/mjsunit/regress/regress-417709a.js +++ b/deps/v8/test/mjsunit/regress/regress-417709a.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --stack-size=100 --turbo-deoptimization +// Flags: --stack-size=100 var a = []; diff --git a/deps/v8/test/mjsunit/regress/regress-4214.js b/deps/v8/test/mjsunit/regress/regress-4214.js new file mode 100644 index 0000000000..7c28104b8a --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-4214.js @@ -0,0 +1,6 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var o = { eval: function() { return this; } } +with (o) assertSame(o, eval()); diff --git a/deps/v8/test/mjsunit/regress/regress-4255-1.js b/deps/v8/test/mjsunit/regress/regress-4255-1.js new file mode 100644 index 0000000000..78fe860290 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-4255-1.js @@ -0,0 +1,26 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation + +'use strict'; +{ + let x = function() {}; + // Trigger OSR. + for (var i = 0; i < 1000000; i++); +} diff --git a/deps/v8/test/mjsunit/regress/regress-4255-2.js b/deps/v8/test/mjsunit/regress/regress-4255-2.js new file mode 100644 index 0000000000..bae82be512 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-4255-2.js @@ -0,0 +1,24 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation + +'use strict'; +for (let i = function f() {}; !i;); + // Trigger OSR. +for (var i = 0; i < 1000000; i++); diff --git a/deps/v8/test/mjsunit/regress/regress-4255-3.js b/deps/v8/test/mjsunit/regress/regress-4255-3.js new file mode 100644 index 0000000000..531d0a34de --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-4255-3.js @@ -0,0 +1,24 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation + +'use strict'; +for (let i in [1, 2, 3]) { function f() {} } +// Trigger OSR. +for (var i = 0; i < 1000000; i++); diff --git a/deps/v8/test/mjsunit/regress/regress-4255-4.js b/deps/v8/test/mjsunit/regress/regress-4255-4.js new file mode 100644 index 0000000000..4de62d905b --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-4255-4.js @@ -0,0 +1,24 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation +// comments to trigger lazy compilation comments to trigger lazy compilation + +'use strict'; +class C { constructor() {} } +// Trigger OSR +for (var i = 0; i < 1000000; i++); diff --git a/deps/v8/test/mjsunit/regress/regress-436896.js b/deps/v8/test/mjsunit/regress/regress-436896.js index 344a7a3049..0ea70523fe 100644 --- a/deps/v8/test/mjsunit/regress/regress-436896.js +++ b/deps/v8/test/mjsunit/regress/regress-436896.js @@ -14,4 +14,4 @@ function g(x) { } %OptimizeFunctionOnNextCall(g); -assertThrows(function() { g(42); }, TypeError); +assertThrows(function() { g(42); }, SyntaxError); diff --git a/deps/v8/test/mjsunit/regress/regress-479528.js b/deps/v8/test/mjsunit/regress/regress-479528.js new file mode 100644 index 0000000000..be0dfaff45 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-479528.js @@ -0,0 +1,13 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +var __v_7 = {"__proto__": this}; +__v_9 = %CreatePrivateSymbol("__v_9"); +this[__v_9] = "moo"; +function __f_5() { + __v_7[__v_9] = "bow-wow"; +} +__f_5(); diff --git a/deps/v8/test/mjsunit/regress/regress-489151.js b/deps/v8/test/mjsunit/regress/regress-489151.js new file mode 100644 index 0000000000..25a655585b --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-489151.js @@ -0,0 +1,12 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +this.__proto__ = Array.prototype; +Object.freeze(this); +function __f_0() { + for (var __v_0 = 0; __v_0 < 10; __v_0++) { + this.length = 1; + } +} + __f_0(); diff --git a/deps/v8/test/mjsunit/regress/regress-491481.js b/deps/v8/test/mjsunit/regress/regress-491481.js new file mode 100644 index 0000000000..196b6aeb79 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-491481.js @@ -0,0 +1,15 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +try { +%OptimizeFunctionOnNextCall(print); +try { + __f_16(); +} catch(e) { print(e); } +try { + __f_10(); +} catch(e) {; } +} catch(e) {} diff --git a/deps/v8/test/mjsunit/regress/regress-491536.js b/deps/v8/test/mjsunit/regress/regress-491536.js new file mode 100644 index 0000000000..6e6e0c6e14 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-491536.js @@ -0,0 +1,10 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-debug-as debug + +if (this["debug"]) debug.Debug.setListener(function() {}); +var source = "var outer = 0; function test() {'use strict'; outer = 1; } test(); print('ok');"; +function test_function() { eval(source); } +assertDoesNotThrow(test_function); diff --git a/deps/v8/test/mjsunit/regress/regress-499790.js b/deps/v8/test/mjsunit/regress/regress-499790.js new file mode 100644 index 0000000000..ce2cd03f02 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-499790.js @@ -0,0 +1,14 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --enable-slow-asserts + +var a = [1]; +a.foo = "bla"; +delete a.foo; +a[0] = 1.5; + +var a2 = []; +a2.foo = "bla"; +delete a2.foo; diff --git a/deps/v8/test/mjsunit/regress/regress-500173.js b/deps/v8/test/mjsunit/regress/regress-500173.js new file mode 100644 index 0000000000..b7083b2c51 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-500173.js @@ -0,0 +1,12 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function f(a) { + a.foo = {}; + a[0] = 1; + a.__defineGetter__('foo', function() {}); + a[0] = {}; + a.bar = 0; +} +f(new Array()); diff --git a/deps/v8/test/mjsunit/regress/regress-500176.js b/deps/v8/test/mjsunit/regress/regress-500176.js new file mode 100644 index 0000000000..6700ef0f33 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-500176.js @@ -0,0 +1,13 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function __f_0(p) { + var __v_0 = -2147483642; + for (var __v_1 = 0; __v_1 < 10; __v_1++) { + if (__v_1 > 5) { __v_0 = __v_0 + p; break;} + } +} +for (var __v_2 = 0; __v_2 < 100000; __v_2++) __f_0(42); +__v_2 = { f: function () { return x + y; }, + 2: function () { return x - y} }; diff --git a/deps/v8/test/mjsunit/regress/regress-500831.js b/deps/v8/test/mjsunit/regress/regress-500831.js new file mode 100644 index 0000000000..6d8cfaf05a --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-500831.js @@ -0,0 +1,94 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +// To reproduce reliably use: --random-seed=-2012454635 --nodebug-code + +function deepEquals(a, b) { + if (a === b) {; + return true; + } + if (typeof a != typeof b) return false; + if (typeof a == "number"); + if (typeof a !== "object" && typeof a !== "function") + return false; + var objectClass = classOf(); + if (b) return false; + if (objectClass === "RegExp") {; + } + if (objectClass === "Function") return false; + if (objectClass === "Array") { + var elementCount = 0; + if (a.length != b.length) { + return false; + } + for (var i = 0; i < a.length; i++) { + if (a[i][i]) return false; + } + return true; + } + if (objectClass == "String" || objectClass == "Number" || + objectClass == "Boolean" || objectClass == "Date") { + if (a.valueOf()) return false; + }; +} +function equals(expected, found, name_opt) { + if (!deepEquals(found, expected)) {} +}; +function instof(obj, type) { + if (!(obj instanceof type)) { + var actualTypeName = null; + var actualConstructor = Object.getPrototypeOf().constructor; + if (typeof actualConstructor == "function") {; + }; + } +}; +var __v_0 = 1; +var __v_6 = {}; +var __v_9 = {}; + +function __f_4() { + return function() {}; +} +__v_6 = new Uint8ClampedArray(10); + +function __f_6() { + __v_6[0] = 0.499; + instof(__f_4(), Function); + equals(); + __v_6[0] = 0.5; + equals(); + __v_0[0] = 0.501; + equals(__v_6[4294967295]); + __v_6[0] = 1.499; + equals(); + __v_6[0] = 1.5; + equals(); + __v_6[0] = 1.501; + equals(); + __v_6[0] = 2.5; + equals(__v_6[-1073741824]); + __v_6[0] = 3.5; + equals(); + __v_6[0] = 252.5; + equals(); + __v_6[0] = 253.5; + equals(); + __v_6[0] = 254.5; + equals(); + __v_6[0] = 256.5; + equals(); + __v_6[0] = -0.5; + equals(__v_6[8]); + __v_6[0] = -1.5; + equals(); + __v_6[0] = 1000000000000; + equals(); + __v_9[0] = -1000000000000; + equals(__v_6[0]); +} +__f_6(); +__f_6(); % OptimizeFunctionOnNextCall(__f_6); +__f_6(); diff --git a/deps/v8/test/mjsunit/regress/regress-500980.js b/deps/v8/test/mjsunit/regress/regress-500980.js new file mode 100644 index 0000000000..841d26aa4a --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-500980.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var a = "a"; +assertThrows(function() { while (true) a += a; }, RangeError); +assertThrows(function() { a in a; }, TypeError); diff --git a/deps/v8/test/mjsunit/regress/regress-503565.js b/deps/v8/test/mjsunit/regress/regress-503565.js new file mode 100644 index 0000000000..9aebe8d7d1 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-503565.js @@ -0,0 +1,21 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Crashes without the fix for bug 503565. +function f() {} +function g() {} +function h() { + g() +} +(function() { + eval("\ + \"use strict\";\ + g = (function(x) {\ + +Math.log(+Math.log((+(+x>0)), f(Math.log())))\ + })\ + ") +})() +for (var j = 0; j < 999; j++) { + h() +} diff --git a/deps/v8/test/mjsunit/regress/regress-507980.js b/deps/v8/test/mjsunit/regress/regress-507980.js new file mode 100644 index 0000000000..d1a1f79f24 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-507980.js @@ -0,0 +1,8 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +__v_1 = new Float64Array(1); +__v_8 = { valueOf: function() { __v_13.y = "bar"; return 42; }}; +__v_13 = __v_1; +__v_13[0] = __v_8; diff --git a/deps/v8/test/mjsunit/regress/regress-581.js b/deps/v8/test/mjsunit/regress/regress-581.js index 65cd87de01..ab345a9b61 100644 --- a/deps/v8/test/mjsunit/regress/regress-581.js +++ b/deps/v8/test/mjsunit/regress/regress-581.js @@ -35,11 +35,13 @@ assertEquals(pow31 + 1, a.length); assertThrows(function() { a.concat(a); }, RangeError); var b = []; -b[pow31 - 2] = 32; +b[pow31 - 3] = 32; +b[pow31 - 2] = "out_of_bounds"; var ab = a.concat(b); assertEquals(2 * pow31 - 1, ab.length); assertEquals(31, ab[pow31]); -assertEquals(32, ab[2 * pow31 - 1]); +assertEquals(32, ab[2 * pow31 - 2]); +assertEquals(undefined, ab[2 * pow31 - 1]); var c = []; c[pow30] = 30; diff --git a/deps/v8/test/mjsunit/regress/regress-747.js b/deps/v8/test/mjsunit/regress/regress-747.js index 648c36684c..a3de131483 100644 --- a/deps/v8/test/mjsunit/regress/regress-747.js +++ b/deps/v8/test/mjsunit/regress/regress-747.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose_gc +// Flags: --expose-gc // This test makes sure that we do flush code with heap allocated locals. // This can be a problem if eval is used within the scope. diff --git a/deps/v8/test/mjsunit/regress/regress-78270.js b/deps/v8/test/mjsunit/regress/regress-78270.js index 02c4b147c9..b9ce286feb 100644 --- a/deps/v8/test/mjsunit/regress/regress-78270.js +++ b/deps/v8/test/mjsunit/regress/regress-78270.js @@ -25,8 +25,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --turbo-deoptimization - for (var i = 0; i < 10000; i++) { try { var object = { }; diff --git a/deps/v8/test/mjsunit/regress/regress-arguments-gc.js b/deps/v8/test/mjsunit/regress/regress-arguments-gc.js index baa4e163f5..b5ed608e0e 100644 --- a/deps/v8/test/mjsunit/regress/regress-arguments-gc.js +++ b/deps/v8/test/mjsunit/regress/regress-arguments-gc.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-gc --nocleanup_code_caches_at_gc +// Flags: --expose-gc --nocleanup-code-caches-at-gc function f(x) { gc(); diff --git a/deps/v8/test/mjsunit/regress/regress-assignment-in-test-context.js b/deps/v8/test/mjsunit/regress/regress-assignment-in-test-context.js index bc4098554a..61ca220293 100644 --- a/deps/v8/test/mjsunit/regress/regress-assignment-in-test-context.js +++ b/deps/v8/test/mjsunit/regress/regress-assignment-in-test-context.js @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --allow-natives-syntax --always-opt -// Flags: --turbo-filter=* --turbo-deoptimization +// Flags: --allow-natives-syntax --always-opt --turbo-filter=* function assertEquals() {} diff --git a/deps/v8/test/mjsunit/regress/regress-binop-nosse2.js b/deps/v8/test/mjsunit/regress/regress-binop-nosse2.js deleted file mode 100644 index 29c8a048fc..0000000000 --- a/deps/v8/test/mjsunit/regress/regress-binop-nosse2.js +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2013 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Flags: --allow-natives-syntax --noenable-sse2 - -// general tests -var e31 = Math.pow(2, 31); - -assertEquals(-e31, -1*e31); -assertEquals(e31, -1*e31*(-1)); -assertEquals(e31, -1*-e31); -assertEquals(e31, -e31*(-1)); - -var x = {toString : function() {return 1}} -function add(a,b){return a+b;} -add(1,x); -add(1,x); -%OptimizeFunctionOnNextCall(add); -add(1,x); -x.toString = function() {return "2"}; - -assertEquals(add(1,x), "12"); - -// Test the correct placement of the simulates in TruncateToNumber: -function Checker() { - this.str = "1"; - var toStringCalled = 0; - var toStringExpected = 0; - this.toString = function() { - toStringCalled++; - return this.str; - }; - this.check = function() { - toStringExpected++; - assertEquals(toStringExpected, toStringCalled); - }; -}; -var left = new Checker(); -var right = new Checker(); - -function test(fun,check_fun,a,b,does_throw) { - left.str = a; - right.str = b; - try { - assertEquals(check_fun(a,b), fun(left, right)); - assertTrue(!does_throw); - } catch(e) { - if (e instanceof TypeError) { - assertTrue(!!does_throw); - } else { - throw e; - } - } finally { - left.check(); - if (!does_throw || does_throw>1) { - right.check(); - } - } -} - -function minus(a,b) { return a-b }; -function check_minus(a,b) { return a-b }; -function mod(a,b) { return a%b }; -function check_mod(a,b) { return a%b }; - -test(minus,check_minus,1,2); -// Bailout on left -test(minus,check_minus,1<<30,1); -// Bailout on right -test(minus,check_minus,1,1<<30); -// Bailout on result -test(minus,check_minus,1<<30,-(1<<30)); - -// Some more interesting things -test(minus,check_minus,1,1.4); -test(minus,check_minus,1.3,4); -test(minus,check_minus,1.3,1.4); -test(minus,check_minus,1,2); -test(minus,check_minus,1,undefined); -test(minus,check_minus,1,2); -test(minus,check_minus,1,true); -test(minus,check_minus,1,2); -test(minus,check_minus,1,null); -test(minus,check_minus,1,2); -test(minus,check_minus,1,""); -test(minus,check_minus,1,2); - -// Throw on left -test(minus,check_minus,{},1,1); -// Throw on right -test(minus,check_minus,1,{},2); -// Throw both -test(minus,check_minus,{},{},1); - -test(minus,check_minus,1,2); - -// Now with optimized code -test(mod,check_mod,1,2); -%OptimizeFunctionOnNextCall(mod); -test(mod,check_mod,1,2); - -test(mod,check_mod,1<<30,1); -%OptimizeFunctionOnNextCall(mod); -test(mod,check_mod,1<<30,1); -test(mod,check_mod,1,1<<30); -%OptimizeFunctionOnNextCall(mod); -test(mod,check_mod,1,1<<30); -test(mod,check_mod,1<<30,-(1<<30)); -%OptimizeFunctionOnNextCall(mod); -test(mod,check_mod,1<<30,-(1<<30)); - -test(mod,check_mod,1,{},2); -%OptimizeFunctionOnNextCall(mod); -test(mod,check_mod,1,{},2); - -test(mod,check_mod,1,2); - - -// test oddballs -function t1(a, b) {return a-b} -assertEquals(t1(1,2), 1-2); -assertEquals(t1(2,true), 2-1); -assertEquals(t1(false,2), 0-2); -assertEquals(t1(1,2.4), 1-2.4); -assertEquals(t1(1.3,2.4), 1.3-2.4); -assertEquals(t1(true,2.4), 1-2.4); -assertEquals(t1(1,undefined), 1-NaN); -assertEquals(t1(1,1<<30), 1-(1<<30)); -assertEquals(t1(1,2), 1-2); - -function t2(a, b) {return a/b} -assertEquals(t2(1,2), 1/2); -assertEquals(t2(null,2), 0/2); -assertEquals(t2(null,-2), 0/-2); -assertEquals(t2(2,null), 2/0); -assertEquals(t2(-2,null), -2/0); -assertEquals(t2(1,2.4), 1/2.4); -assertEquals(t2(1.3,2.4), 1.3/2.4); -assertEquals(t2(null,2.4), 0/2.4); -assertEquals(t2(1.3,null), 1.3/0); -assertEquals(t2(undefined,2), NaN/2); -assertEquals(t2(1,1<<30), 1/(1<<30)); -assertEquals(t2(1,2), 1/2); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-107996.js b/deps/v8/test/mjsunit/regress/regress-crbug-107996.js index b4907f3bb8..dfe07e59de 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-107996.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-107996.js @@ -26,7 +26,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug -// Flags: --turbo-deoptimization Debug = debug.Debug; diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-171715.js b/deps/v8/test/mjsunit/regress/regress-crbug-171715.js index 309f50a01b..040c381e39 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-171715.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-171715.js @@ -26,7 +26,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug -// Flags: --turbo-deoptimization Debug = debug.Debug diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-217858.js b/deps/v8/test/mjsunit/regress/regress-crbug-217858.js index e61cb9f6d2..d6d6e9feed 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-217858.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-217858.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --noanalyze_environment_liveness +// Flags: --noanalyze-environment-liveness var r = /r/; function f() { diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-222893.js b/deps/v8/test/mjsunit/regress/regress-crbug-222893.js index 75e17289fd..39363bc912 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-222893.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-222893.js @@ -26,7 +26,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug -// Flags: --turbo-deoptimization Debug = debug.Debug diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-424142.js b/deps/v8/test/mjsunit/regress/regress-crbug-424142.js index 0a370d4142..b188565fe2 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-424142.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-424142.js @@ -23,6 +23,7 @@ function sentinel() {} Debug = debug.Debug; +Debug.setListener(function(){}); var script = Debug.findScript(sentinel); var line = 14; @@ -34,3 +35,5 @@ var actual = Debug.setBreakPointByScriptIdAndPosition( // the break point. assertTrue(line_start <= actual); assertTrue(actual <= line_end); + +Debug.setListener(null); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-450960.js b/deps/v8/test/mjsunit/regress/regress-crbug-450960.js index f745522dbe..28db6dff8b 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-450960.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-450960.js @@ -2,15 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --stack-size=70 +// Flags: --stack-size=100 "a".replace(/a/g, ""); +var count = 0; function test() { try { test(); } catch(e) { - "b".replace(/(b)/g, new []); + if (count < 50) { + count++; + "b".replace(/(b)/g, new []); + } } } diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-467180.js b/deps/v8/test/mjsunit/regress/regress-crbug-467180.js new file mode 100644 index 0000000000..fcf5c30294 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-467180.js @@ -0,0 +1,41 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-debug-as debug + +function f() { + for (var i = 10; i < 14; i++) { // 1 + i; // 2 + } +} // 3 + +var state = "conditional"; +var log = []; +var exception = null; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + var label = +exec_state.frame(0).sourceLineText().substr(-1); + log.push(label); + if (label == 2) log.push(exec_state.frame(0).evaluate("i").value()); + exec_state.prepareStep(Debug.StepAction.StepNext, 1); + } catch (e) { + exception = e; + print("Caught something. " + e + " " + e.stack); + }; +}; + + +var Debug = debug.Debug; +Debug.setListener(listener); + +Debug.setBreakPoint(f, 2, 0, "i == 12"); + +f(); + +Debug.setListener(null); // 4 + +assertEquals([2,12,1,1,2,13,1,1,3,4], log); +assertNull(exception); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-471659.js b/deps/v8/test/mjsunit/regress/regress-crbug-471659.js new file mode 100644 index 0000000000..fa27baa3e8 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-471659.js @@ -0,0 +1,22 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --stack-size=100 + +var s = "0123456789ABCDEF"; +for (var i = 0; i < 16; i++) s += s; + +var count = 0; +function f() { + try { + f(); + if (count < 10) { + f(); + } + } catch(e) { + s.replace("+", "-"); + } + count++; +} +f(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-474297.js b/deps/v8/test/mjsunit/regress/regress-crbug-474297.js index 3169c2815a..ce240251bd 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-474297.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-474297.js @@ -4,4 +4,9 @@ // Flags: --gc-interval=33 --expose-gc --allow-natives-syntax +var Debug = %GetDebugContext().Debug; +Debug.setListener(function(){}); + %DebugGetLoadedScripts(); + +Debug.setListener(null); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-480819.js b/deps/v8/test/mjsunit/regress/regress-crbug-480819.js index 8d3b7eed60..086f6c84c2 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-480819.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-480819.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --turbo-filter=* --always-opt --turbo-deoptimization --noanalyze-environment-liveness +// Flags: --turbo-filter=* --always-opt --noanalyze-environment-liveness (function() { "use strict"; diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-481896.js b/deps/v8/test/mjsunit/regress/regress-crbug-481896.js new file mode 100644 index 0000000000..0d5c650f1e --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-481896.js @@ -0,0 +1,56 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-debug-as debug + +function static() { + print("> static"); // Break +} + +var Debug = debug.Debug; +var exception = null; +var break_count = 0; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + print("breakpoint hit at " + exec_state.frame(0).sourceLineText()); + assertTrue(exec_state.frame(0).sourceLineText().indexOf("// Break") > 0); + break_count++; + } catch (e) { + exception = e; + } +} + +Debug.setListener(listener); + +function install() { + eval("this.dynamic = function dynamic() { \n" + + " print(\"> dynamic\"); // Break\n" + + "}\n" + + "//@ sourceURL=dynamicScript"); +} + +install(); + +var scripts = Debug.scripts(); +var dynamic_script; +var static_script; +for (var script of scripts) { + if (script.source_url == "dynamicScript") dynamic_script = script; + if (script.source_url == "staticScript") static_script = script; +} + +Debug.setScriptBreakPointById(dynamic_script.id, 1); +Debug.setScriptBreakPointById(static_script.id, 7); + +dynamic(); +static(); + +Debug.setListener(null); + +assertNull(exception); +assertEquals(2, break_count); + +//@ sourceURL=staticScript diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-482998.js b/deps/v8/test/mjsunit/regress/regress-crbug-482998.js new file mode 100644 index 0000000000..80933a7a6d --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-482998.js @@ -0,0 +1,23 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Should not time out. Running time 0.5s vs. 120s before the change. +function collapse(flags) { + var src = "(?:"; + for (var i = 128; i < 0x1000; i++) { + src += String.fromCharCode(96 + i % 26) + String.fromCharCode(i) + "|"; + } + src += "aa)"; + var collapsible = new RegExp(src, flags); + var subject = "zzzzzzz" + String.fromCharCode(3000); + for (var i = 0; i < 1000; i++) { + subject += "xxxxxxx"; + } + for (var i = 0; i < 2000; i++) { + assertFalse(collapsible.test(subject)); + } +} + +collapse("i"); +collapse(""); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-487105.js b/deps/v8/test/mjsunit/regress/regress-crbug-487105.js new file mode 100644 index 0000000000..160f9b04e0 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-487105.js @@ -0,0 +1,9 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +"use strict"; +function assertThrows() { + eval(); +}; +eval("delete this;") diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-487289.js b/deps/v8/test/mjsunit/regress/regress-crbug-487289.js new file mode 100644 index 0000000000..dbfb4041ca --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-487289.js @@ -0,0 +1,20 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-debug-as debug + +var Debug = debug.Debug; +var receiver = null; + +Debug.setListener(function(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + receiver = exec_state.frame(0).evaluate('this').value(); +}); + +function f() { debugger; } + +var expected = {}; +f.call(expected); + +assertEquals(expected, receiver); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-487608.js b/deps/v8/test/mjsunit/regress/regress-crbug-487608.js new file mode 100644 index 0000000000..c1eafce5ef --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-487608.js @@ -0,0 +1,22 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +function inlined(a, i) { + return a[i + 1]; +} + +function foo(index) { + var a = [0, 1, 2, 3]; + var result = 0; + result += a[index]; + result += inlined(a, index); + return result; +} + +foo(0); +foo(0); +%OptimizeFunctionOnNextCall(foo); +foo(0); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-489293.js b/deps/v8/test/mjsunit/regress/regress-crbug-489293.js new file mode 100644 index 0000000000..bcfc702df3 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-489293.js @@ -0,0 +1,16 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --turbo-filter=f +// Flags: --noanalyze-environment-liveness + +function f() { + var x = 0; + for (var y = 0; y < 0; ++y) { + x = (x + y) | 0; + } + return unbound; +} +%OptimizeFunctionOnNextCall(f); +assertThrows(f, ReferenceError); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-489597.js b/deps/v8/test/mjsunit/regress/regress-crbug-489597.js new file mode 100644 index 0000000000..b10af92b5f --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-489597.js @@ -0,0 +1,12 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +try { + load("test/mjsunit/regress/regress-crbug-489597.js-script"); +} catch (e) { +} + +var o = this; +Error.captureStackTrace(o); +o.stack; diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-489597.js-script b/deps/v8/test/mjsunit/regress/regress-crbug-489597.js-script new file mode 100644 index 0000000000..cb4dd84df3 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-489597.js-script @@ -0,0 +1,5 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +throw new Error("boom"); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-490680.js b/deps/v8/test/mjsunit/regress/regress-crbug-490680.js new file mode 100644 index 0000000000..735f3b7f50 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-490680.js @@ -0,0 +1,18 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var sentinel = null; + +try { + throw { toString: function() { sentinel = "observed"; } }; +} catch (e) { +} + +L: try { + throw { toString: function() { sentinel = "observed"; } }; +} finally { + break L; +} + +assertNull(sentinel); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-491062.js b/deps/v8/test/mjsunit/regress/regress-crbug-491062.js new file mode 100644 index 0000000000..d2cd7579bc --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-491062.js @@ -0,0 +1,22 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --stack-size=100 + +function g() {} + +var count = 0; +function f() { + try { + f(); + } catch(e) { + print(e.stack); + } + if (count < 100) { + count++; + %DebugGetLoadedScripts(); + } +} +f(); +g(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-491943.js b/deps/v8/test/mjsunit/regress/regress-crbug-491943.js new file mode 100644 index 0000000000..c87d1301b7 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-491943.js @@ -0,0 +1,25 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-debug-as debug + +var Debug = debug.Debug; +var receiver = null; + +Debug.setListener(function(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + receiver = exec_state.frame(0).evaluate('this').value(); +}); + + +function f() { + var context_local = 1; + (function() { return context_local; })(); + debugger; +} + +var expected = {}; +f.call(expected); + +assertEquals(expected, receiver); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-492526.js b/deps/v8/test/mjsunit/regress/regress-crbug-492526.js new file mode 100644 index 0000000000..e8ea298f8b --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-492526.js @@ -0,0 +1,7 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +assertThrows(function() { %FormatMessageString(-1, "", "", ""); }); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-493284.js b/deps/v8/test/mjsunit/regress/regress-crbug-493284.js new file mode 100644 index 0000000000..64f9463471 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-493284.js @@ -0,0 +1,10 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --invoke-weak-callbacks --omit-quit --no-test + +if (this.Intl) { + var coll = new Intl.Collator(); + assertEquals(-1, coll.compare('a', 'c')); +} diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-493290.js b/deps/v8/test/mjsunit/regress/regress-crbug-493290.js new file mode 100644 index 0000000000..6ff9fe1a65 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-493290.js @@ -0,0 +1,9 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function f() { + throw "boom"; + try {} catch (e) {} +} +assertThrows(f); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-493568.js b/deps/v8/test/mjsunit/regress/regress-crbug-493568.js new file mode 100644 index 0000000000..081f4937fe --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-493568.js @@ -0,0 +1,12 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-proxies + +var p = Proxy.create({ fix: function() { return {}; } }); + +var obj = {}; +obj.x = p; + +Object.preventExtensions(p); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-493779.js b/deps/v8/test/mjsunit/regress/regress-crbug-493779.js new file mode 100644 index 0000000000..1071ed23ac --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-493779.js @@ -0,0 +1,11 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --enable-slow-asserts + +var s = "\u1234-------"; +for (var i = 0; i < 17; i++) { + s += s; +} +s.replace(/[\u1234]/g, ""); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-498022.js b/deps/v8/test/mjsunit/regress/regress-crbug-498022.js new file mode 100644 index 0000000000..cb8e0a460d --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-498022.js @@ -0,0 +1,15 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --debug-code --nouse-gvn + +"use strict"; +class Base { +} +class Derived extends Base { + constructor() { + eval(); + } +} +assertThrows("new Derived()", ReferenceError); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-498142.js b/deps/v8/test/mjsunit/regress/regress-crbug-498142.js new file mode 100644 index 0000000000..fcec5d1bd7 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-498142.js @@ -0,0 +1,8 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-sharedarraybuffer + +var sab = new SharedArrayBuffer(16); +assertThrows(function() { %ArrayBufferNeuter(sab); }); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-498811.js b/deps/v8/test/mjsunit/regress/regress-crbug-498811.js new file mode 100644 index 0000000000..53f57b8c17 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-498811.js @@ -0,0 +1,9 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// NO HARNESS + +"use strict"; +let l = 0; +eval("eval('this')"); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-514268.js b/deps/v8/test/mjsunit/regress/regress-crbug-500435.js index 75d9970eed..acc17ac5ec 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-514268.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-500435.js @@ -5,16 +5,15 @@ // Flags: --allow-natives-syntax function bar(a) { - a.pop(); + delete a[1]; } + function foo(a) { - assertEquals(2, a.length); var d; for (d in a) { + assertFalse(d === undefined); bar(a); } - // If this fails, bar was not called exactly once. - assertEquals(1, a.length); } foo([1,2]); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-500497.js b/deps/v8/test/mjsunit/regress/regress-crbug-500497.js index 9117440c2c..2d3d40f0f7 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-500497.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-500497.js @@ -13,6 +13,9 @@ function Ctor() { } for (var i = 0; i < 120; i++) { + // This print() is important! Without it, in --gc-stress mode, the function + // Ctor is optimized too early. No idea why. + print(i); // Make the "a" property long-lived, while everything else is short-lived. global.push(Ctor().a); (function FillNewSpace() { new Array(10000); })(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-500824.js b/deps/v8/test/mjsunit/regress/regress-crbug-500824.js new file mode 100644 index 0000000000..08d0d107ca --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-500824.js @@ -0,0 +1,23 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +function get_thrower() { + "use strict"; + return Object.getOwnPropertyDescriptor(arguments, "callee").get; +} + +var f = (function(v) { + "use asm"; + function fun() { + switch (v) {} + } + return { + fun: fun + }; +})(get_thrower()).fun; + +%OptimizeFunctionOnNextCall(f); +f(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-501711.js b/deps/v8/test/mjsunit/regress/regress-crbug-501711.js new file mode 100644 index 0000000000..f8eda6e8d8 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-501711.js @@ -0,0 +1,14 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --stack-size=100 + +function f() { + try { + f(); + } catch(e) { + Realm.create(); + } +} +f(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-501808.js b/deps/v8/test/mjsunit/regress/regress-crbug-501808.js new file mode 100644 index 0000000000..f9b97841c4 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-501808.js @@ -0,0 +1,6 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var r = Realm.create(); +assertEquals(0, "a".localeCompare("a")); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-501809.js b/deps/v8/test/mjsunit/regress/regress-crbug-501809.js new file mode 100644 index 0000000000..b348e5d5f6 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-501809.js @@ -0,0 +1,9 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-sharedarraybuffer --harmony-atomics +var sab = new SharedArrayBuffer(8); +var ta = new Int32Array(sab); +ta.__defineSetter__('length', function() {;}); +assertThrows(function() { Atomics.compareExchange(ta, 4294967295, 0, 0); }); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-503578.js b/deps/v8/test/mjsunit/regress/regress-crbug-503578.js new file mode 100644 index 0000000000..1274d91ffe --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-503578.js @@ -0,0 +1,14 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +if (this.Worker) { + function __f_0(byteLength) { + var __v_1 = new ArrayBuffer(byteLength); + var __v_5 = new Uint32Array(__v_1); + return __v_5; + } + var __v_6 = new Worker('onmessage = function() {}'); + var __v_3 = __f_0(16); + __v_6.postMessage(__v_3); +} diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-503698.js b/deps/v8/test/mjsunit/regress/regress-crbug-503698.js new file mode 100644 index 0000000000..415d1bc81b --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-503698.js @@ -0,0 +1,9 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --invoke-weak-callbacks + +if (this.Worker) { + var __v_6 = new Worker(''); +} diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-503968.js b/deps/v8/test/mjsunit/regress/regress-crbug-503968.js new file mode 100644 index 0000000000..78d1c7b98a --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-503968.js @@ -0,0 +1,13 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +if (this.Worker) { + function __f_0() { this.s = new Object(); } + function __f_1() { + this.l = [new __f_0, new __f_0]; + } + __v_6 = new __f_1; + var __v_9 = new Worker(''); + __v_9.postMessage(__v_6); +} diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-503991.js b/deps/v8/test/mjsunit/regress/regress-crbug-503991.js new file mode 100644 index 0000000000..6a3b0de759 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-503991.js @@ -0,0 +1,9 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +if (this.Worker) { + __v_3 = ""; + var __v_6 = new Worker(''); + __v_6.postMessage(__v_3); +} diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-504136.js b/deps/v8/test/mjsunit/regress/regress-crbug-504136.js new file mode 100644 index 0000000000..4ed6843544 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-504136.js @@ -0,0 +1,9 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +if (this.Worker) { + var __v_10 = new Worker(''); + __v_10.terminate(); + __v_10.getMessage(); +} diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-504727.js b/deps/v8/test/mjsunit/regress/regress-crbug-504727.js new file mode 100644 index 0000000000..16d8ff16cd --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-504727.js @@ -0,0 +1,9 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --no-test + +if (this.Worker) { + var __v_2 = new Worker(''); +} diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-504729.js b/deps/v8/test/mjsunit/regress/regress-crbug-504729.js new file mode 100644 index 0000000000..435cafee87 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-504729.js @@ -0,0 +1,9 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +if (this.Worker) { + Function.prototype.toString = "foo"; + function __f_7() {} + assertThrows(function() { var __v_5 = new Worker(__f_7.toString()); }); +} diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-504787.js b/deps/v8/test/mjsunit/regress/regress-crbug-504787.js new file mode 100644 index 0000000000..66274bc6b9 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-504787.js @@ -0,0 +1,15 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --noturbo-osr + +function f() { + "use asm"; + function g() { + function f() {}; + } + return g; +} + +f()(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-505007-1.js b/deps/v8/test/mjsunit/regress/regress-crbug-505007-1.js new file mode 100644 index 0000000000..6012577aaa --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-505007-1.js @@ -0,0 +1,14 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --stack-size=100 --allow-natives-syntax + +function f() { + try { + f(); + } catch(e) { + %GetDebugContext(); + } +} +f(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-505007-2.js b/deps/v8/test/mjsunit/regress/regress-crbug-505007-2.js new file mode 100644 index 0000000000..dfa34ae6ad --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-505007-2.js @@ -0,0 +1,15 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --stack-size=100 --allow-natives-syntax + +function g() {} +function f() { + try { + f(); + } catch(e) { + %ExecuteInDebugContext(g); + } +} +f(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-505354.js b/deps/v8/test/mjsunit/regress/regress-crbug-505354.js new file mode 100644 index 0000000000..61c40c44da --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-505354.js @@ -0,0 +1,14 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --turbo-filter=f + +function f() { + "use strict"; + try { + for (let i = 0; i < 10; i++) {} + } catch(e) {} +} +%OptimizeFunctionOnNextCall(f); +f(); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-505370.js b/deps/v8/test/mjsunit/regress/regress-crbug-505370.js new file mode 100644 index 0000000000..f67d82b66f --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-505370.js @@ -0,0 +1,22 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var o = { + get 0() { reference_error; }, + get length() { return 1; } +}; + +var method_name; + +try { + o[0]; +} catch (e) { + thrown = true; + Error.prepareStackTrace = function(exception, frames) { return frames; }; + var frames = e.stack; + Error.prepareStackTrace = undefined; + method_name = frames[0].getMethodName(); +} + +assertEquals("0", method_name); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-505778.js b/deps/v8/test/mjsunit/regress/regress-crbug-505778.js new file mode 100644 index 0000000000..74d96ab094 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-505778.js @@ -0,0 +1,8 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +if (this.Worker) { + var __v_7 = new Worker('onmessage = function() {}'); + __v_7.postMessage(""); +} diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-506443.js b/deps/v8/test/mjsunit/regress/regress-crbug-506443.js new file mode 100644 index 0000000000..13cbac6769 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-506443.js @@ -0,0 +1,89 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +assertSame = function assertSame() { + if (found === expected) { + if (1 / expected) return; + } else if ((expected !== expected) && (found !== found)) { + return; + }; +}; +assertEquals = function assertEquals() { + if (expected) {; + } +}; +assertArrayEquals = function assertArrayEquals() { + var start = ""; + if (name_opt) { + start = name_opt + " - "; + }; + if (expected.length == found.length) { + for (var i = 0; i < expected.length; ++i) {; + } + } +}; +assertPropertiesEqual = function assertPropertiesEqual() { + if (found) {; + } +}; +assertToStringEquals = function assertToStringEquals() { + if (found) {; + } +}; +assertTrue = function assertTrue() {; +}; +assertFalse = function assertFalse() {; +}; +assertUnreachable = function assertUnreachable() { + var message = "Fail" + "ure: unreachable"; + if (name_opt) { + message += " - " + name_opt; + } +}; +OptimizationStatus = function() {} +assertUnoptimized = function assertUnoptimized() {; +} +assertOptimized = function assertOptimized() {; +} +triggerAssertFalse = function() {} +var __v_2 = {}; +var __v_3 = {}; +var __v_4 = {}; +var __v_5 = {}; +var __v_6 = 1073741823; +var __v_7 = {}; +var __v_8 = {}; +var __v_9 = {}; +var __v_10 = {}; +var __v_11 = 2147483648; +var __v_12 = 1073741823; +var __v_13 = {}; +var __v_14 = {}; +var __v_15 = -2147483648; +var __v_16 = {}; +var __v_17 = {}; +var __v_19 = {}; +var __v_20 = {}; +var __v_21 = {}; +var __v_22 = {}; +var __v_23 = {}; +var __v_24 = {}; +try { + (function() { + var Debug = %GetDebugContext().Debug; + + function __f_0() {} + for (var __v_0 = 0; __v_0 < 3; __v_0++) { + var __v_2 = function() { + a = 1; + } + Debug.setListener(__f_0); + if (__v_0 < 2) Debug.setBreakPoint(__v_2); + } + })(); +} catch (e) { + print(); +} diff --git a/deps/v8/test/mjsunit/regress/regress-debug-code-recompilation.js b/deps/v8/test/mjsunit/regress/regress-debug-code-recompilation.js index 4723ec1307..2f81d0cb54 100644 --- a/deps/v8/test/mjsunit/regress/regress-debug-code-recompilation.js +++ b/deps/v8/test/mjsunit/regress/regress-debug-code-recompilation.js @@ -29,6 +29,7 @@ // Flags: --expose-debug-as debug Debug = debug.Debug +Debug.setListener(function(){}); function f() {a=1;b=2}; function g() { @@ -46,3 +47,5 @@ Debug.clearBreakPoint(bp); %OptimizeFunctionOnNextCall(Debug.setBreakPoint); bp = Debug.setBreakPoint(f, 0, 0); Debug.clearBreakPoint(bp); + +Debug.setListener(null); diff --git a/deps/v8/test/mjsunit/regress/regress-debug-deopt-while-recompile.js b/deps/v8/test/mjsunit/regress/regress-debug-deopt-while-recompile.js index ce5220a2b8..52c32e9cc3 100644 --- a/deps/v8/test/mjsunit/regress/regress-debug-deopt-while-recompile.js +++ b/deps/v8/test/mjsunit/regress/regress-debug-deopt-while-recompile.js @@ -26,7 +26,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Flags: --expose-debug-as debug --allow-natives-syntax -// Flags: --turbo-deoptimization Debug = debug.Debug; diff --git a/deps/v8/test/mjsunit/regress/regress-eval-context.js b/deps/v8/test/mjsunit/regress/regress-eval-context.js new file mode 100644 index 0000000000..e376282461 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-eval-context.js @@ -0,0 +1,20 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(function() { + 'use strict'; + var x = 0; + + { + let x = 1; + assertEquals(1, eval("x")); + } + + { + let y = 2; + assertEquals(0, eval("x")); + } + + assertEquals(0, eval("x")); +})(); diff --git a/deps/v8/test/mjsunit/regress/regress-existing-shared-function-info.js b/deps/v8/test/mjsunit/regress/regress-existing-shared-function-info.js new file mode 100644 index 0000000000..a53014c034 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-existing-shared-function-info.js @@ -0,0 +1,18 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-gc + +function f() { + return function g() { + return function h() {} + } +} + +var h = f()(); + +// Make sure code has been flushed. +for (var i of Array(10)) gc(); + +f()(); diff --git a/deps/v8/test/mjsunit/regress/regress-opt-after-debug-deopt.js b/deps/v8/test/mjsunit/regress/regress-opt-after-debug-deopt.js index 5cbaabca55..c637be5497 100644 --- a/deps/v8/test/mjsunit/regress/regress-opt-after-debug-deopt.js +++ b/deps/v8/test/mjsunit/regress/regress-opt-after-debug-deopt.js @@ -27,7 +27,6 @@ // Flags: --expose-debug-as debug --allow-natives-syntax // Flags: --concurrent-recompilation --block-concurrent-recompilation -// Flags: --turbo-deoptimization if (!%IsConcurrentRecompilationSupported()) { print("Concurrent recompilation is disabled. Skipping this test."); diff --git a/deps/v8/test/mjsunit/regress/regress-osr-context.js b/deps/v8/test/mjsunit/regress/regress-osr-context.js new file mode 100644 index 0000000000..8ceb79119a --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-osr-context.js @@ -0,0 +1,19 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --context-specialization --turbo-filter=f + +(function() { + "use strict"; + var a = 23; + function f() { + for (let i = 0; i < 5; ++i) { + a--; // Make sure {a} is non-immutable, hence context allocated. + function g() { return i } // Make sure block has a context. + if (i == 2) %OptimizeOsr(); + } + return a; + } + assertEquals(18, f()); +})(); diff --git a/deps/v8/test/mjsunit/regress/regress-prepare-break-while-recompile.js b/deps/v8/test/mjsunit/regress/regress-prepare-break-while-recompile.js index 0aedcab015..0673220e4a 100644 --- a/deps/v8/test/mjsunit/regress/regress-prepare-break-while-recompile.js +++ b/deps/v8/test/mjsunit/regress/regress-prepare-break-while-recompile.js @@ -54,8 +54,10 @@ foo(); // and (shared) unoptimized code on foo, and sets both to lazy-compile builtin. // Clear the break point immediately after to deactivate the debugger. // Do all of this after compile graph has been created. +Debug.setListener(function(){}); Debug.setBreakPoint(bar, 0, 0); Debug.clearAllBreakPoints(); +Debug.setListener(null); // At this point, concurrent recompilation is still blocked. assertUnoptimized(foo, "no sync"); diff --git a/deps/v8/test/mjsunit/regress/regress-regexp-codeflush.js b/deps/v8/test/mjsunit/regress/regress-regexp-codeflush.js index 5fa42bf8dc..8e7b0396e8 100644 --- a/deps/v8/test/mjsunit/regress/regress-regexp-codeflush.js +++ b/deps/v8/test/mjsunit/regress/regress-regexp-codeflush.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --gc_global +// Flags: --gc-global // Regression test for regexp that has multiple matches and which // internally calls RegExpImpl::IrregexpExecOnce more than once without diff --git a/deps/v8/test/mjsunit/regress/regress-splice-large-index.js b/deps/v8/test/mjsunit/regress/regress-splice-large-index.js index 5da17eecf1..1f4eb9ce59 100644 --- a/deps/v8/test/mjsunit/regress/regress-splice-large-index.js +++ b/deps/v8/test/mjsunit/regress/regress-splice-large-index.js @@ -30,6 +30,7 @@ a[0xfffffffe] = 10; assertThrows("a.unshift(1);", RangeError); assertEquals(0xffffffff, a.length); assertEquals(10, a[0xffffffff]); +assertEquals(0xffffffff, a.length); assertEquals(undefined, a[0xfffffffe]); a = [1,2,3]; diff --git a/deps/v8/test/mjsunit/regress/regress-x87.js b/deps/v8/test/mjsunit/regress/regress-x87.js index 60380a8fcb..c5edb709f8 100644 --- a/deps/v8/test/mjsunit/regress/regress-x87.js +++ b/deps/v8/test/mjsunit/regress/regress-x87.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --allow-natives-syntax --noenable-sse2 +// Flags: --allow-natives-syntax // Regression for register allocation. var x; diff --git a/deps/v8/test/mjsunit/regress/string-set-char-deopt.js b/deps/v8/test/mjsunit/regress/string-set-char-deopt.js index 03100a3505..8956e287db 100644 --- a/deps/v8/test/mjsunit/regress/string-set-char-deopt.js +++ b/deps/v8/test/mjsunit/regress/string-set-char-deopt.js @@ -25,7 +25,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --allow-natives-syntax --turbo-deoptimization +// Flags: --allow-natives-syntax (function OneByteSeqStringSetCharDeoptOsr() { function deopt() { diff --git a/deps/v8/test/mjsunit/samevalue.js b/deps/v8/test/mjsunit/samevalue.js index 36a7dea3ea..229db0db4c 100644 --- a/deps/v8/test/mjsunit/samevalue.js +++ b/deps/v8/test/mjsunit/samevalue.js @@ -26,7 +26,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --expose-natives_as natives +// Flags: --expose-natives-as natives // Test the SameValue internal method. var obj1 = {x: 10, y: 11, z: "test"}; diff --git a/deps/v8/test/mjsunit/strict-mode.js b/deps/v8/test/mjsunit/strict-mode.js index 326e725774..d9939765fc 100644 --- a/deps/v8/test/mjsunit/strict-mode.js +++ b/deps/v8/test/mjsunit/strict-mode.js @@ -25,8 +25,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Flags: --turbo-deoptimization - function CheckStrictMode(code, exception) { assertDoesNotThrow(code); assertThrows("'use strict';\n" + code, exception); diff --git a/deps/v8/test/mjsunit/string-normalize.js b/deps/v8/test/mjsunit/string-normalize.js new file mode 100644 index 0000000000..f88f193a09 --- /dev/null +++ b/deps/v8/test/mjsunit/string-normalize.js @@ -0,0 +1,11 @@ +// 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. + +assertEquals('', ''.normalize()); +assertTrue(delete Array.prototype.indexOf); +assertEquals('', ''.normalize()); + +assertThrows(function() { ''.normalize('invalid'); }, RangeError); +assertTrue(delete Array.prototype.join); +assertThrows(function() { ''.normalize('invalid'); }, RangeError); diff --git a/deps/v8/test/mjsunit/strong/classes.js b/deps/v8/test/mjsunit/strong/classes.js index c329043ae1..c8d261760d 100644 --- a/deps/v8/test/mjsunit/strong/classes.js +++ b/deps/v8/test/mjsunit/strong/classes.js @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --strong-mode -// Flags: --harmony-classes --harmony-arrow-functions +// Flags: --strong-mode --harmony-arrow-functions 'use strong'; diff --git a/deps/v8/test/mjsunit/strong/declaration-after-use.js b/deps/v8/test/mjsunit/strong/declaration-after-use.js index 020067c1e5..5f3ef2a79c 100644 --- a/deps/v8/test/mjsunit/strong/declaration-after-use.js +++ b/deps/v8/test/mjsunit/strong/declaration-after-use.js @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --strong-mode --harmony_rest_parameters --harmony_arrow_functions --harmony_classes --harmony_computed-property_names +// Flags: --strong-mode --harmony-rest-parameters --harmony-arrow-functions +// Flags: --harmony-computed-property-names // Note that it's essential for these tests that the reference is inside dead // code (because we already produce ReferenceErrors for run-time unresolved @@ -192,10 +193,6 @@ function assertThrowsHelper(code) { i; } - let var6 = [1, 2]; - // The second var6 resolves to outside (not to the first var6). - for (let var6 of var6) { var6; } - try { throw "error"; } catch (e) { @@ -211,13 +208,14 @@ function assertThrowsHelper(code) { func2; function func4(p, ...rest) { p; rest; this; func2; } - func4(); + // TODO(arv): The arity checking is not correct with rest parameters. + func4(1, 2); let func5 = (p1, p2) => { p1; p2; }; - func5(); + func5(1, 2); let func5b = p1 => p1; - func5b(); + func5b(1); function func6() { var1, var2a, var2b, var2c; diff --git a/deps/v8/test/mjsunit/strong/function-arity.js b/deps/v8/test/mjsunit/strong/function-arity.js new file mode 100644 index 0000000000..4d8833564c --- /dev/null +++ b/deps/v8/test/mjsunit/strong/function-arity.js @@ -0,0 +1,355 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode --harmony-arrow-functions --harmony-reflect +// Flags: --harmony-spreadcalls --harmony-rest-parameters --allow-natives-syntax + +'use strict'; + + +function generateArguments(n, prefix) { + let a = []; + if (prefix) { + a.push(prefix); + } + for (let i = 0; i < n; i++) { + a.push(String(i)); + } + + return a.join(', '); +} + + +function generateParams(n) { + let a = []; + for (let i = 0; i < n; i++) { + a[i] = `p${i}`; + } + return a.join(', '); +} + +function generateParamsWithRest(n) { + let a = []; + let i = 0; + for (; i < n; i++) { + a[i] = `p${i}`; + } + a.push(`...p${i}`) + return a.join(', '); +} + + +function generateSpread(n) { + return `...[${generateArguments(n)}]`; +} + + +(function FunctionCall() { + for (let parameterCount = 0; parameterCount < 3; parameterCount++) { + let defs = [ + `'use strong'; function f(${generateParams(parameterCount)}) {}`, + `'use strong'; function f(${generateParamsWithRest(parameterCount)}) {}`, + `'use strong'; function* f(${generateParams(parameterCount)}) {}`, + `'use strong'; function* f(${generateParamsWithRest(parameterCount)}) {}`, + `'use strong'; let f = (${generateParams(parameterCount)}) => {}`, + `function f(${generateParams(parameterCount)}) { 'use strong'; }`, + `function* f(${generateParams(parameterCount)}) { 'use strong'; }`, + `let f = (${generateParams(parameterCount)}) => { 'use strong'; }`, + ]; + for (let def of defs) { + for (let argumentCount = 0; argumentCount < 3; argumentCount++) { + let calls = [ + `f(${generateArguments(argumentCount)})`, + `f(${generateSpread(argumentCount)})`, + `f.call(${generateArguments(argumentCount, 'undefined')})`, + `f.call(undefined, ${generateSpread(argumentCount)})`, + `f.apply(undefined, [${generateArguments(argumentCount)}])`, + `f.bind(undefined)(${generateArguments(argumentCount)})`, + `%_CallFunction(${generateArguments(argumentCount, 'undefined')}, + f)`, + `%Call(${generateArguments(argumentCount, 'undefined')}, f)`, + `%Apply(f, undefined, [${generateArguments(argumentCount)}], 0, + ${argumentCount})`, + ]; + + for (let call of calls) { + let code = `'use strict'; ${def}; ${call};`; + if (argumentCount < parameterCount) { + assertThrows(code, TypeError); + } else { + assertDoesNotThrow(code); + } + } + } + + let calls = [ + `f.call()`, + `f.apply()`, + `f.apply(undefined)`, + ]; + for (let call of calls) { + let code = `'use strict'; ${def}; ${call};`; + if (parameterCount > 0) { + assertThrows(code, TypeError); + } else { + assertDoesNotThrow(code); + } + } + } + } +})(); + + +(function MethodCall() { + for (let genParams of [generateParams, generateParamsWithRest]) { + for (let parameterCount = 0; parameterCount < 3; parameterCount++) { + let defs = [ + `let o = new class { + m(${genParams(parameterCount)}) { 'use strong'; } + }`, + `let o = new class { + *m(${genParams(parameterCount)}) { 'use strong'; } + }`, + `let o = { m(${genParams(parameterCount)}) { 'use strong'; } }`, + `let o = { *m(${genParams(parameterCount)}) { 'use strong'; } }`, + `'use strong'; + let o = new class { m(${genParams(parameterCount)}) {} }`, + `'use strong'; + let o = new class { *m(${genParams(parameterCount)}) {} }`, + `'use strong'; let o = { m(${genParams(parameterCount)}) {} }`, + `'use strong'; let o = { *m(${genParams(parameterCount)}) {} }`, + ]; + for (let def of defs) { + for (let argumentCount = 0; argumentCount < 3; argumentCount++) { + let calls = [ + `o.m(${generateArguments(argumentCount)})`, + `o.m(${generateSpread(argumentCount)})`, + `o.m.call(${generateArguments(argumentCount, 'o')})`, + `o.m.call(o, ${generateSpread(argumentCount)})`, + `o.m.apply(o, [${generateArguments(argumentCount)}])`, + `o.m.bind(o)(${generateArguments(argumentCount)})`, + `%_CallFunction(${generateArguments(argumentCount, 'o')}, o.m)`, + `%Call(${generateArguments(argumentCount, 'o')}, o.m)`, + `%Apply(o.m, o, [${generateArguments(argumentCount)}], 0, + ${argumentCount})`, + ]; + + for (let call of calls) { + let code = `'use strict'; ${def}; ${call};`; + if (argumentCount < parameterCount) { + assertThrows(code, TypeError); + } else { + assertDoesNotThrow(code); + } + } + } + + let calls = [ + `o.m.call()`, + `o.m.apply()`, + `o.m.apply(o)`, + ]; + for (let call of calls) { + let code = `'use strict'; ${def}; ${call};`; + if (parameterCount > 0) { + assertThrows(code, TypeError); + } else { + assertDoesNotThrow(code); + } + } + } + } + } +})(); + + +(function Constructor() { + for (let genParams of [generateParams, generateParamsWithRest]) { + for (let argumentCount = 0; argumentCount < 3; argumentCount++) { + for (let parameterCount = 0; parameterCount < 3; parameterCount++) { + let defs = [ + `'use strong'; + class C { constructor(${genParams(parameterCount)}) {} }`, + `'use strict'; + class C { + constructor(${genParams(parameterCount)}) { 'use strong'; } + }`, + ]; + for (let def of defs) { + let calls = [ + `new C(${generateArguments(argumentCount)})`, + `new C(${generateSpread(argumentCount)})`, + `Reflect.construct(C, [${generateArguments(argumentCount)}])`, + ]; + for (let call of calls) { + let code = `${def}; ${call};`; + if (argumentCount < parameterCount) { + assertThrows(code, TypeError); + } else { + assertDoesNotThrow(code); + } + } + } + } + } + } +})(); + + +(function DerivedConstructor() { + for (let genParams of [generateParams, generateParamsWithRest]) { + for (let genArgs of [generateArguments, generateSpread]) { + for (let argumentCount = 0; argumentCount < 3; argumentCount++) { + for (let parameterCount = 0; parameterCount < 3; parameterCount++) { + let defs = [ + `'use strong'; + class B { + constructor(${genParams(parameterCount)}) {} + } + class C extends B { + constructor() { + super(${genArgs(argumentCount)}); + } + }`, + `'use strict'; + class B { + constructor(${genParams(parameterCount)}) { 'use strong'; } + } + class C extends B { + constructor() { + super(${genArgs(argumentCount)}); + } + }`, + ]; + for (let def of defs) { + let code = `${def}; new C();`; + if (argumentCount < parameterCount) { + assertThrows(code, TypeError); + } else { + assertDoesNotThrow(code); + } + } + } + } + } + } +})(); + + +(function DerivedConstructorDefaultConstructorInDerivedClass() { + for (let genParams of [generateParams, generateParamsWithRest]) { + for (let genArgs of [generateArguments, generateSpread]) { + for (let argumentCount = 0; argumentCount < 3; argumentCount++) { + for (let parameterCount = 0; parameterCount < 3; parameterCount++) { + let defs = [ + `'use strong'; + class B { + constructor(${genParams(parameterCount)}) {} + } + class C extends B {}`, + `'use strict'; + class B { + constructor(${genParams(parameterCount)}) { 'use strong'; } + } + class C extends B {}`, + ]; + for (let def of defs) { + let code = `${def}; new C(${genArgs(argumentCount)})`; + if (argumentCount < parameterCount) { + assertThrows(code, TypeError); + } else { + assertDoesNotThrow(code); + } + } + } + } + } + } +})(); + + +(function TestOptimized() { + function f(x, y) { 'use strong'; } + + assertThrows(f, TypeError); + %OptimizeFunctionOnNextCall(f); + assertThrows(f, TypeError); + + function g() { + f(1); + } + assertThrows(g, TypeError); + %OptimizeFunctionOnNextCall(g); + assertThrows(g, TypeError); + + f(1, 2); + %OptimizeFunctionOnNextCall(f); + f(1, 2); +})(); + + +(function TestOptimized2() { + 'use strong'; + function f(x, y) {} + + assertThrows(f, TypeError); + %OptimizeFunctionOnNextCall(f); + assertThrows(f, TypeError); + + function g() { + f(1); + } + assertThrows(g, TypeError); + %OptimizeFunctionOnNextCall(g); + assertThrows(g, TypeError); + + f(1, 2); + %OptimizeFunctionOnNextCall(f); + f(1, 2); +})(); + + +(function TestOptimized3() { + function f(x, y) {} + function g() { + 'use strong'; + f(1); + } + + g(); + %OptimizeFunctionOnNextCall(f); + g(); +})(); + + +(function ParametersSuper() { + for (let genArgs of [generateArguments, generateSpread]) { + for (let argumentCount = 0; argumentCount < 3; argumentCount++) { + for (let parameterCount = 0; parameterCount < 3; parameterCount++) { + let defs = [ + `'use strict'; + class B { + m(${generateParams(parameterCount)} ){ 'use strong' } + }`, + `'use strong'; class B { m(${generateParams(parameterCount)}) {} }`, + ]; + for (let def of defs) { + let code = `${def}; + class D extends B { + m() { + super.m(${genArgs(argumentCount)}); + } + } + new D().m()`; + print('\n\n' + code); + if (argumentCount < parameterCount) { + assertThrows(code, TypeError); + } else { + assertDoesNotThrow(code); + } + } + } + } + } +})(); diff --git a/deps/v8/test/mjsunit/strong/functions.js b/deps/v8/test/mjsunit/strong/functions.js index 6956462e5d..a237270977 100644 --- a/deps/v8/test/mjsunit/strong/functions.js +++ b/deps/v8/test/mjsunit/strong/functions.js @@ -47,8 +47,8 @@ function* g() {} (function LexicalBindings(global) { assertEquals('function', typeof f); assertEquals('function', typeof g); - assertEquals(undefined, global.f); - assertEquals(undefined, global.g); + assertFalse(global.hasOwnProperty("f")); + assertFalse(global.hasOwnProperty("g")); })(this); (function ImmutableBindings() { diff --git a/deps/v8/test/mjsunit/strong/implicit-conversions-constants.js b/deps/v8/test/mjsunit/strong/implicit-conversions-constants.js new file mode 100644 index 0000000000..c24056299f --- /dev/null +++ b/deps/v8/test/mjsunit/strong/implicit-conversions-constants.js @@ -0,0 +1,203 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode --allow-natives-syntax + +"use strict"; + +function getTestFuncs() { + "use strong"; + return [ + function(x){return 1 + true;}, + function(x){return 1 - true;}, + function(x){return 1 * true;}, + function(x){return 1 / true;}, + function(x){return 1 % true;}, + function(x){return 1 | true;}, + function(x){return 1 & true;}, + function(x){return 1 ^ true;}, + function(x){return 1 << true;}, + function(x){return 1 >> true;}, + function(x){return 1 >>> true;}, + function(x){return 1 < true;}, + function(x){return 1 > true;}, + function(x){return 1 <= true;}, + function(x){return 1 >= true;}, + function(x){return 1 + undefined;}, + function(x){return 1 - undefined;}, + function(x){return 1 * undefined;}, + function(x){return 1 / undefined;}, + function(x){return 1 % undefined;}, + function(x){return 1 | undefined;}, + function(x){return 1 & undefined;}, + function(x){return 1 ^ undefined;}, + function(x){return 1 << undefined;}, + function(x){return 1 >> undefined;}, + function(x){return 1 >>> undefined;}, + function(x){return 1 < undefined;}, + function(x){return 1 > undefined;}, + function(x){return 1 <= undefined;}, + function(x){return 1 >= undefined;}, + function(x){return 1 + null;}, + function(x){return 1 - null;}, + function(x){return 1 * null;}, + function(x){return 1 / null;}, + function(x){return 1 % null;}, + function(x){return 1 | null;}, + function(x){return 1 & null;}, + function(x){return 1 ^ null;}, + function(x){return 1 << null;}, + function(x){return 1 >> null;}, + function(x){return 1 >>> null;}, + function(x){return 1 < null;}, + function(x){return 1 > null;}, + function(x){return 1 <= null;}, + function(x){return 1 >= null;}, + function(x){return NaN + true;}, + function(x){return NaN - true;}, + function(x){return NaN * true;}, + function(x){return NaN / true;}, + function(x){return NaN % true;}, + function(x){return NaN | true;}, + function(x){return NaN & true;}, + function(x){return NaN ^ true;}, + function(x){return NaN << true;}, + function(x){return NaN >> true;}, + function(x){return NaN >>> true;}, + function(x){return NaN < true;}, + function(x){return NaN > true;}, + function(x){return NaN <= true;}, + function(x){return NaN >= true;}, + function(x){return NaN + undefined;}, + function(x){return NaN - undefined;}, + function(x){return NaN * undefined;}, + function(x){return NaN / undefined;}, + function(x){return NaN % undefined;}, + function(x){return NaN | undefined;}, + function(x){return NaN & undefined;}, + function(x){return NaN ^ undefined;}, + function(x){return NaN << undefined;}, + function(x){return NaN >> undefined;}, + function(x){return NaN >>> undefined;}, + function(x){return NaN < undefined;}, + function(x){return NaN > undefined;}, + function(x){return NaN <= undefined;}, + function(x){return NaN >= undefined;}, + function(x){return NaN + null;}, + function(x){return NaN - null;}, + function(x){return NaN * null;}, + function(x){return NaN / null;}, + function(x){return NaN % null;}, + function(x){return NaN | null;}, + function(x){return NaN & null;}, + function(x){return NaN ^ null;}, + function(x){return NaN << null;}, + function(x){return NaN >> null;}, + function(x){return NaN >>> null;}, + function(x){return NaN < null;}, + function(x){return NaN > null;}, + function(x){return NaN <= null;}, + function(x){return NaN >= null;}, + function(x){return true + 1;}, + function(x){return true - 1;}, + function(x){return true * 1;}, + function(x){return true / 1;}, + function(x){return true % 1;}, + function(x){return true | 1;}, + function(x){return true & 1;}, + function(x){return true ^ 1;}, + function(x){return true << 1;}, + function(x){return true >> 1;}, + function(x){return true >>> 1;}, + function(x){return true < 1;}, + function(x){return true > 1;}, + function(x){return true <= 1;}, + function(x){return true >= 1;}, + function(x){return undefined + 1;}, + function(x){return undefined - 1;}, + function(x){return undefined * 1;}, + function(x){return undefined / 1;}, + function(x){return undefined % 1;}, + function(x){return undefined | 1;}, + function(x){return undefined & 1;}, + function(x){return undefined ^ 1;}, + function(x){return undefined << 1;}, + function(x){return undefined >> 1;}, + function(x){return undefined >>> 1;}, + function(x){return undefined < 1;}, + function(x){return undefined > 1;}, + function(x){return undefined <= 1;}, + function(x){return undefined >= 1;}, + function(x){return null + 1;}, + function(x){return null - 1;}, + function(x){return null * 1;}, + function(x){return null / 1;}, + function(x){return null % 1;}, + function(x){return null | 1;}, + function(x){return null & 1;}, + function(x){return null ^ 1;}, + function(x){return null << 1;}, + function(x){return null >> 1;}, + function(x){return null >>> 1;}, + function(x){return null < 1;}, + function(x){return null > 1;}, + function(x){return null <= 1;}, + function(x){return null >= 1;}, + function(x){return true + NaN;}, + function(x){return true - NaN;}, + function(x){return true * NaN;}, + function(x){return true / NaN;}, + function(x){return true % NaN;}, + function(x){return true | NaN;}, + function(x){return true & NaN;}, + function(x){return true ^ NaN;}, + function(x){return true << NaN;}, + function(x){return true >> NaN;}, + function(x){return true >>> NaN;}, + function(x){return true < NaN;}, + function(x){return true > NaN;}, + function(x){return true <= NaN;}, + function(x){return true >= NaN;}, + function(x){return undefined + NaN;}, + function(x){return undefined - NaN;}, + function(x){return undefined * NaN;}, + function(x){return undefined / NaN;}, + function(x){return undefined % NaN;}, + function(x){return undefined | NaN;}, + function(x){return undefined & NaN;}, + function(x){return undefined ^ NaN;}, + function(x){return undefined << NaN;}, + function(x){return undefined >> NaN;}, + function(x){return undefined >>> NaN;}, + function(x){return undefined < NaN;}, + function(x){return undefined > NaN;}, + function(x){return undefined <= NaN;}, + function(x){return undefined >= NaN;}, + function(x){return null + NaN;}, + function(x){return null - NaN;}, + function(x){return null * NaN;}, + function(x){return null / NaN;}, + function(x){return null % NaN;}, + function(x){return null | NaN;}, + function(x){return null & NaN;}, + function(x){return null ^ NaN;}, + function(x){return null << NaN;}, + function(x){return null >> NaN;}, + function(x){return null >>> NaN;}, + function(x){return null < NaN;}, + function(x){return null > NaN;}, + function(x){return null <= NaN;}, + function(x){return null >= NaN;} + ]; +} + +for (let func of getTestFuncs()) { + assertThrows(func, TypeError); + assertThrows(func, TypeError); + assertThrows(func, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(func, TypeError); + %DeoptimizeFunction(func); + assertThrows(func, TypeError); +} diff --git a/deps/v8/test/mjsunit/strong/implicit-conversions-count.js b/deps/v8/test/mjsunit/strong/implicit-conversions-count.js new file mode 100644 index 0000000000..88ed3c2068 --- /dev/null +++ b/deps/v8/test/mjsunit/strong/implicit-conversions-count.js @@ -0,0 +1,168 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode --allow-natives-syntax + +"use strict"; + +function pre_inc(x) { + return ++x; +} + +function post_inc(x) { + return x++; +} + +function pre_dec(x) { + return --x; +} + +function post_dec(x) { + return x--; +} + +function getTestFuncs() { + return [ + function(x){ + "use strong"; + let y = x; + assertEquals(++y, pre_inc(x)); + try { + assertEquals(x+1, y) + } catch (e) { + assertUnreachable(); + } + }, + function(x){ + "use strong"; + let y = x; + assertEquals(y++, post_inc(x)); + try { + assertEquals(x+1, y) + } catch (e) { + assertUnreachable(); + } + }, + function(x){ + "use strong"; + let y = x; + assertEquals(--y, pre_dec(x)); + try { + assertEquals(x-1, y) + } catch (e) { + assertUnreachable(); + } + }, + function(x){ + "use strong"; + let y = x; + assertEquals(y--, post_dec(x)); + try { + assertEquals(x-1, y) + } catch (e) { + assertUnreachable(); + } + }, + function(x){ + "use strong"; + let obj = { foo: x }; + let y = ++obj.foo; + assertEquals(y, pre_inc(x)); + try { + assertEquals(x+1, obj.foo) + } catch (e) { + assertUnreachable(); + } + }, + function(x){ + "use strong"; + let obj = { foo: x }; + let y = obj.foo++; + assertEquals(y, post_inc(x)); + try { + assertEquals(x+1, obj.foo) + } catch (e) { + assertUnreachable(); + } + }, + function(x){ + "use strong"; + let obj = { foo: x }; + let y = --obj.foo; + assertEquals(y, pre_dec(x)); + try { + assertEquals(x-1, obj.foo) + } catch (e) { + assertUnreachable(); + } + }, + function(x){ + "use strong"; + let obj = { foo: x }; + let y = obj.foo--; + assertEquals(y, post_dec(x)); + try { + assertEquals(x-1, obj.foo) + } catch (e) { + assertUnreachable(); + } + }, + ]; +} + +let nonNumberValues = [ + {}, + (function(){}), + [], + (class Foo {}), + "", + "foo", + "NaN", + Object(""), + false, + null, + undefined +]; + +// Check prior input of None works +for (let func of getTestFuncs()) { + for (let value of nonNumberValues) { + assertThrows(function(){func(value)}, TypeError); + assertThrows(function(){func(value)}, TypeError); + assertThrows(function(){func(value)}, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(function(){func(value)}, TypeError); + %DeoptimizeFunction(func); + } +} + +// Check prior input of Smi works +for (let func of getTestFuncs()) { + func(1); + func(1); + func(1); + for (let value of nonNumberValues) { + assertThrows(function(){func(value)}, TypeError); + assertThrows(function(){func(value)}, TypeError); + assertThrows(function(){func(value)}, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(function(){func(value)}, TypeError); + %DeoptimizeFunction(func); + } +} + +// Check prior input of Number works +for (let func of getTestFuncs()) { + func(9999999999999); + func(9999999999999); + func(9999999999999); + for (let value of nonNumberValues) { + assertThrows(function(){func(value)}, TypeError); + assertThrows(function(){func(value)}, TypeError); + assertThrows(function(){func(value)}, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(function(){func(value)}, TypeError); + %DeoptimizeFunction(func); + } +} diff --git a/deps/v8/test/mjsunit/strong/implicit-conversions-inlining.js b/deps/v8/test/mjsunit/strong/implicit-conversions-inlining.js index f1cb9cd36d..15997a37aa 100644 --- a/deps/v8/test/mjsunit/strong/implicit-conversions-inlining.js +++ b/deps/v8/test/mjsunit/strong/implicit-conversions-inlining.js @@ -6,6 +6,8 @@ "use strict"; +//****************************************************************************** +// Number function declarations function inline_add_strong(x, y) { "use strong"; return x + y; @@ -105,6 +107,42 @@ function inline_sar_strong_outer(x, y) { return inline_sar_strong(x, y); } +function inline_less_strong(x, y) { + "use strong"; + return x < y; +} + +function inline_less_strong_outer(x, y) { + return inline_less_strong(x, y); +} + +function inline_greater_strong(x, y) { + "use strong"; + return x > y; +} + +function inline_greater_strong_outer(x, y) { + return inline_greater_strong(x, y); +} + +function inline_less_equal_strong(x, y) { + "use strong"; + return x <= y; +} + +function inline_less_equal_strong_outer(x, y) { + return inline_less_equal_strong(x, y); +} + +function inline_greater_equal_strong(x, y) { + "use strong"; + return x >= y; +} + +function inline_greater_equal_strong_outer(x, y) { + return inline_greater_equal_strong(x, y); +} + function inline_add(x, y) { return x + y; } @@ -204,19 +242,170 @@ function inline_sar_outer_strong(x, y) { return inline_sar(x, y); } -let strong_inner_funcs = [inline_add_strong_outer, inline_sub_strong_outer, - inline_mul_strong_outer, inline_div_strong_outer, - inline_mod_strong_outer, inline_or_strong_outer, - inline_and_strong_outer, inline_xor_strong_outer, - inline_shl_strong_outer, inline_shr_strong_outer]; +function inline_less(x, y) { + return x < y; +} + +function inline_less_outer_strong(x, y) { + "use strong"; + return inline_less(x, y); +} + +function inline_greater(x, y) { + return x > y; +} + +function inline_greater_outer_strong(x, y) { + "use strong"; + return inline_greater(x, y); +} -let strong_outer_funcs = [inline_add_outer_strong, inline_sub_outer_strong, - inline_mul_outer_strong, inline_div_outer_strong, - inline_mod_outer_strong, inline_or_outer_strong, - inline_and_outer_strong, inline_xor_outer_strong, - inline_shl_outer_strong, inline_shr_outer_strong]; +function inline_less_equal(x, y) { + return x <= y; +} + +function inline_less_equal_outer_strong(x, y) { + "use strong"; + return inline_less_equal(x, y); +} + +function inline_greater_equal(x, y) { + return x >>> y; +} + +function inline_greater_equal_outer_strong(x, y) { + "use strong"; + return inline_greater_equal(x, y); +} + +//****************************************************************************** +// String function declarations +function inline_add_string_strong(x, y) { + "use strong"; + return x + y; +} + +function inline_add_string_strong_outer(x, y) { + return inline_add_string_strong(x, y); +} + +function inline_less_string_strong(x, y) { + "use strong"; + return x < y; +} + +function inline_less_string_strong_outer(x, y) { + return inline_less_string_strong(x, y); +} -for (let strong_inner_func of strong_inner_funcs) { +function inline_greater_string_strong(x, y) { + "use strong"; + return x > y; +} + +function inline_greater_string_strong_outer(x, y) { + return inline_greater_string_strong(x, y); +} + +function inline_less_equal_string_strong(x, y) { + "use strong"; + return x <= y; +} + +function inline_less_equal_string_strong_outer(x, y) { + return inline_less_equal_string_strong(x, y); +} + +function inline_greater_equal_string_strong(x, y) { + "use strong"; + return x >= y; +} + +function inline_greater_equal_string_strong_outer(x, y) { + return inline_greater_equal_string_strong(x, y); +} + +function inline_add_string(x, y) { + return x + y; +} + +function inline_add_string_outer_strong(x, y) { + "use strong"; + return inline_add_string(x, y); +} + +function inline_less_string(x, y) { + return x < y; +} + +function inline_less_string_outer_strong(x, y) { + "use strong"; + return inline_less_string(x, y); +} + +function inline_greater_string(x, y) { + return x > y; +} + +function inline_greater_string_outer_strong(x, y) { + "use strong"; + return inline_greater_string(x, y); +} + +function inline_less_equal_string(x, y) { + return x <= y; +} + +function inline_less_equal_string_outer_strong(x, y) { + "use strong"; + return inline_less_equal_string(x, y); +} + +function inline_greater_equal_string(x, y) { + return x >= y; +} + +function inline_greater_equal_string_outer_strong(x, y) { + "use strong"; + return inline_greater_equal_string(x, y); +} + + +//****************************************************************************** +// Testing +let strong_inner_funcs_num = [inline_add_strong_outer, inline_sub_strong_outer, + inline_mul_strong_outer, inline_div_strong_outer, + inline_mod_strong_outer, inline_or_strong_outer, + inline_and_strong_outer, inline_xor_strong_outer, + inline_shl_strong_outer, inline_shr_strong_outer, + inline_less_strong_outer, + inline_greater_strong_outer, + inline_less_equal_strong_outer, + inline_greater_equal_strong_outer]; + +let strong_outer_funcs_num = [inline_add_outer_strong, inline_sub_outer_strong, + inline_mul_outer_strong, inline_div_outer_strong, + inline_mod_outer_strong, inline_or_outer_strong, + inline_and_outer_strong, inline_xor_outer_strong, + inline_shl_outer_strong, inline_shr_outer_strong, + inline_less_outer_strong, + inline_greater_outer_strong, + inline_less_equal_outer_strong, + inline_greater_equal_outer_strong]; + +let strong_inner_funcs_string = [inline_add_string_strong_outer, + inline_less_string_strong_outer, + inline_greater_string_strong_outer, + inline_less_equal_string_strong_outer, + inline_greater_equal_string_strong_outer]; + +let strong_outer_funcs_string = [inline_add_string_outer_strong, + inline_less_string_outer_strong, + inline_greater_string_outer_strong, + inline_less_equal_string_outer_strong, + inline_greater_equal_string_outer_strong]; + +for (let strong_inner_func of strong_inner_funcs_num) { assertThrows(function(){strong_inner_func(1, {})}, TypeError); for (var i = 0; i < 100; i++) { strong_inner_func(1, 2); @@ -225,7 +414,7 @@ for (let strong_inner_func of strong_inner_funcs) { assertThrows(function(){strong_inner_func(1, {})}, TypeError); } -for (let strong_outer_func of strong_outer_funcs) { +for (let strong_outer_func of strong_outer_funcs_num) { assertDoesNotThrow(function(){strong_outer_func(1, {})}); for (var i = 0; i < 100; i++) { strong_outer_func(1, 2); @@ -233,3 +422,21 @@ for (let strong_outer_func of strong_outer_funcs) { %OptimizeFunctionOnNextCall(strong_outer_func); assertDoesNotThrow(function(){strong_outer_func(1, {})}); } + +for (let strong_inner_func of strong_inner_funcs_string) { + assertThrows(function(){strong_inner_func("foo", {})}, TypeError); + for (var i = 0; i < 100; i++) { + strong_inner_func("foo", "bar"); + } + %OptimizeFunctionOnNextCall(strong_inner_func); + assertThrows(function(){strong_inner_func("foo", {})}, TypeError); +} + +for (let strong_outer_func of strong_outer_funcs_string) { + assertDoesNotThrow(function(){strong_outer_func("foo", {})}); + for (var i = 0; i < 100; i++) { + strong_outer_func("foo", "bar"); + } + %OptimizeFunctionOnNextCall(strong_outer_func); + assertDoesNotThrow(function(){strong_outer_func("foo", {})}); +} diff --git a/deps/v8/test/mjsunit/strong/implicit-conversions.js b/deps/v8/test/mjsunit/strong/implicit-conversions.js index c13953583f..cd8acf7085 100644 --- a/deps/v8/test/mjsunit/strong/implicit-conversions.js +++ b/deps/v8/test/mjsunit/strong/implicit-conversions.js @@ -6,22 +6,26 @@ "use strict"; -// TODO(conradw): Implement other strong operators +// Boolean indicates whether an operator can be part of a compound assignment. let strongNumberBinops = [ - "-", - "*", - "/", - "%", - "|", - "&", - "^", - "<<", - ">>", - ">>>", + ["-", true], + ["*", true], + ["/", true], + ["%", true], + ["|", true], + ["&", true], + ["^", true], + ["<<", true], + [">>", true], + [">>>", true] ]; let strongStringOrNumberBinops = [ - "+" + ["+", true], + ["<", false], + [">", false], + ["<=", false], + [">=", false] ]; let strongBinops = strongNumberBinops.concat(strongStringOrNumberBinops); @@ -33,6 +37,8 @@ let strongUnops = [ ]; let nonStringOrNumberValues = [ + "null", + "undefined", "{}", "false", "(function(){})", @@ -55,23 +61,17 @@ let numberValues = [ "0", "(-0)", "1", - "0.79", - "(-0.79)", - "4294967295", - "4294967296", "(-4294967295)", "(-4294967296)", "9999999999999", "(-9999999999999)", - "1.5e10", - "(-1.5e10)", - "0xFFF", - "(-0xFFF)", "NaN", "Infinity", "(-Infinity)" ]; +//****************************************************************************** +// Relational comparison function declarations function add_strong(x, y) { "use strong"; return x + y; @@ -132,6 +132,46 @@ function sar_strong(x, y) { return x >>> y; } +function less_strong(x, y) { + "use strong"; + return x < y; +} + +function less_num_strong(x, y) { + "use strong"; + return x < y; +} + +function greater_strong(x, y) { + "use strong"; + return x > y; +} + +function greater_num_strong(x, y) { + "use strong"; + return x > y; +} + +function less_equal_strong(x, y) { + "use strong"; + return x <= y; +} + +function less_equal_num_strong(x, y) { + "use strong"; + return x <= y; +} + +function greater_equal_strong(x, y) { + "use strong"; + return x >= y; +} + +function greater_equal_num_strong(x, y) { + "use strong"; + return x >= y; +} + function typed_add_strong(x, y) { "use strong"; return (+x) + (+y); @@ -187,15 +227,52 @@ function typed_sar_strong(x, y) { return (+x) >>> (+y); } +function typed_less_strong(x, y) { + "use strong"; + return (+x) < (+y); +} + +function typed_greater_strong(x, y) { + "use strong"; + return (+x) > (+y); +} + +function typed_less_equal_strong(x, y) { + "use strong"; + return (+x) <= (+y); +} + +function typed_greater_equal_strong(x, y) { + "use strong"; + return (+x) >= (+y); +} + +//****************************************************************************** +// (in)equality function declarations +function str_equal_strong(x, y) { + "use strong"; + return x === y; +} + +function str_ineq_strong(x, y) { + "use strong"; + return x !== y; +} + let strongNumberFuncs = [add_num_strong, sub_strong, mul_strong, div_strong, mod_strong, or_strong, and_strong, xor_strong, - shl_strong, shr_strong, sar_strong, typed_add_strong, + shl_strong, shr_strong, sar_strong, less_num_strong, + greater_num_strong, less_equal_num_strong, + greater_equal_num_strong, typed_add_strong, typed_sub_strong, typed_mul_strong, typed_div_strong, typed_mod_strong, typed_or_strong, typed_and_strong, typed_xor_strong, typed_shl_strong, typed_shr_strong, - typed_sar_strong]; + typed_sar_strong, typed_less_strong, + typed_greater_strong, typed_less_equal_strong, + typed_greater_equal_strong]; -let strongStringOrNumberFuncs = [add_strong]; +let strongStringOrNumberFuncs = [add_strong, less_strong, greater_strong, + less_equal_strong, greater_equal_strong]; let strongFuncs = strongNumberFuncs.concat(strongStringOrNumberFuncs); @@ -214,16 +291,20 @@ function assertStrongThrowBehaviour(expr) { function checkArgumentCombinations(op, leftList, rightList, willThrow) { for (let v1 of leftList) { - let assignExpr = "foo " + op + "= " + v1 + ";"; + let assignExpr = "foo " + op[0] + "= " + v1 + ";"; for (let v2 of rightList) { let compoundAssignment = "'use strong'; let foo = " + v2 + "; " + assignExpr; - if(willThrow) { - assertThrows(compoundAssignment, TypeError); - assertStrongThrowBehaviour("(" + v1 + op + v2 + ")"); + if (willThrow) { + if (op[1]) { + assertThrows(compoundAssignment, TypeError); + } + assertStrongThrowBehaviour("(" + v1 + op[0] + v2 + ")"); } else { - assertDoesNotThrow(compoundAssignment); - assertStrongNonThrowBehaviour("(" + v1 + op + v2 + ")"); + if (op[1]) { + assertDoesNotThrow(compoundAssignment); + } + assertStrongNonThrowBehaviour("(" + v1 + op[0] + v2 + ")"); } } } @@ -257,44 +338,75 @@ for (let op of strongUnops) { for (let func of strongNumberFuncs) { // Check IC None*None->None throws - assertThrows(function(){func(2, "foo");}, TypeError); - %OptimizeFunctionOnNextCall(func); - assertThrows(function(){func(2, "foo");}, TypeError); - %DeoptimizeFunction(func); + for (let v of nonNumberValues) { + let value = eval(v); + assertThrows(function(){func(2, value);}, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(function(){func(2, value);}, TypeError); + %DeoptimizeFunction(func); + } func(4, 5); func(4, 5); // Check IC Smi*Smi->Smi throws - assertThrows(function(){func(2, "foo");}, TypeError); - %OptimizeFunctionOnNextCall(func); - assertThrows(function(){func(2, "foo");}, TypeError); - %DeoptimizeFunction(func); + for (let v of nonNumberValues) { + let value = eval(v); + assertThrows(function(){func(2, value);}, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(function(){func(2, value);}, TypeError); + %DeoptimizeFunction(func); + } func(NaN, NaN); func(NaN, NaN); // Check IC Number*Number->Number throws - assertThrows(function(){func(2, "foo");}, TypeError); - %OptimizeFunctionOnNextCall(func); - assertThrows(function(){func(2, "foo");}, TypeError); - %DeoptimizeFunction(func); + for (let v of nonNumberValues) { + let value = eval(v); + assertThrows(function(){func(2, value);}, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(function(){func(2, value);}, TypeError); + %DeoptimizeFunction(func); + } } for (let func of strongStringOrNumberFuncs) { // Check IC None*None->None throws - assertThrows(function(){func(2, "foo");}, TypeError); - %OptimizeFunctionOnNextCall(func); - assertThrows(function(){func(2, "foo");}, TypeError); - %DeoptimizeFunction(func); + for (let v of nonNumberValues) { + let value = eval(v); + assertThrows(function(){func(2, value);}, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(function(){func(2, value);}, TypeError); + %DeoptimizeFunction(func); + } func("foo", "bar"); func("foo", "bar"); // Check IC String*String->String throws - assertThrows(function(){func(2, "foo");}, TypeError); - %OptimizeFunctionOnNextCall(func); - assertThrows(function(){func(2, "foo");}, TypeError); - %DeoptimizeFunction(func); + for (let v of nonNumberValues) { + let value = eval(v); + assertThrows(function(){func(2, value);}, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(function(){func(2, value);}, TypeError); + %DeoptimizeFunction(func); + } func(NaN, NaN); func(NaN, NaN); // Check IC Generic*Generic->Generic throws - assertThrows(function(){func(2, "foo");}, TypeError); + for (let v of nonNumberValues) { + let value = eval(v); + assertThrows(function(){func(2, value);}, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(function(){func(2, value);}, TypeError); + %DeoptimizeFunction(func); + } +} + +for (let func of [str_equal_strong, str_ineq_strong]) { + assertDoesNotThrow(function(){func(2, undefined)}); + assertDoesNotThrow(function(){func(2, undefined)}); + %OptimizeFunctionOnNextCall(func); + assertDoesNotThrow(function(){func(2, undefined)}); + %DeoptimizeFunction(func); + assertDoesNotThrow(function(){func(true, {})}); + assertDoesNotThrow(function(){func(true, {})}); %OptimizeFunctionOnNextCall(func); - assertThrows(function(){func(2, "foo");}, TypeError); + assertDoesNotThrow(function(){func(true, {})}); %DeoptimizeFunction(func); } diff --git a/deps/v8/test/mjsunit/strong/literals.js b/deps/v8/test/mjsunit/strong/literals.js new file mode 100644 index 0000000000..73129e7a09 --- /dev/null +++ b/deps/v8/test/mjsunit/strong/literals.js @@ -0,0 +1,352 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode --allow-natives-syntax +// Flags: --harmony-arrow-functions --harmony-rest-parameters +// Flags: --harmony-destructuring --harmony-spread-arrays + +'use strict'; + +(function WeakObjectLiterals() { + function assertWeakObject(x) { + assertFalse(%IsStrong(x)); + assertSame(Object.prototype, Object.getPrototypeOf(x)); + } + assertWeakObject({}); + assertWeakObject({a: 0, b: 0}); + assertWeakObject({a: [], b: {}}); + assertWeakObject({a: [], b: {}}.b); + assertWeakObject({a: {b: {c: {}}}}.a); + assertWeakObject({a: {b: {c: {}}}}.a.b); + assertWeakObject({a: {b: {c: {}}}}.a.b.c); + assertWeakObject([[1], {}, [[3]]][1]); + assertWeakObject({f: function(){}}); + assertWeakObject( + Realm.eval(Realm.current(), "({f: function(){}})")); +})(); + +(function StrongObjectLiterals() { + 'use strong'; + function assertStrongObject(x) { + assertTrue(%IsStrong(x)); + assertSame(Object.prototype, Object.getPrototypeOf(x)); + } + assertStrongObject({}); + assertStrongObject({a: 0, b: 0}); + assertStrongObject({a: [], b: {}}); + assertStrongObject({a: [], b: {}}.b); + assertStrongObject({a: {b: {c: {}}}}.a); + assertStrongObject({a: {b: {c: {}}}}.a.b); + assertStrongObject({a: {b: {c: {}}}}.a.b.c); + // Maps for literals with too many properties are not cached. + assertStrongObject({ + x001: 0, x002: 0, x003: 0, x004: 0, x005: 0, + x006: 0, x007: 0, x008: 0, x009: 0, x010: 0, + x011: 0, x012: 0, x013: 0, x014: 0, x015: 0, + x016: 0, x017: 0, x018: 0, x019: 0, x020: 0, + x021: 0, x022: 0, x023: 0, x024: 0, x025: 0, + x026: 0, x027: 0, x028: 0, x029: 0, x030: 0, + x031: 0, x032: 0, x033: 0, x034: 0, x035: 0, + x036: 0, x037: 0, x038: 0, x039: 0, x040: 0, + x041: 0, x042: 0, x043: 0, x044: 0, x045: 0, + x046: 0, x047: 0, x048: 0, x049: 0, x050: 0, + x051: 0, x052: 0, x053: 0, x054: 0, x055: 0, + x056: 0, x057: 0, x058: 0, x059: 0, x060: 0, + x061: 0, x062: 0, x063: 0, x064: 0, x065: 0, + x066: 0, x067: 0, x068: 0, x069: 0, x070: 0, + x071: 0, x072: 0, x073: 0, x074: 0, x075: 0, + x076: 0, x077: 0, x078: 0, x079: 0, x080: 0, + x081: 0, x082: 0, x083: 0, x084: 0, x085: 0, + x086: 0, x087: 0, x088: 0, x089: 0, x090: 0, + x091: 0, x092: 0, x093: 0, x094: 0, x095: 0, + x096: 0, x097: 0, x098: 0, x099: 0, x100: 0, + x101: 0, x102: 0, x103: 0, x104: 0, x105: 0, + x106: 0, x107: 0, x108: 0, x109: 0, x110: 0, + x111: 0, x112: 0, x113: 0, x114: 0, x115: 0, + x116: 0, x117: 0, x118: 0, x119: 0, x120: 0, + x121: 0, x122: 0, x123: 0, x124: 0, x125: 0, + x126: 0, x127: 0, x128: 0, x129: 0, x130: 0, + x131: 0, x132: 0, x133: 0, x134: 0, x135: 0, + x136: 0, x137: 0, x138: 0, x139: 0, x140: 0, + x141: 0, x142: 0, x143: 0, x144: 0, x145: 0, + x146: 0, x147: 0, x148: 0, x149: 0, x150: 0, + x151: 0, x152: 0, x153: 0, x154: 0, x155: 0, + x156: 0, x157: 0, x158: 0, x159: 0, x160: 0, + x161: 0, x162: 0, x163: 0, x164: 0, x165: 0, + x166: 0, x167: 0, x168: 0, x169: 0, x170: 0, + x171: 0, x172: 0, x173: 0, x174: 0, x175: 0, + x176: 0, x177: 0, x178: 0, x179: 0, x180: 0, + x181: 0, x182: 0, x183: 0, x184: 0, x185: 0, + x186: 0, x187: 0, x188: 0, x189: 0, x190: 0, + x191: 0, x192: 0, x193: 0, x194: 0, x195: 0, + x196: 0, x197: 0, x198: 0, x199: 0, x200: 0, + }); + assertStrongObject([[1], {}, [[3]]][1]); + assertStrongObject({[Date() + ""]: 0, [Symbol()]: 0}); + assertStrongObject({m() { super.m() }}); + assertTrue(%IsStrong({__proto__: {}, get a() {}, set b(x) {}})); + // Object literals with constant functions are treated specially, + // but currently only on the toplevel (using Realm.eval to emulate that). + assertStrongObject({f: function(){}}); + assertStrongObject( + Realm.eval(Realm.current(), "'use strong'; ({f: function(){}})")); +})(); + +(function WeakArrayLiterals(...args) { + function assertWeakArray(x) { + assertFalse(%IsStrong(x)); + assertSame(Array.prototype, Object.getPrototypeOf(x)); + } + let [...r] = []; + assertWeakArray(args); + assertWeakArray(r); + assertWeakArray([]); + assertWeakArray([1, 2, 3]); + assertWeakArray([1, 2, ...[3, 4], 5]); + assertWeakArray([[[]]]); + assertWeakArray([[1], {}, [[3]]]); + assertWeakArray([[1], {}, [[3]]][0]); + assertWeakArray([[1], {}, [[3]]][2]); + assertWeakArray([[1], {}, [[3]]][2][0]); + assertWeakArray({a: [], b: {}}.a); +})(); + +(function StrongArrayLiterals(...args) { + 'use strong'; + function assertStrongArray(x) { + assertTrue(%IsStrong(x)); + assertSame(Array.prototype, Object.getPrototypeOf(x)); + } + let [...r] = []; + assertStrongArray(args); + assertStrongArray(r); + assertStrongArray([]); + assertStrongArray([1, 2, 3]); + assertStrongArray([1, 2, ...[3, 4], 5]); + assertStrongArray([[[]]]); + assertStrongArray([[1], {}, [[3]]]); + assertStrongArray([[1], {}, [[3]]][0]); + assertStrongArray([[1], {}, [[3]]][2]); + assertStrongArray([[1], {}, [[3]]][2][0]); + assertStrongArray({a: [], b: {}}.a); +})(); + +(function WeakFunctionLiterals() { + function assertWeakFunction(x) { + assertFalse(%IsStrong(x)); + assertFalse(%IsStrong(x.prototype)); + assertSame(Function.prototype, Object.getPrototypeOf(x)); + } + function f() {} + assertWeakFunction(f); + assertWeakFunction(function(){}); + assertWeakFunction(function f(){}); + assertWeakFunction(() => {}); + assertWeakFunction(x => x); + assertWeakFunction({m(){}}.m); + assertWeakFunction(Object.getOwnPropertyDescriptor( + {get a(){}}, 'a').get); + assertWeakFunction(Object.getOwnPropertyDescriptor( + {set a(x){}}, 'a').set); + assertWeakFunction((class {static m(){}}).m); + assertWeakFunction(Object.getOwnPropertyDescriptor( + class {static get a(){}}, 'a').get); + assertWeakFunction(Object.getOwnPropertyDescriptor( + class {static set a(x){}}, 'a').set); + assertWeakFunction((new class {m(){}}).m); + assertWeakFunction(Object.getOwnPropertyDescriptor( + (class {get a(){}}).prototype, 'a').get); + assertWeakFunction(Object.getOwnPropertyDescriptor( + (class {set a(x){}}).prototype, 'a').set); +})(); + +(function StrongFunctionLiterals() { + 'use strong'; + function assertStrongFunction(x) { + assertTrue(%IsStrong(x)); + assertFalse('prototype' in x); + assertSame(Function.prototype, Object.getPrototypeOf(x)); + } + function f() {} + assertStrongFunction(f); + assertStrongFunction(function(){}); + assertStrongFunction(function f(){}); + assertStrongFunction(() => {}); + assertStrongFunction(x => x); + assertStrongFunction({m(){}}.m); + assertStrongFunction(Object.getOwnPropertyDescriptor( + {get a(){}}, 'a').get); + assertStrongFunction(Object.getOwnPropertyDescriptor( + {set a(x){}}, 'a').set); + assertStrongFunction((class {static m(){}}).m); + assertStrongFunction(Object.getOwnPropertyDescriptor( + class {static get a(){}}, 'a').get); + assertStrongFunction(Object.getOwnPropertyDescriptor( + class {static set a(x){}}, 'a').set); + assertStrongFunction((new class {m(){}}).m); + assertStrongFunction(Object.getOwnPropertyDescriptor( + (class {get a(){}}).prototype, 'a').get); + assertStrongFunction(Object.getOwnPropertyDescriptor( + (class {set a(x){}}).prototype, 'a').set); +})(); + +(function SelfStrongFunctionLiterals() { + function assertStrongFunction(x) { + assertTrue(%IsStrong(x)); + assertFalse('prototype' in x); + assertSame(Function.prototype, Object.getPrototypeOf(x)); + } + function f() {'use strong'} + assertStrongFunction(f); + assertStrongFunction(function(){'use strong'}); + assertStrongFunction(function f(){'use strong'}); + assertStrongFunction(() => {'use strong'}); + assertStrongFunction(x => {'use strong'}); + assertStrongFunction({m(){'use strong'}}.m); + assertStrongFunction(Object.getOwnPropertyDescriptor( + {get a(){'use strong'}}, 'a').get); + assertStrongFunction(Object.getOwnPropertyDescriptor( + {set a(x){'use strong'}}, 'a').set); + assertStrongFunction((class {static m(){'use strong'}}).m); + assertStrongFunction(Object.getOwnPropertyDescriptor( + class {static get a(){'use strong'}}, 'a').get); + assertStrongFunction(Object.getOwnPropertyDescriptor( + class {static set a(x){'use strong'}}, 'a').set); + assertStrongFunction((new class {m(){'use strong'}}).m); + assertStrongFunction(Object.getOwnPropertyDescriptor( + (class {get a(){'use strong'}}).prototype, 'a').get); + assertStrongFunction(Object.getOwnPropertyDescriptor( + (class {set a(x){'use strong'}}).prototype, 'a').set); +})(); + +let GeneratorPrototype = (function*(){}).__proto__; + +(function WeakGeneratorLiterals() { + function assertWeakGenerator(x) { + assertFalse(%IsStrong(x)); + assertFalse(%IsStrong(x.prototype)); + assertSame(GeneratorPrototype, Object.getPrototypeOf(x)); + assertFalse(%IsStrong(x())); + } + function* g() {} + assertWeakGenerator(g); + assertWeakGenerator(function*(){}); + assertWeakGenerator(function* g(){}); + assertWeakGenerator({*m(){}}.m); + assertWeakGenerator((class {static *m(){}}).m); + assertWeakGenerator((new class {*m(){}}).m); +})(); + +(function StrongGeneratorLiterals() { + 'use strong'; + function assertStrongGenerator(x) { + assertTrue(%IsStrong(x)); + // TODO(rossberg): strongify generator prototypes + // assertTrue(%IsStrong(x.prototype)); + assertSame(GeneratorPrototype, Object.getPrototypeOf(x)); + // TODO(rossberg): strongify generator instances + // assertTrue(%IsStrong(x())); + } + function* g() {} + assertStrongGenerator(g); + assertStrongGenerator(function*(){}); + assertStrongGenerator(function* g(){}); + assertStrongGenerator({*m(){}}.m); + assertStrongGenerator((class {static *m(){}}).m); + assertStrongGenerator((new class {*m(){}}).m); +})(); + +(function SelfStrongGeneratorLiterals() { + function assertStrongGenerator(x) { + assertTrue(%IsStrong(x)); + // TODO(rossberg): strongify generator prototypes + // assertTrue(%IsStrong(x.prototype)); + assertSame(GeneratorPrototype, Object.getPrototypeOf(x)); + // TODO(rossberg): strongify generator instances + // assertTrue(%IsStrong(x())); + } + function* g() {'use strong'} + assertStrongGenerator(g); + assertStrongGenerator(function*(){'use strong'}); + assertStrongGenerator(function* g(){'use strong'}); + assertStrongGenerator({*m(){'use strong'}}.m); + assertStrongGenerator((class {static *m(){'use strong'}}).m); + assertStrongGenerator((new class {*m(){'use strong'}}).m); +})(); + +(function WeakClassLiterals() { + function assertWeakClass(x) { + assertFalse(%IsStrong(x)); + assertFalse(%IsStrong(x.prototype)); + assertFalse(%IsStrong(new x)); + } + class C {}; + class D extends C {}; + class E extends Object {}; + // class F extends null {}; + const S = (() => {'use strong'; return class {}})(); + class G extends S {}; + assertWeakClass(C); + assertWeakClass(D); + assertWeakClass(E); + // assertWeakClass(F); + assertWeakClass(G); + assertWeakClass(class {}); + assertWeakClass(class extends Object {}); + // assertWeakClass(class extends null {}); + assertWeakClass(class extends C {}); + assertWeakClass(class extends S {}); + assertWeakClass(class extends class {} {}); + assertWeakClass(class C {}); + assertWeakClass(class D extends Object {}); + // assertWeakClass(class D extends null {}); + assertWeakClass(class D extends C {}); + assertWeakClass(class D extends S {}); + assertWeakClass(class D extends class {} {}); +})(); + +(function StrongClassLiterals() { + 'use strong'; + function assertStrongClass(x) { + assertTrue(%IsStrong(x)); + // TODO(rossberg): strongify class prototype and instance + // assertTrue(%IsStrong(x.prototype)); + // assertTrue(%IsStrong(new x)); + } + class C {}; + class D extends C {}; + class E extends Object {}; + const W = (1, eval)(() => {'use strict'; return class {}})(); + class G extends W {}; + assertStrongClass(C); + assertStrongClass(D); + assertStrongClass(E); + assertStrongClass(G); + assertStrongClass(class {}); + assertStrongClass(class extends Object {}); + assertStrongClass(class extends C {}); + assertStrongClass(class extends W {}); + assertStrongClass(class extends class {} {}); + assertStrongClass(class C {}); + assertStrongClass(class D extends Object {}); + assertStrongClass(class D extends C {}); + assertStrongClass(class D extends W {}); + assertStrongClass(class D extends class {} {}); +})(); + +(function WeakRegExpLiterals() { + function assertWeakRegExp(x) { + assertFalse(%IsStrong(x)); + } + assertWeakRegExp(/abc/); +})(); + +(function StrongRegExpLiterals() { + 'use strong'; + function assertStrongRegExp(x) { + // TODO(rossberg): strongify regexps + // assertTrue(%IsStrong(x)); + } + assertStrongRegExp(/abc/); +})(); diff --git a/deps/v8/test/mjsunit/strong/load-builtins.js b/deps/v8/test/mjsunit/strong/load-builtins.js new file mode 100644 index 0000000000..6638ff3332 --- /dev/null +++ b/deps/v8/test/mjsunit/strong/load-builtins.js @@ -0,0 +1,42 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode + +function getGlobal() { + return this; +} + +function polluteGlobal() { + bar = 0; +} + +(function() { + "use strict"; + + let builtins = [ + Array, + Object, + Function, + getGlobal() + ]; + + for (let builtin of builtins) { + assertThrows(function(){"use strong"; builtin.foo}, TypeError); + assertThrows(function(){"use strong"; builtin[0]}, TypeError); + assertThrows(function(){"use strong"; builtin[10000]}, TypeError); + builtin.foo = 1; + assertDoesNotThrow(function(){"use strong"; builtin.foo}); + assertThrows(function(){"use strong"; builtin.bar}); + assertThrows(function(){"use strong"; builtin[0]}, TypeError); + assertThrows(function(){"use strong"; builtin[10000]}, TypeError); + builtin[0] = 1; + assertDoesNotThrow(function(){"use strong"; builtin.foo}); + assertThrows(function(){"use strong"; builtin.bar}); + assertDoesNotThrow(function(){"use strong"; builtin[0]}); + assertThrows(function(){"use strong"; builtin[10000]}, TypeError); + } + polluteGlobal(); + assertDoesNotThrow(function(){"use strong"; getGlobal().bar}); +})(); diff --git a/deps/v8/test/mjsunit/strong/load-element-mutate-backing-store.js b/deps/v8/test/mjsunit/strong/load-element-mutate-backing-store.js new file mode 100644 index 0000000000..f3465028b7 --- /dev/null +++ b/deps/v8/test/mjsunit/strong/load-element-mutate-backing-store.js @@ -0,0 +1,239 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode --allow-natives-syntax + +function getSloppyArguments() { + return arguments; +} + +function getObjects() { + "use strict"; + return [ + {}, + Object(""), + [], + (function(){}), + (class Foo {}), + getSloppyArguments(), + arguments, + new Date(), + ]; +} + +// TODO(conradw): add tests for non-inheritance once semantics are implemented. +function getNonInheritingObjects() { + "use strong"; + return [ + Object(""), + [], + // TODO(conradw): uncomment and correct test once Object.defineProperty is + // fixed. + // new Uint32Array(0) + ]; +} + +function readFromObjectElementSloppy(o) { + return o[0]; +} + +function readFromObjectElementSparseSloppy(o) { + return o[100000]; +} + +function readFromObjectElementNonSmiSloppy(o) { + return o[3000000000]; +} + +function readFromObjectNonIndexSloppy(o) { + return o[5000000000]; +} + +function readFromObjectElementVarSloppy(o) { + var a = 0; + return o[a]; +} + +function readFromObjectElementSparseVarSloppy(o) { + var a = 100000; + return o[a]; +} + +function readFromObjectElementNonSmiVarSloppy(o) { + var a = 3000000000; + return o[a]; +} + +function readFromObjectNonIndexVarSloppy(o) { + var a = 5000000000; + return o[a]; +} + +function readFromObjectElementStrong(o) { + "use strong"; + return o[0]; +} + +function readFromObjectElementSparseStrong(o) { + "use strong"; + return o[100000]; +} + +function readFromObjectElementNonSmiStrong(o) { + "use strong"; + return o[3000000000]; +} + +function readFromObjectNonIndexStrong(o) { + "use strong"; + return o[5000000000]; +} + +function readFromObjectElementLetStrong(o) { + "use strong"; + let a = 0; + return o[a]; +} + +function readFromObjectElementSparseLetStrong(o) { + "use strong"; + let a = 100000; + return o[a]; +} + +function readFromObjectElementNonSmiLetStrong(o) { + "use strong"; + let a = 3000000000; + return o[a]; +} + +function readFromObjectNonIndexLetStrong(o) { + "use strong"; + let a = 5000000000; + return o[a]; +} + +function getDescs(x) { + return [ + {value: x}, + {configurable: true, enumerable: true, writable: true, value: x}, + {configurable: true, enumerable: true, get: (function() {return x}) }, + ]; +} + +function assertStrongSemantics(func, object) { + %DeoptimizeFunction(func); + %ClearFunctionTypeFeedback(func); + assertThrows(function(){func(object)}, TypeError); + assertThrows(function(){func(object)}, TypeError); + assertThrows(function(){func(object)}, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(function(){func(object)}, TypeError); + %DeoptimizeFunction(func); + assertThrows(function(){func(object)}, TypeError); +} + +function assertSloppySemantics(func, object) { + %DeoptimizeFunction(func); + %ClearFunctionTypeFeedback(func); + assertDoesNotThrow(function(){func(object)}); + assertDoesNotThrow(function(){func(object)}); + assertDoesNotThrow(function(){func(object)}); + %OptimizeFunctionOnNextCall(func); + assertDoesNotThrow(function(){func(object)}); + %DeoptimizeFunction(func); + assertDoesNotThrow(function(){func(object)}); +} + +(function () { + "use strict"; + + let goodKeys = [ + "0", + "100000", + "3000000000", + "5000000000" + ] + + let badKeys = [ + "bar", + "1", + "100001", + "3000000001", + "5000000001" + ]; + + let values = [ + "string", + 1, + 100001, + 30000000001, + 50000000001, + NaN, + {}, + undefined + ]; + + let badAccessorDescs = [ + { set: (function(){}) }, + { configurable: true, enumerable: true, set: (function(){}) } + ]; + + let readSloppy = [ + readFromObjectElementSloppy, + readFromObjectElementSparseSloppy, + readFromObjectElementNonSmiSloppy, + readFromObjectNonIndexSloppy, + readFromObjectElementVarSloppy, + readFromObjectElementSparseVarSloppy, + readFromObjectElementNonSmiVarSloppy, + readFromObjectNonIndexVarSloppy + ]; + + let readStrong = [ + readFromObjectElementStrong, + readFromObjectElementSparseStrong, + readFromObjectElementNonSmiStrong, + readFromObjectNonIndexStrong, + readFromObjectElementLetStrong, + readFromObjectElementSparseLetStrong, + readFromObjectElementNonSmiLetStrong, + readFromObjectNonIndexLetStrong + ]; + + let dummyProto = {}; + for (let key of goodKeys) { + Object.defineProperty(dummyProto, key, { value: undefined }); + } + + // After altering the backing store, accessing a missing property should still + // throw. + for (let key of badKeys) { + for (let value of values) { + for (let desc of getDescs(value)) { + let objects = getObjects(); + let nonInheritingObjects = getNonInheritingObjects(); + for (let object of objects.concat(nonInheritingObjects)) { + Object.defineProperty(object, key, desc); + for (let func of readStrong) { + assertStrongSemantics(func, object); + } + for (let func of readSloppy) { + assertSloppySemantics(func, object); + } + } + for (let object of objects) { + // Accessing a property which is on the prototype chain of the object + // should not throw. + object.__proto__ = dummyProto; + for (let key of goodKeys) { + for (let func of readStrong.concat(readSloppy)) { + assertSloppySemantics(func, object); + } + } + } + } + } + } +})(); diff --git a/deps/v8/test/mjsunit/strong/load-element.js b/deps/v8/test/mjsunit/strong/load-element.js new file mode 100644 index 0000000000..4007b7db61 --- /dev/null +++ b/deps/v8/test/mjsunit/strong/load-element.js @@ -0,0 +1,267 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode --allow-natives-syntax + +function getSloppyArguments() { + return arguments; +} + +function getObjects() { + "use strict"; + return [ + {}, + Object(""), + [], + (function(){}), + (class Foo {}), + getSloppyArguments(), + arguments, + new Date() + ]; +} + +//TODO(conradw): add tests for non-inheritance once semantics are implemented. +function getNonInheritingObjects() { + "use strong"; + return [ + Object(""), + [], + new Uint32Array(0) + ]; +} + +function readFromObjectElementSloppy(o) { + return o[0]; +} + +function readFromObjectElementSparseSloppy(o) { + return o[100000]; +} + +function readFromObjectElementNonSmiSloppy(o) { + return o[3000000000]; +} + +function readFromObjectNonIndexSloppy(o) { + return o[5000000000]; +} + +function readFromObjectElementVarSloppy(o) { + var a = 0; + return o[a]; +} + +function readFromObjectElementSparseVarSloppy(o) { + var a = 100000; + return o[a]; +} + +function readFromObjectElementNonSmiVarSloppy(o) { + var a = 3000000000; + return o[a]; +} + +function readFromObjectNonIndexVarSloppy(o) { + var a = 5000000000; + return o[a]; +} + +function readFromObjectElementStrong(o) { + "use strong"; + return o[0]; +} + +function readFromObjectElementSparseStrong(o) { + "use strong"; + return o[100000]; +} + +function readFromObjectElementNonSmiStrong(o) { + "use strong"; + return o[3000000000]; +} + +function readFromObjectNonIndexStrong(o) { + "use strong"; + return o[5000000000]; +} + +function readFromObjectElementLetStrong(o) { + "use strong"; + let a = 0; + return o[a]; +} + +function readFromObjectElementSparseLetStrong(o) { + "use strong"; + let a = 100000; + return o[a]; +} + +function readFromObjectElementNonSmiLetStrong(o) { + "use strong"; + let a = 3000000000; + return o[a]; +} + +function readFromObjectNonIndexLetStrong(o) { + "use strong"; + let a = 5000000000; + return o[a]; +} + +function getDescs(x) { + return [ + {value: x}, + {configurable: true, enumerable: true, writable: true, value: x}, + {configurable: true, enumerable: true, get: (function() {return x}) }, + ]; +} + +function assertStrongSemantics(func, object) { + %DeoptimizeFunction(func); + %ClearFunctionTypeFeedback(func); + assertThrows(function(){func(object)}, TypeError); + assertThrows(function(){func(object)}, TypeError); + assertThrows(function(){func(object)}, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(function(){func(object)}, TypeError); + %DeoptimizeFunction(func); + assertThrows(function(){func(object)}, TypeError); +} + +function assertSloppySemantics(func, object) { + %DeoptimizeFunction(func); + %ClearFunctionTypeFeedback(func); + assertDoesNotThrow(function(){func(object)}); + assertDoesNotThrow(function(){func(object)}); + assertDoesNotThrow(function(){func(object)}); + %OptimizeFunctionOnNextCall(func); + assertDoesNotThrow(function(){func(object)}); + %DeoptimizeFunction(func); + assertDoesNotThrow(function(){func(object)}); +} + +(function () { + "use strict"; + + let goodKeys = [ + "0", + "100000", + "3000000000", + "5000000000" + ] + + let badKeys = [ + "bar", + "1", + "100001", + "3000000001", + "5000000001" + ]; + + let values = [ + "string", + 1, + 100001, + 30000000001, + 50000000001, + NaN, + {}, + undefined + ]; + + let literals = [0, NaN, true, ""]; + + let badAccessorDescs = [ + { set: (function(){}) }, + { configurable: true, enumerable: true, set: (function(){}) } + ]; + + let readSloppy = [ + readFromObjectElementSloppy, + readFromObjectElementSparseSloppy, + readFromObjectElementNonSmiSloppy, + readFromObjectNonIndexSloppy, + readFromObjectElementVarSloppy, + readFromObjectElementSparseVarSloppy, + readFromObjectElementNonSmiVarSloppy, + readFromObjectNonIndexVarSloppy + ]; + + let readStrong = [ + readFromObjectElementStrong, + readFromObjectElementSparseStrong, + readFromObjectElementNonSmiStrong, + readFromObjectNonIndexStrong, + readFromObjectElementLetStrong, + readFromObjectElementSparseLetStrong, + readFromObjectElementNonSmiLetStrong, + readFromObjectNonIndexLetStrong + ]; + + let dummyProto = {}; + for (let key of goodKeys) { + Object.defineProperty(dummyProto, key, { value: undefined }); + } + + let dummyAccessorProto = {}; + for (let key of goodKeys) { + Object.defineProperty(dummyAccessorProto, key, { set: (function(){}) }) + } + + // String literals/objects should not throw on character index access + assertDoesNotThrow(function() {"use strong"; return "string"[0]; }); + assertDoesNotThrow(function() {"use strong"; return Object("string")[0]; }); + + // Attempting to access a property on an object with no defined properties + // should throw. + for (let object of getObjects().concat(getNonInheritingObjects(), literals)) { + for (let func of readStrong) { + assertStrongSemantics(func, object); + } + for (let func of readSloppy) { + assertSloppySemantics(func, object); + } + } + for (let object of getObjects()) { + // Accessing a property which is on the prototype chain of the object should + // not throw. + object.__proto__ = dummyProto; + for (let key of goodKeys) { + for (let func of readStrong.concat(readSloppy)) { + assertSloppySemantics(func, object); + } + } + } + // Properties with accessor descriptors missing 'get' should throw on access. + for (let desc of badAccessorDescs) { + for (let key of goodKeys) { + for (let object of getObjects()) { + Object.defineProperty(object, key, desc); + for (let func of readStrong) { + assertStrongSemantics(func, object); + } + for (let func of readSloppy) { + assertSloppySemantics(func, object); + } + } + } + } + // The same behaviour should be expected for bad accessor properties on the + // prototype chain. + for (let object of getObjects()) { + object.__proto__ = dummyAccessorProto; + for (let func of readStrong) { + assertStrongSemantics(func, object); + } + for (let func of readSloppy) { + assertSloppySemantics(func, object); + } + } + assertThrows(function(){"use strong"; typeof ({})[1];}, TypeError); + assertThrows( + function(){"use strong"; typeof ({})[1] === "undefined"}, TypeError); +})(); diff --git a/deps/v8/test/mjsunit/strong/load-property-mutate-backing-store.js b/deps/v8/test/mjsunit/strong/load-property-mutate-backing-store.js new file mode 100644 index 0000000000..5ed45530c4 --- /dev/null +++ b/deps/v8/test/mjsunit/strong/load-property-mutate-backing-store.js @@ -0,0 +1,174 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode --allow-natives-syntax + +function getSloppyArguments() { + return arguments; +} + +function getObjects() { + "use strict"; + return [ + {}, + Object(""), + [], + (function(){}), + (class Foo {}), + getSloppyArguments(), + arguments, + new Date(), + // TODO(conradw): uncomment once Object.defineProperty is fixed. + // new Uint32Array(0) + ]; +} + +function readFromObjectSloppy(o) { + return o.foo; +} + +function readFromObjectKeyedSloppy(o) { + return o["foo"]; +} + +function readFromObjectKeyedVarSloppy(o) { + var a = "foo"; + return o[a]; +} + +function readFromObjectKeyedComputedSloppy(o) { + var a = "o"; + return o["fo" + a]; +} + +function readFromObjectStrong(o) { + "use strong"; + return o.foo; +} + +function readFromObjectKeyedStrong(o) { + "use strong"; + return o["foo"]; +} + +function readFromObjectKeyedLetStrong(o) { + "use strong"; + let a = "foo"; + return o[a]; +} + +function readFromObjectKeyedComputedStrong(o) { + "use strong"; + let a = "o"; + return o["fo" + a]; +} + +function getDescs(x) { + return [ + {value: x}, + {configurable: true, enumerable: true, writable: true, value: x}, + {configurable: true, enumerable: true, get: (function() {return x}) }, + ]; +} + +function assertStrongSemantics(func, object) { + %DeoptimizeFunction(func); + %ClearFunctionTypeFeedback(func); + assertThrows(function(){func(object)}, TypeError); + assertThrows(function(){func(object)}, TypeError); + assertThrows(function(){func(object)}, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(function(){func(object)}, TypeError); + %DeoptimizeFunction(func); + assertThrows(function(){func(object)}, TypeError); +} + +function assertSloppySemantics(func, object) { + %DeoptimizeFunction(func); + %ClearFunctionTypeFeedback(func); + assertDoesNotThrow(function(){func(object)}); + assertDoesNotThrow(function(){func(object)}); + assertDoesNotThrow(function(){func(object)}); + %OptimizeFunctionOnNextCall(func); + assertDoesNotThrow(function(){func(object)}); + %DeoptimizeFunction(func); + assertDoesNotThrow(function(){func(object)}); +} + +(function () { + "use strict"; + + let goodKeys = [ + "foo" + ] + + let badKeys = [ + "bar", + "1", + "100001", + "3000000001", + "5000000001" + ]; + + let values = [ + "string", + 1, + 100001, + 30000000001, + 50000000001, + NaN, + {}, + undefined + ]; + + let badAccessorDescs = [ + { set: (function(){}) }, + { configurable: true, enumerable: true, set: (function(){}) } + ]; + + let readSloppy = [ + readFromObjectSloppy, + readFromObjectKeyedSloppy, + readFromObjectKeyedVarSloppy, + readFromObjectKeyedComputedSloppy + ]; + + let readStrong = [ + readFromObjectStrong, + readFromObjectKeyedStrong, + readFromObjectKeyedLetStrong, + readFromObjectKeyedComputedStrong + ]; + + let dummyProto = {}; + for (let key of goodKeys) { + Object.defineProperty(dummyProto, key, { value: undefined }); + } + + // After altering the backing store, accessing a missing property should still + // throw. + for (let key of badKeys) { + for (let value of values) { + for (let desc of getDescs(value)) { + for (let object of getObjects()) { + Object.defineProperty(object, key, desc); + for (let func of readStrong) { + assertStrongSemantics(func, object); + } + for (let func of readSloppy) { + assertSloppySemantics(func, object); + } + // Accessing a property which is on the prototype chain of the object + // should not throw. + object.__proto__ = dummyProto; + for (let key of goodKeys) { + for (let func of readStrong.concat(readSloppy)) { + assertSloppySemantics(func, object); + } + } + } + } + } + } +})(); diff --git a/deps/v8/test/mjsunit/strong/load-property.js b/deps/v8/test/mjsunit/strong/load-property.js new file mode 100644 index 0000000000..ddbcbb67fb --- /dev/null +++ b/deps/v8/test/mjsunit/strong/load-property.js @@ -0,0 +1,203 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode --allow-natives-syntax + +function getSloppyArguments() { + return arguments; +} + +function getObjects() { + "use strict"; + return [ + {}, + Object(""), + [], + (function(){}), + (class Foo {}), + getSloppyArguments(), + arguments, + new Date(), + new Uint32Array(0) + ]; +} + +function readFromObjectSloppy(o) { + return o.foo; +} + +function readFromObjectKeyedSloppy(o) { + return o["foo"]; +} + +function readFromObjectKeyedVarSloppy(o) { + var a = "foo"; + return o[a]; +} + +function readFromObjectKeyedComputedSloppy(o) { + var a = "o"; + return o["fo" + a]; +} + +function readFromObjectStrong(o) { + "use strong"; + return o.foo; +} + +function readFromObjectKeyedStrong(o) { + "use strong"; + return o["foo"]; +} + +function readFromObjectKeyedLetStrong(o) { + "use strong"; + let a = "foo"; + return o[a]; +} + +function readFromObjectKeyedComputedStrong(o) { + "use strong"; + let a = "o"; + return o["fo" + a]; +} + +function getDescs(x) { + return [ + {value: x}, + {configurable: true, enumerable: true, writable: true, value: x}, + {configurable: true, enumerable: true, get: (function() {return x}) }, + ]; +} + +function assertStrongSemantics(func, object) { + %DeoptimizeFunction(func); + %ClearFunctionTypeFeedback(func); + assertThrows(function(){func(object)}, TypeError); + assertThrows(function(){func(object)}, TypeError); + assertThrows(function(){func(object)}, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(function(){func(object)}, TypeError); + %DeoptimizeFunction(func); + assertThrows(function(){func(object)}, TypeError); +} + +function assertSloppySemantics(func, object) { + %DeoptimizeFunction(func); + %ClearFunctionTypeFeedback(func); + assertDoesNotThrow(function(){func(object)}); + assertDoesNotThrow(function(){func(object)}); + assertDoesNotThrow(function(){func(object)}); + %OptimizeFunctionOnNextCall(func); + assertDoesNotThrow(function(){func(object)}); + %DeoptimizeFunction(func); + assertDoesNotThrow(function(){func(object)}); +} + +(function () { + "use strict"; + + let goodKeys = [ + "foo" + ] + + let badKeys = [ + "bar", + "1", + "100001", + "3000000001", + "5000000001" + ]; + + let values = [ + "string", + 1, + 100001, + 30000000001, + 50000000001, + NaN, + {}, + undefined + ]; + + let literals = [0, NaN, true, "string"]; + + let badAccessorDescs = [ + { set: (function(){}) }, + { configurable: true, enumerable: true, set: (function(){}) } + ]; + + let readSloppy = [ + readFromObjectSloppy, + readFromObjectKeyedSloppy, + readFromObjectKeyedVarSloppy, + readFromObjectKeyedComputedSloppy + ]; + + let readStrong = [ + readFromObjectStrong, + readFromObjectKeyedStrong, + readFromObjectKeyedLetStrong, + readFromObjectKeyedComputedStrong + ]; + + let dummyProto = {}; + for (let key of goodKeys) { + Object.defineProperty(dummyProto, key, { value: undefined }); + } + + let dummyAccessorProto = {}; + for (let key of goodKeys) { + Object.defineProperty(dummyAccessorProto, key, { set: (function(){}) }) + } + + // Attempting to access a property on an object with no defined properties + // should throw. + for (let object of getObjects().concat(literals)) { + for (let func of readStrong) { + assertStrongSemantics(func, object); + } + for (let func of readSloppy) { + assertSloppySemantics(func, object); + } + } + for (let object of getObjects()) { + // Accessing a property which is on the prototype chain of the object should + // not throw. + object.__proto__ = dummyProto; + for (let key of goodKeys) { + for (let func of readStrong.concat(readSloppy)) { + assertSloppySemantics(func, object); + } + } + } + // Properties with accessor descriptors missing 'get' should throw on access. + for (let desc of badAccessorDescs) { + for (let key of goodKeys) { + for (let object of getObjects()) { + Object.defineProperty(object, key, desc); + for (let func of readStrong) { + assertStrongSemantics(func, object); + } + for (let func of readSloppy) { + assertSloppySemantics(func, object); + } + } + } + } + // The same behaviour should be expected for bad accessor properties on the + // prototype chain. + for (let object of getObjects()) { + object.__proto__ = dummyAccessorProto; + for (let func of readStrong) { + assertStrongSemantics(func, object); + } + for (let func of readSloppy) { + assertSloppySemantics(func, object); + } + } + assertThrows(function(){"use strong"; typeof ({}).foo;}, TypeError); + assertThrows( + function(){"use strong"; typeof ({}).foo === "undefined"}, TypeError); +})(); diff --git a/deps/v8/test/mjsunit/strong/load-proxy.js b/deps/v8/test/mjsunit/strong/load-proxy.js new file mode 100644 index 0000000000..98a3238c4e --- /dev/null +++ b/deps/v8/test/mjsunit/strong/load-proxy.js @@ -0,0 +1,98 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-proxies --strong-mode + +// Forwarding proxies adapted from proposal definition +function handlerMaker1(obj) { + return { + getPropertyDescriptor: function(name) { + var desc; + var searchObj = obj; + while (desc === undefined && searchObj != null) { + desc = Object.getOwnPropertyDescriptor(searchObj, name); + searchObj = searchObj.__proto__; + } + // a trapping proxy's properties must always be configurable + if (desc !== undefined) { desc.configurable = true; } + return desc; + }, + fix: function() { + if (Object.isFrozen(obj)) { + var result = {}; + Object.getOwnPropertyNames(obj).forEach(function(name) { + result[name] = Object.getOwnPropertyDescriptor(obj, name); + }); + return result; + } + // As long as obj is not frozen, the proxy won't allow itself to be fixed + return undefined; // will cause a TypeError to be thrown + } + }; +} +function handlerMaker2(obj) { + return { + get: function(receiver, name) { + return obj[name]; + }, + fix: function() { + if (Object.isFrozen(obj)) { + var result = {}; + Object.getOwnPropertyNames(obj).forEach(function(name) { + result[name] = Object.getOwnPropertyDescriptor(obj, name); + }); + return result; + } + // As long as obj is not frozen, the proxy won't allow itself to be fixed + return undefined; // will cause a TypeError to be thrown + } + }; +} +var baseObj = {}; +var proxy1 = Proxy.create(handlerMaker1(baseObj)); +var proxy2 = Proxy.create(handlerMaker2(baseObj)); +var childObj1 = { __proto__: proxy1 }; +var childObj2 = { __proto__: proxy2 }; +var childObjAccessor1 = { set foo(_){}, set "1"(_){}, __proto__: proxy1 }; +var childObjAccessor2 = { set foo(_){}, set "1"(_){}, __proto__: proxy2 }; + +(function() { + "use strong"; + // TODO(conradw): These asserts are sanity checking V8's proxy implementation. + // Strong mode semantics for ES6 proxies still need to be explored. + assertDoesNotThrow(function(){proxy1.foo}); + assertDoesNotThrow(function(){proxy1[1]}); + assertDoesNotThrow(function(){proxy2.foo}); + assertDoesNotThrow(function(){proxy2[1]}); + assertDoesNotThrow(function(){childObj1.foo}); + assertDoesNotThrow(function(){childObj1[1]}); + assertDoesNotThrow(function(){childObj2.foo}); + assertDoesNotThrow(function(){childObj2[1]}); + assertThrows(function(){baseObj.foo}, TypeError); + assertThrows(function(){baseObj[1]}, TypeError); + assertThrows(function(){childObjAccessor1.foo}, TypeError); + assertThrows(function(){childObjAccessor1[1]}, TypeError); + assertThrows(function(){childObjAccessor2.foo}, TypeError); + assertThrows(function(){childObjAccessor2[1]}, TypeError); + + // Once the proxy is no longer trapping, property access should have strong + // semantics. + Object.freeze(baseObj); + + Object.freeze(proxy1); + assertThrows(function(){proxy1.foo}, TypeError); + assertThrows(function(){proxy1[1]}, TypeError); + assertThrows(function(){childObj1.foo}, TypeError); + assertThrows(function(){childObj1[1]}, TypeError); + assertThrows(function(){childObjAccessor1.foo}, TypeError); + assertThrows(function(){childObjAccessor1[1]}, TypeError); + + Object.freeze(proxy2); + assertThrows(function(){proxy2.foo}, TypeError); + assertThrows(function(){proxy2[1]}, TypeError); + assertThrows(function(){childObj2.foo}, TypeError); + assertThrows(function(){childObj2[1]}, TypeError); + assertThrows(function(){childObjAccessor2.foo}, TypeError); + assertThrows(function(){childObjAccessor2[1]}, TypeError); +})(); diff --git a/deps/v8/test/mjsunit/strong/load-super.js b/deps/v8/test/mjsunit/strong/load-super.js new file mode 100644 index 0000000000..4aa91c222a --- /dev/null +++ b/deps/v8/test/mjsunit/strong/load-super.js @@ -0,0 +1,102 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode + +"use strong"; + +function testSuper(object) { + assertEquals(0, object.validLoad()); + assertThrows(function(){ return object.propertyLoad() }, TypeError); + assertThrows(function(){ return object.elementLoad() }, TypeError); + assertThrows(function(){ return object.accessorLoad() }, TypeError); +} + +class A { + constructor() {} + foo() { + return 0; + } + get bar() { + return 0; + } + set baz(_) { + return; + } +} + +class B extends A { + constructor() { + super(); + } + validLoad() { + return super.foo() + super.bar; + } + propertyLoad() { + return super.x; + } + elementLoad() { + return super[1]; + } + accessorLoad() { + return super.baz; + } +} + +class C extends A { + constructor() { + super(); + this[1] = 0; + this.x = 0; + } + get baz() { + return 0; + } + validLoad() { + return super.foo() + super.bar; + } + propertyLoad() { + return super.x; + } + elementLoad() { + return super[1]; + } + accessorLoad() { + return super.baz; + } +} + +let b = new B(); +let c = new C(); +testSuper(b); +testSuper(c); + +let d = { + "0": 0, + foo: 0, + bar: (function(){return 0}), + get baz(){return 0}, + set qux(_){return} +} + +let e = { + __proto__: d, + "1": 0, + x: 0, + get baz(){return 0}, + validLoad() { + return super[0] + super.foo + super.bar() + super.baz; + }, + propertyLoad() { + return super.x; + }, + elementLoad() { + return super[1]; + }, + accessorLoad() { + return super.qux; + } +} + +testSuper(e); diff --git a/deps/v8/test/mjsunit/strong/object-delete.js b/deps/v8/test/mjsunit/strong/object-delete.js new file mode 100644 index 0000000000..a655b65c78 --- /dev/null +++ b/deps/v8/test/mjsunit/strong/object-delete.js @@ -0,0 +1,255 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode --allow-natives-syntax + +// TODO(conradw): Track implementation of strong bit for other objects, add +// tests. + +function getSloppyObjects() { + return [(function(){}), ({})]; +} + +function getStrictObjects() { + "use strict"; + return [(function(){}), ({})]; +} + +function getWeakObjects() { + return getSloppyObjects().concat(getStrictObjects()); +} + +function getStrongObjects() { + "use strong"; +// Strong functions can't have properties added to them, and will be tested as a +// special case. + return [({})]; +} + +function strongFunction() { + "use strong"; +} + +function deleteFromObjectSloppy(o) { + return delete o.foo; +} + +function deleteFromObjectKeyedSloppy(o) { + return delete o["foo"]; +} + +function deleteFromObjectKeyedVarSloppy(o) { + var a = "foo"; + return delete o[a]; +} + +function deleteFromObjectKeyedComputedSloppy(o) { + var a = "o"; + return delete o["fo" + a]; +} + +function deleteFromObjectWith(o) { + with (o) { + return delete foo; + } +} + +function deleteFromObjectElementSloppy(o) { + return delete o[0]; +} + +function deleteFromObjectElementVarSloppy(o) { + var a = 0; + return delete o[a]; +} + +function deleteFromObjectElementSparseSloppy(o) { + return delete o[100000]; +} + +function deleteFromObjectElementVarSloppy(o) { + var a = 0; + return delete o[a]; +} + +function deleteFromObjectElementSparseVarSloppy(o) { + var a = 100000; + return delete o[a]; +} + +function deleteFromObjectStrict(o) { + "use strict"; + return delete o.foo; +} + +function deleteFromObjectKeyedStrict(o) { + "use strict"; + return delete o["foo"]; +} + +function deleteFromObjectKeyedVarStrict(o) { + "use strict"; + var a = "foo"; + return delete o[a]; +} + +function deleteFromObjectKeyedComputedStrict(o) { + "use strict"; + var a = "o"; + return delete o["fo" + a]; +} + +function deleteFromObjectElementStrict(o) { + "use strict"; + return delete o[0]; +} + +function deleteFromObjectElementSparseStrict(o) { + "use strict"; + return delete o[100000]; +} + +function deleteFromObjectElementVarStrict(o) { + "use strict"; + var a = 0; + return delete o[a]; +} + +function deleteFromObjectElementSparseVarStrict(o) { + "use strict"; + var a = 100000; + return delete o[a]; +} + +function testStrongObjectDelete() { + "use strict"; + + let deletePropertyFuncsSloppy = [ + deleteFromObjectSloppy, + deleteFromObjectKeyedSloppy, + deleteFromObjectKeyedVarSloppy, + deleteFromObjectKeyedComputedSloppy, + deleteFromObjectWith + ]; + let deletePropertyFuncsStrict = [ + deleteFromObjectStrict, + deleteFromObjectKeyedStrict, + deleteFromObjectKeyedVarStrict, + deleteFromObjectKeyedComputedStrict + ]; + let deleteElementFuncsSloppy = [ + deleteFromObjectElementSloppy, + deleteFromObjectElementVarSloppy + ]; + let deleteElementSparseFuncsSloppy = [ + deleteFromObjectElementSparseSloppy, + deleteFromObjectElementSparseVarSloppy + ]; + let deleteElementFuncsStrict = [ + deleteFromObjectElementStrict, + deleteFromObjectElementVarStrict + ]; + let deleteElementSparseFuncsStrict = [ + deleteFromObjectElementSparseStrict, + deleteFromObjectElementSparseVarStrict + ]; + let deleteFuncs = deletePropertyFuncsSloppy.concat( + deletePropertyFuncsStrict, deleteElementFuncsSloppy, + deleteElementSparseFuncsSloppy, deleteElementFuncsStrict, + deleteElementSparseFuncsStrict); + + for (let deleteFunc of deleteFuncs) { + assertTrue(deleteFunc(strongFunction)); + } + + let testCasesSloppy = [ + [deletePropertyFuncsSloppy, "foo"], + [deleteElementFuncsSloppy, "0"], + [deleteElementSparseFuncsSloppy, "100000"] + ]; + + let testCasesStrict = [ + [deletePropertyFuncsStrict, "foo"], + [deleteElementFuncsStrict, "0"], + [deleteElementSparseFuncsStrict, "100000"] + ]; + + let propDescs = [ + {configurable: true, value: "bar"}, + {configurable: true, value: 1}, + {configurable: true, enumerable: true, writable: true, value: "bar"}, + {configurable: true, enumerable: true, writable: true, value: 1}, + {configurable: true, get: (function(){return 0}), set: (function(x){})} + ]; + + for (let propDesc of propDescs) { + for (let testCase of testCasesSloppy) { + let name = testCase[1]; + for (let deleteFunc of testCase[0]) { + for (let o of getWeakObjects()) { + Object.defineProperty(o, name, propDesc); + assertTrue(delete o["bar"]); + assertTrue(delete o[5000]); + assertTrue(deleteFunc(o)); + assertFalse(o.hasOwnProperty(name)); + %OptimizeFunctionOnNextCall(deleteFunc); + Object.defineProperty(o, name, propDesc); + assertTrue(deleteFunc(o)); + assertFalse(o.hasOwnProperty(name)); + %DeoptimizeFunction(deleteFunc); + Object.defineProperty(o, name, propDesc); + assertTrue(deleteFunc(o)); + assertFalse(o.hasOwnProperty(name)); + } + for (let o of getStrongObjects()) { + Object.defineProperty(o, name, propDesc); + assertTrue(delete o["bar"]); + assertTrue(delete o[5000]); + assertFalse(deleteFunc(o)); + assertTrue(o.hasOwnProperty(name)); + %OptimizeFunctionOnNextCall(deleteFunc); + assertFalse(deleteFunc(o)); + assertTrue(o.hasOwnProperty(name)); + %DeoptimizeFunction(deleteFunc); + assertFalse(deleteFunc(o)); + assertTrue(o.hasOwnProperty(name)); + } + } + } + for (let testCase of testCasesStrict) { + let name = testCase[1]; + for (let deleteFunc of testCase[0]) { + for (let o of getWeakObjects()) { + Object.defineProperty(o, name, propDesc); + assertTrue(delete o["bar"]); + assertTrue(delete o[5000]); + assertTrue(deleteFunc(o)); + assertFalse(o.hasOwnProperty(name)); + %OptimizeFunctionOnNextCall(deleteFunc); + Object.defineProperty(o, name, propDesc); + assertTrue(deleteFunc(o)); + assertFalse(o.hasOwnProperty(name)); + %DeoptimizeFunction(deleteFunc); + Object.defineProperty(o, name, propDesc); + assertTrue(deleteFunc(o)); + assertFalse(o.hasOwnProperty(name)); + } + for (let o of getStrongObjects()) { + Object.defineProperty(o, name, propDesc); + assertTrue(delete o["bar"]); + assertTrue(delete o[5000]); + assertThrows(function(){deleteFunc(o)}, TypeError); + assertTrue(o.hasOwnProperty(name)); + %OptimizeFunctionOnNextCall(deleteFunc); + assertThrows(function(){deleteFunc(o)}, TypeError); + assertTrue(o.hasOwnProperty(name)); + %DeoptimizeFunction(deleteFunc); + assertThrows(function(){deleteFunc(o)}, TypeError); + assertTrue(o.hasOwnProperty(name)); + } + } + } + } +} +testStrongObjectDelete(); diff --git a/deps/v8/test/mjsunit/strong/object-freeze-property.js b/deps/v8/test/mjsunit/strong/object-freeze-property.js new file mode 100644 index 0000000000..e76af1bfc6 --- /dev/null +++ b/deps/v8/test/mjsunit/strong/object-freeze-property.js @@ -0,0 +1,75 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode --allow-natives-syntax + +// TODO(conradw): Track implementation of strong bit for other objects, add +// tests. + +function getSloppyObjects() { + return [(function(){}), ({})]; +} + +function getStrictObjects() { + "use strict"; + return [(function(){}), ({})]; +} + +function getStrongObjects() { + "use strong"; + // Strong functions can't have properties added to them. + return [{}]; +} + +(function testStrongObjectFreezePropValid() { + "use strict"; + let strongObjects = getStrongObjects(); + + for (let o of strongObjects) { + Object.defineProperty(o, "foo", { configurable: true, writable: true }); + assertDoesNotThrow( + function() { + "use strong"; + Object.defineProperty(o, "foo", {configurable: true, writable: false }); + }); + } +})(); + +(function testStrongObjectFreezePropInvalid() { + "use strict"; + let sloppyObjects = getSloppyObjects(); + let strictObjects = getStrictObjects(); + let strongObjects = getStrongObjects(); + let weakObjects = sloppyObjects.concat(strictObjects); + + for (let o of weakObjects) { + Object.defineProperty(o, "foo", { writable: true }); + assertDoesNotThrow( + function() { + "use strong"; + Object.defineProperty(o, "foo", { writable: false }); + }); + } + for (let o of strongObjects) { + function defProp(o) { + Object.defineProperty(o, "foo", { writable: false }); + } + function defProps(o) { + Object.defineProperties(o, { "foo": { writable: false } }); + } + function freezeProp(o) { + Object.freeze(o); + } + Object.defineProperty(o, "foo", { writable: true }); + for (let func of [defProp, defProps, freezeProp]) { + assertThrows(function(){func(o)}, TypeError); + assertThrows(function(){func(o)}, TypeError); + assertThrows(function(){func(o)}, TypeError); + %OptimizeFunctionOnNextCall(func); + assertThrows(function(){func(o)}, TypeError); + %DeoptimizeFunction(func); + assertThrows(function(){func(o)}, TypeError); + } + } +})(); diff --git a/deps/v8/test/mjsunit/strong/object-set-prototype.js b/deps/v8/test/mjsunit/strong/object-set-prototype.js new file mode 100644 index 0000000000..53706df1ee --- /dev/null +++ b/deps/v8/test/mjsunit/strong/object-set-prototype.js @@ -0,0 +1,83 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode --allow-natives-syntax + +// TODO(conradw): Track implementation of strong bit for other objects, add +// tests. + +function getSloppyObjects() { + return [(function(){}), ({})]; +} + +function getStrictObjects() { + "use strict"; + return [(function(){}), ({})]; +} + +function getStrongObjects() { + "use strong"; + return [(function(){}), ({})]; +} + +function declareObjectLiteralWithProtoSloppy() { + return {__proto__: {}}; +} + +function declareObjectLiteralWithProtoStrong() { + "use strong"; + return {__proto__: {}}; +} + +function testStrongObjectSetProto() { + "use strict"; + let sloppyObjects = getSloppyObjects(); + let strictObjects = getStrictObjects(); + let strongObjects = getStrongObjects(); + let weakObjects = sloppyObjects.concat(strictObjects); + + for (let o of weakObjects) { + let setProtoBuiltin = function(o){Object.setPrototypeOf(o, {})}; + let setProtoProperty = function(o){o.__proto__ = {}}; + for (let setProtoFunc of [setProtoBuiltin, setProtoProperty]) { + assertDoesNotThrow(function(){setProtoFunc(o)}); + assertDoesNotThrow(function(){setProtoFunc(o)}); + assertDoesNotThrow(function(){setProtoFunc(o)}); + %OptimizeFunctionOnNextCall(setProtoFunc); + assertDoesNotThrow(function(){setProtoFunc(o)}); + %DeoptimizeFunction(setProtoFunc); + assertDoesNotThrow(function(){setProtoFunc(o)}); + } + } + for (let o of strongObjects) { + let setProtoBuiltin = function(o){Object.setPrototypeOf(o, {})}; + let setProtoProperty = function(o){o.__proto__ = {}}; + for (let setProtoFunc of [setProtoBuiltin, setProtoProperty]) { + assertThrows(function(){setProtoFunc(o)}, TypeError); + assertThrows(function(){setProtoFunc(o)}, TypeError); + assertThrows(function(){setProtoFunc(o)}, TypeError); + %OptimizeFunctionOnNextCall(setProtoFunc); + assertThrows(function(){setProtoFunc(o)}, TypeError); + %DeoptimizeFunction(setProtoFunc); + assertThrows(function(){setProtoFunc(o)}, TypeError); + } + } + + assertDoesNotThrow(declareObjectLiteralWithProtoSloppy); + assertDoesNotThrow(declareObjectLiteralWithProtoSloppy); + assertDoesNotThrow(declareObjectLiteralWithProtoSloppy); + %OptimizeFunctionOnNextCall(declareObjectLiteralWithProtoSloppy); + assertDoesNotThrow(declareObjectLiteralWithProtoSloppy); + %DeoptimizeFunction(declareObjectLiteralWithProtoSloppy); + assertDoesNotThrow(declareObjectLiteralWithProtoSloppy); + + assertDoesNotThrow(declareObjectLiteralWithProtoStrong); + assertDoesNotThrow(declareObjectLiteralWithProtoStrong); + assertDoesNotThrow(declareObjectLiteralWithProtoStrong); + %OptimizeFunctionOnNextCall(declareObjectLiteralWithProtoStrong); + assertDoesNotThrow(declareObjectLiteralWithProtoStrong); + %DeoptimizeFunction(declareObjectLiteralWithProtoStrong); + assertDoesNotThrow(declareObjectLiteralWithProtoStrong); +} +testStrongObjectSetProto(); diff --git a/deps/v8/test/mjsunit/strong/super.js b/deps/v8/test/mjsunit/strong/super.js new file mode 100644 index 0000000000..bd289f204f --- /dev/null +++ b/deps/v8/test/mjsunit/strong/super.js @@ -0,0 +1,62 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --strong-mode --allow-natives-syntax + +'use strong'; + + +function desc(obj, n) { + return Object.getOwnPropertyDescriptor(obj, n); +} + + +(function TestClass() { + class C { + m() { + super.x; + } + get x() { + super.x; + } + set y(_) { + super.x; + } + static m() { + super.x; + } + static get x() { + super.x; + } + static set y(_) { + super.x; + } + } + + assertEquals(C.prototype, C.prototype.m[%HomeObjectSymbol()]); + assertEquals(C.prototype, desc(C.prototype, 'x').get[%HomeObjectSymbol()]); + assertEquals(C.prototype, desc(C.prototype, 'y').set[%HomeObjectSymbol()]); + assertEquals(C, C.m[%HomeObjectSymbol()]); + assertEquals(C, desc(C, 'x').get[%HomeObjectSymbol()]); + assertEquals(C, desc(C, 'y').set[%HomeObjectSymbol()]); +})(); + + +(function TestObjectLiteral() { + let o = { + m() { + super.x; + }, + get x() { + super.x; + }, + set y(_) { + super.x; + } + }; + + assertEquals(o, o.m[%HomeObjectSymbol()]); + assertEquals(o, desc(o, 'x').get[%HomeObjectSymbol()]); + assertEquals(o, desc(o, 'y').set[%HomeObjectSymbol()]); +})(); diff --git a/deps/v8/test/mjsunit/testcfg.py b/deps/v8/test/mjsunit/testcfg.py index 8389696f49..cf4b6276e4 100644 --- a/deps/v8/test/mjsunit/testcfg.py +++ b/deps/v8/test/mjsunit/testcfg.py @@ -35,6 +35,7 @@ FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)") FILES_PATTERN = re.compile(r"//\s+Files:(.*)") SELF_SCRIPT_PATTERN = re.compile(r"//\s+Env: TEST_FILE_NAME") MODULE_PATTERN = re.compile(r"^// MODULE$", flags=re.MULTILINE) +NO_HARNESS_PATTERN = re.compile(r"^// NO HARNESS$", flags=re.MULTILINE) class MjsunitTestSuite(testsuite.TestSuite): @@ -79,7 +80,7 @@ class MjsunitTestSuite(testsuite.TestSuite): env = ["-e", "TEST_FILE_NAME=\"%s\"" % testfilename.replace("\\", "\\\\")] files = env + files - if not context.no_harness: + if not context.no_harness and not NO_HARNESS_PATTERN.search(source): files.append(os.path.join(self.root, "mjsunit.js")) if MODULE_PATTERN.search(source): diff --git a/deps/v8/test/mjsunit/third_party/object-keys/LICENSE b/deps/v8/test/mjsunit/third_party/object-keys/LICENSE new file mode 100644 index 0000000000..67002b4400 --- /dev/null +++ b/deps/v8/test/mjsunit/third_party/object-keys/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following +disclaimer in the documentation and/or other materials provided +with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any +contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/deps/v8/test/mjsunit/third_party/object-keys.js b/deps/v8/test/mjsunit/third_party/object-keys/object-keys.js index c8003745c4..c8003745c4 100644 --- a/deps/v8/test/mjsunit/third_party/object-keys.js +++ b/deps/v8/test/mjsunit/third_party/object-keys/object-keys.js diff --git a/deps/v8/test/mjsunit/third_party/regexp-pcre/LICENSE b/deps/v8/test/mjsunit/third_party/regexp-pcre/LICENSE new file mode 100644 index 0000000000..4baa7d83a1 --- /dev/null +++ b/deps/v8/test/mjsunit/third_party/regexp-pcre/LICENSE @@ -0,0 +1,68 @@ +PCRE LICENCE +------------ + +PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + +Release 7 of PCRE is distributed under the terms of the "BSD" licence, as +specified below. The documentation for PCRE, supplied in the "doc" +directory, is distributed under the same terms as the software itself. + +The basic library functions are written in C and are freestanding. Also +included in the distribution is a set of C++ wrapper functions. + + +THE BASIC LIBRARY FUNCTIONS +--------------------------- + +Written by: Philip Hazel +Email local part: ph10 +Email domain: cam.ac.uk + +University of Cambridge Computing Service, +Cambridge, England. + +Copyright (c) 1997-2007 University of Cambridge +All rights reserved. + + +THE C++ WRAPPER FUNCTIONS +------------------------- + +Contributed by: Google Inc. + +Copyright (c) 2007, Google Inc. +All rights reserved. + + +THE "BSD" LICENCE +----------------- + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the name of Google + Inc. nor the names of their contributors may be used to endorse or + promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +End diff --git a/deps/v8/test/mjsunit/third_party/regexp-pcre.js b/deps/v8/test/mjsunit/third_party/regexp-pcre/regexp-pcre.js index c049fb4d09..c049fb4d09 100644 --- a/deps/v8/test/mjsunit/third_party/regexp-pcre.js +++ b/deps/v8/test/mjsunit/third_party/regexp-pcre/regexp-pcre.js diff --git a/deps/v8/test/mjsunit/this-dynamic-lookup.js b/deps/v8/test/mjsunit/this-dynamic-lookup.js new file mode 100644 index 0000000000..c5fa7a2c79 --- /dev/null +++ b/deps/v8/test/mjsunit/this-dynamic-lookup.js @@ -0,0 +1,10 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-arrow-functions +// NO HARNESS + +var globalEval = eval; +globalEval("this; eval('42')"); +globalEval("eval('42'); this"); diff --git a/deps/v8/test/mjsunit/unbox-double-field-indexed.js b/deps/v8/test/mjsunit/unbox-double-field-indexed.js new file mode 100644 index 0000000000..29dfc79205 --- /dev/null +++ b/deps/v8/test/mjsunit/unbox-double-field-indexed.js @@ -0,0 +1,23 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +function Foo(x) { + this.x = x; +} + +var f = new Foo(1.25); +var g = new Foo(2.25); + +function add(a, b) { + var name = "x"; + return a[name] + b[name]; +} + +assertEquals(3.5, add(f, g)); +assertEquals(3.5, add(g, f)); +%OptimizeFunctionOnNextCall(add); +assertEquals(3.5, add(f, g)); +assertEquals(3.5, add(g, f)); diff --git a/deps/v8/test/mjsunit/unbox-double-field.js b/deps/v8/test/mjsunit/unbox-double-field.js new file mode 100644 index 0000000000..9fb5479be7 --- /dev/null +++ b/deps/v8/test/mjsunit/unbox-double-field.js @@ -0,0 +1,22 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +function Foo(x) { + this.x = x; +} + +var f = new Foo(1.25); +var g = new Foo(2.25); + +function add(a, b) { + return a.x + b.x; +} + +assertEquals(3.5, add(f, g)); +assertEquals(3.5, add(g, f)); +%OptimizeFunctionOnNextCall(add); +assertEquals(3.5, add(f, g)); +assertEquals(3.5, add(g, f)); diff --git a/deps/v8/test/mjsunit/unbox-smi-field-indexed.js b/deps/v8/test/mjsunit/unbox-smi-field-indexed.js new file mode 100644 index 0000000000..9e77da03ed --- /dev/null +++ b/deps/v8/test/mjsunit/unbox-smi-field-indexed.js @@ -0,0 +1,23 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +function Foo(x) { + this.x = x; +} + +var f = new Foo(1); +var g = new Foo(2); + +function add(a, b) { + var name = "x"; + return a[name] + b[name]; +} + +assertEquals(3, add(f, g)); +assertEquals(3, add(g, f)); +%OptimizeFunctionOnNextCall(add); +assertEquals(3, add(f, g)); +assertEquals(3, add(g, f)); diff --git a/deps/v8/test/mjsunit/unbox-smi-field.js b/deps/v8/test/mjsunit/unbox-smi-field.js new file mode 100644 index 0000000000..361911800b --- /dev/null +++ b/deps/v8/test/mjsunit/unbox-smi-field.js @@ -0,0 +1,22 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +function Foo(x) { + this.x = x; +} + +var f = new Foo(1); +var g = new Foo(2); + +function add(a, b) { + return a.x + b.x; +} + +assertEquals(3, add(f, g)); +assertEquals(3, add(g, f)); +%OptimizeFunctionOnNextCall(add); +assertEquals(3, add(f, g)); +assertEquals(3, add(g, f)); diff --git a/deps/v8/test/mjsunit/undetectable-compare.js b/deps/v8/test/mjsunit/undetectable-compare.js new file mode 100644 index 0000000000..fbfbbe1051 --- /dev/null +++ b/deps/v8/test/mjsunit/undetectable-compare.js @@ -0,0 +1,96 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +var undetectable = %GetUndetectable(); + +var tests = [ + true, false, + false, false, + null, true, + void 0, true, + 0, false, + 0.0, false, + -0, false, + "", false, + -1, false, + -1.25, false, + 1, false, + 1.25, false, + -2147483648, false, + 2147483648, false, + Infinity, false, + -Infinity, false, + NaN, false +]; + +var func = (function eq(a) { return a == undetectable; }); +var left_funcs = [ + (function eq_L0() { return true == undetectable; }), + (function eq_L1() { return false == undetectable; }), + (function eq_L2() { return null == undetectable; }), + (function eq_L3() { return void 0 == undetectable; }), + (function eq_L4() { return 0 == undetectable; }), + (function eq_L5() { return 0.0 == undetectable; }), + (function eq_L6() { return -0 == undetectable; }), + (function eq_L7() { return "" == undetectable; }), + (function eq_L8() { return -1 == undetectable; }), + (function eq_L9() { return -1.25 == undetectable; }), + (function eq_L10() { return 1 == undetectable; }), + (function eq_L11() { return 1.25 == undetectable; }), + (function eq_L12() { return -2147483648 == undetectable; }), + (function eq_L13() { return 2147483648 == undetectable; }), + (function eq_L14() { return Infinity == undetectable; }), + (function eq_L15() { return -Infinity == undetectable; }), + (function eq_L16() { return NaN == undetectable; }) +]; + +var right_funcs = [ + (function eq_R0() { return undetectable == true; }), + (function eq_R1() { return undetectable == false; }), + (function eq_R2() { return undetectable == null; }), + (function eq_R3() { return undetectable == void 0; }), + (function eq_R4() { return undetectable == 0; }), + (function eq_R5() { return undetectable == 0.0; }), + (function eq_R6() { return undetectable == -0; }), + (function eq_R7() { return undetectable == ""; }), + (function eq_R8() { return undetectable == -1; }), + (function eq_R9() { return undetectable == -1.25; }), + (function eq_R10() { return undetectable == 1; }), + (function eq_R11() { return undetectable == 1.25; }), + (function eq_R12() { return undetectable == -2147483648; }), + (function eq_R13() { return undetectable == 2147483648; }), + (function eq_R14() { return undetectable == Infinity; }), + (function eq_R15() { return undetectable == -Infinity; }), + (function eq_R16() { return undetectable == NaN; }) +]; + +function test() { + for (var i = 0; i < tests.length; i += 2) { + var val = tests[i]; + var eq = tests[i + 1]; + + assertEquals(eq, val == undetectable); + assertEquals(eq, undetectable == val); + + assertFalse(val === undetectable); + assertFalse(undetectable === val); + + assertEquals(eq, left_funcs[i/2]()); + assertEquals(eq, right_funcs[i/2]()); + } + + assertTrue(undetectable == undetectable); + assertTrue(undetectable === undetectable); + +} + +for (var i = 0; i < 5; i++) { + test(); +} + + +assertFalse(undetectable == %GetUndetectable()); +assertFalse(undetectable === %GetUndetectable()); diff --git a/deps/v8/test/mjsunit/undetectable.js b/deps/v8/test/mjsunit/undetectable.js new file mode 100644 index 0000000000..f4871f995c --- /dev/null +++ b/deps/v8/test/mjsunit/undetectable.js @@ -0,0 +1,87 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +var obj = %GetUndetectable(); + +function shouldNotBeTaken() { + fail("Undetectable branch should not be taken", "branch was taken"); +} + +function shouldBeTaken() { + fail("Inverted Undetectable branch should be taken", "branch was not taken"); +} + +function testCompares() { + assertTrue(!obj); + assertFalse(!!obj); + assertFalse(obj == true); + assertFalse(obj == false); + assertFalse(obj === true); + assertFalse(obj === false); + assertEquals(2, obj ? 1 : 2); + assertEquals(obj, true && obj); + assertEquals(obj, false || obj); +} + +function testIfs() { + if (obj) { + shouldNotBeTaken(); + } + + if (obj) { + shouldNotBeTaken(); + } else { + // do nothing + } + + if (!obj) { + // do nothing + } else { + shouldBeTaken(); + } +} + +function testWhiles() { + while (obj) { + shouldNotBeTaken(); + } + + var i = 0; + while (!obj) { + i++; + break; + } + + assertEquals(1, i); +} + +function testFors() { + for (var i = 0; obj; i++) { + shouldNotBeTaken(); + } + + var j = 0; + for (var i = 0; !obj; i++) { + j++; + break; + } + + assertEquals(1, j); +} + +for (var j = 0; j < 5; j++) { + testCompares(); + testIfs(); + testWhiles(); + testFors(); + + if (j == 3) { + %OptimizeFunctionOnNextCall(testCompares); + %OptimizeFunctionOnNextCall(testIfs); + %OptimizeFunctionOnNextCall(testWhiles); + %OptimizeFunctionOnNextCall(testFors); + } +} diff --git a/deps/v8/test/mjsunit/uri.js b/deps/v8/test/mjsunit/uri.js index fae349f439..862e420f89 100644 --- a/deps/v8/test/mjsunit/uri.js +++ b/deps/v8/test/mjsunit/uri.js @@ -88,3 +88,13 @@ test("\u1234\u0123\uabcd"); test("abcd"); test("ab<\u1234\u0123"); test("ab\u1234<\u0123"); + + +(function TestDeleteCharCodeAt() { + assertEquals('abc', encodeURI('abc')); + assertEquals('abc', decodeURI('abc')); + assertTrue(delete String.prototype.charCodeAt); + assertTrue(delete String.prototype.charAt); + assertEquals('abc', encodeURI('abc')); + assertEquals('abc', decodeURI('abc')); +})(); diff --git a/deps/v8/test/mozilla/mozilla.status b/deps/v8/test/mozilla/mozilla.status index 109efb78e2..94278e39b3 100644 --- a/deps/v8/test/mozilla/mozilla.status +++ b/deps/v8/test/mozilla/mozilla.status @@ -63,6 +63,7 @@ 'ecma_3/Statements/regress-74474-002': [PASS, NO_VARIANTS], 'ecma_3/Statements/regress-74474-003': [PASS, NO_VARIANTS], 'js1_5/Regress/regress-111557': [PASS, NO_VARIANTS], + 'js1_5/Regress/regress-155081': [PASS, NO_VARIANTS], 'js1_5/Regress/regress-155081-2': [PASS, NO_VARIANTS], 'js1_5/Regress/regress-451322': [PASS, NO_VARIANTS], diff --git a/deps/v8/test/simdjs/SimdJs.json b/deps/v8/test/simdjs/SimdJs.json new file mode 100644 index 0000000000..b671ac4cb8 --- /dev/null +++ b/deps/v8/test/simdjs/SimdJs.json @@ -0,0 +1,315 @@ +{ + "flags": [ + "--harmony-object", + "test/simdjs/harness-adapt.js" + ], + "name": "SIMDJS", + "path": [ + "../../" + ], + "resources": [ + "test/simdjs/data/src/benchmarks/base.js", + "test/simdjs/data/src/ecmascript_simd.js", + "test/simdjs/harness-adapt.js", + "test/simdjs/harness-finish.js", + "test/simdjs/data/src/benchmarks/kernel-template.js", + "test/simdjs/data/src/benchmarks/averageFloat32x4.js", + "test/simdjs/data/src/benchmarks/averageFloat32x4LoadFromInt8Array.js", + "test/simdjs/data/src/benchmarks/averageFloat32x4LoadX.js", + "test/simdjs/data/src/benchmarks/averageFloat32x4LoadXY.js", + "test/simdjs/data/src/benchmarks/averageFloat32x4LoadXYZ.js", + "test/simdjs/data/src/benchmarks/averageFloat64x2.js", + "test/simdjs/data/src/benchmarks/averageFloat64x2Load.js", + "test/simdjs/data/src/benchmarks/mandelbrot.js", + "test/simdjs/data/src/benchmarks/matrix-multiplication.js", + "test/simdjs/data/src/benchmarks/transform.js", + "test/simdjs/data/src/benchmarks/shiftrows.js", + "test/simdjs/data/src/benchmarks/transpose4x4.js", + "test/simdjs/data/src/benchmarks/inverse4x4.js", + "test/simdjs/data/src/benchmarks/sinx4.js", + "test/simdjs/data/src/benchmarks/memset.js", + "test/simdjs/data/src/benchmarks/memcpy.js" + ], + "run_count": 5, + "run_count_android_arm": 1, + "run_count_android_arm64": 3, + "run_count_arm": 3, + "tests": [ + { + "flags": [ + "test/simdjs/data/src/benchmarks/kernel-template.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "kernel-template", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/averageFloat32x4.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "averageFloat32x4", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/averageFloat32x4LoadFromInt8Array.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "averageFloat32x4LoadFromInt8Array", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/averageFloat32x4LoadX.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "averageFloat32x4LoadX", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/averageFloat32x4LoadXY.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "averageFloat32x4LoadXY", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/averageFloat32x4LoadXYZ.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "averageFloat32x4LoadXYZ", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/averageFloat64x2.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "averageFloat64x2", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/averageFloat64x2Load.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "averageFloat64x2Load", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/mandelbrot.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "mandelbrot", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/matrix-multiplication.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "matrix-multiplication", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/transform.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "transform", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/shiftrows.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "shiftrows", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/transpose4x4.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "transpose4x4", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/inverse4x4.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "inverse4x4", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/sinx4.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "sinx4", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/memset.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "memset", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + }, + { + "flags": [ + "test/simdjs/data/src/benchmarks/memcpy.js" + ], + "main": "test/simdjs/harness-finish.js", + "name": "memcpy", + "results_regexp": "%s\\([ ]*([0-9.]+)(ms)?\\)", + "tests": [ + { + "name": "SIMD" + }, + { + "name": "Non-SIMD" + } + ] + } + ], + "timeout_android_arm": 180, + "timeout_android_arm64": 120, + "timeout_arm": 120, + "units": "ms" +}
\ No newline at end of file diff --git a/deps/v8/test/simdjs/generate.py b/deps/v8/test/simdjs/generate.py new file mode 100755 index 0000000000..b100a94ae6 --- /dev/null +++ b/deps/v8/test/simdjs/generate.py @@ -0,0 +1,61 @@ +#!/usr/bin/python +# Copyright 2015 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Script to re-generate SimdJs.json from a SimdJs.json.template. + +import json +import os +import re + +SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) + +SKIP_FILES = [ + '../ecmascript_simd', + 'base', + # TODO(bradnelson): Drop these when tests are fixed upstream. + 'aobench', + 'averageFloat32x4Load', + 'matrix-multiplication-load', +] + +run_js = open( + os.path.join(SCRIPT_DIR, 'data', 'src', 'benchmarks', 'run.js')).read() +tests = re.findall("load \\(\\'([^']+)[.]js\\'\\)", run_js) +tests = [t for t in tests if t not in SKIP_FILES] + +output = { + 'name': 'SIMDJS', + 'run_count': 5, + 'run_count_arm': 3, + 'run_count_android_arm': 1, + 'run_count_android_arm64': 3, + 'timeout_arm': 120, + 'timeout_android_arm': 180, + 'timeout_android_arm64': 120, + 'units': 'ms', + 'resources': [ + 'test/simdjs/data/src/benchmarks/base.js', + 'test/simdjs/data/src/ecmascript_simd.js', + 'test/simdjs/harness-adapt.js', + 'test/simdjs/harness-finish.js' + ] + ['test/simdjs/data/src/benchmarks/%s.js' % t for t in tests], + 'flags': ['--harmony-object', 'test/simdjs/harness-adapt.js'], + 'path': ['../../'], + 'tests': [ + { + 'name': test, + 'main': 'test/simdjs/harness-finish.js', + 'flags': ['test/simdjs/data/src/benchmarks/%s.js' % test], + 'results_regexp': '%s\\([ ]*([0-9.]+)(ms)?\\)', + 'tests': [ + {'name': 'SIMD'}, + {'name': 'Non-SIMD'}, + ] + } + for test in tests], +} + +with open(os.path.join(SCRIPT_DIR, 'SimdJs.json'), 'w') as fh: + fh.write(json.dumps(output, separators=(',',': '), indent=2, sort_keys=True)) diff --git a/deps/v8/test/simdjs/harness-adapt.js b/deps/v8/test/simdjs/harness-adapt.js new file mode 100644 index 0000000000..a2ca2372c4 --- /dev/null +++ b/deps/v8/test/simdjs/harness-adapt.js @@ -0,0 +1,29 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(function() { + +"use strict"; + +var _oldLoad = load; + +// Filter load paths in the ecmascript_simd tests that +// assume the test is run with a current working directory +// set to the directory containing the test. +load = function(filename) { + // Decide if this is the compliance test or the benchmarks. + if (filename === 'ecmascript_simd.js' || + filename === 'ecmascript_simd_tests.js') { + _oldLoad('test/simdjs/data/src/' + filename); + } else { + _oldLoad('test/simdjs/data/src/benchmarks/' + filename); + } +}; + +// TODO(bbudge): Drop when polyfill is not needed. +load('ecmascript_simd.js'); + +load('base.js'); + +})(); diff --git a/deps/v8/test/simdjs/harness-finish.js b/deps/v8/test/simdjs/harness-finish.js new file mode 100644 index 0000000000..9df611085c --- /dev/null +++ b/deps/v8/test/simdjs/harness-finish.js @@ -0,0 +1,26 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(function() { + +"use strict"; + +function printResult (str) { + print (str); +} + +function printError (str) { + print (str); +} + +function printScore (str) { + print (str); +} + +benchmarks.runAll ({notifyResult: printResult, + notifyError: printError, + notifyScore: printScore}, + true); + +})(); diff --git a/deps/v8/test/simdjs/simdjs.status b/deps/v8/test/simdjs/simdjs.status new file mode 100644 index 0000000000..99ce8865e5 --- /dev/null +++ b/deps/v8/test/simdjs/simdjs.status @@ -0,0 +1,26 @@ +# Copyright 2015 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# -------------------------------------------------------------------- +# If you add a test case to this file, please try to provide +# an explanation of why the test fails; this may ease future +# debugging. +# -------------------------------------------------------------------- + +[ +[ALWAYS, { + # TODO(bradnelson): Drop when test is fixed upstream. + 'benchmarks/aobench': SKIP, + + # TODO(bbudge): Drop this when simd implementation is faster. + 'benchmarks/memcpy': SKIP, +}], + +###################################################################### +['byteorder == big', { + # shell_test_runner requires little-endian, skip it on big-endian. + 'shell_test_runner': [SKIP], +}], # 'byteorder == big' + +] diff --git a/deps/v8/test/simdjs/testcfg.py b/deps/v8/test/simdjs/testcfg.py new file mode 100644 index 0000000000..c0390afd65 --- /dev/null +++ b/deps/v8/test/simdjs/testcfg.py @@ -0,0 +1,101 @@ +# 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. + + +import hashlib +import os +import shutil +import sys +import tarfile +import imp + +from testrunner.local import testsuite +from testrunner.local import utils +from testrunner.objects import testcase + +SIMDJS_ARCHIVE_REVISION = "07e2713e0c9ea19feb0732d5bd84770c87310d79" +SIMDJS_ARCHIVE_MD5 = "cf6bddf99f18800b68e782054268ee3c" +SIMDJS_URL = ( + "https://github.com/johnmccutchan/ecmascript_simd/archive/%s.tar.gz") + +SIMDJS_SUITE_PATH = ["data", "src"] + + +class SimdJsTestSuite(testsuite.TestSuite): + + def __init__(self, name, root): + super(SimdJsTestSuite, self).__init__(name, root) + self.testroot = os.path.join(self.root, *SIMDJS_SUITE_PATH) + self.ParseTestRecord = None + + def ListTests(self, context): + tests = [ + testcase.TestCase(self, 'shell_test_runner'), + ] + for filename in os.listdir(os.path.join(self.testroot, 'benchmarks')): + if (not filename.endswith('.js') or + filename in ['run.js', 'run_browser.js', 'base.js']): + continue + name = filename.rsplit('.')[0] + tests.append( + testcase.TestCase(self, 'benchmarks/' + name)) + return tests + + def GetFlagsForTestCase(self, testcase, context): + return (testcase.flags + context.mode_flags + + [os.path.join(self.root, "harness-adapt.js"), + "--harmony", + os.path.join(self.testroot, testcase.path + ".js"), + os.path.join(self.root, "harness-finish.js")]) + + def GetSourceForTest(self, testcase): + filename = os.path.join(self.testroot, testcase.path + ".js") + with open(filename) as f: + return f.read() + + def IsNegativeTest(self, testcase): + return False + + def IsFailureOutput(self, output, testpath): + if output.exit_code != 0: + return True + return "FAILED!" in output.stdout + + def DownloadData(self): + revision = SIMDJS_ARCHIVE_REVISION + archive_url = SIMDJS_URL % revision + archive_name = os.path.join( + self.root, "ecmascript_simd-%s.tar.gz" % revision) + directory_name = os.path.join(self.root, "data") + directory_old_name = os.path.join(self.root, "data.old") + if not os.path.exists(archive_name): + print "Downloading test data from %s ..." % archive_url + utils.URLRetrieve(archive_url, archive_name) + if os.path.exists(directory_name): + if os.path.exists(directory_old_name): + shutil.rmtree(directory_old_name) + os.rename(directory_name, directory_old_name) + if not os.path.exists(directory_name): + print "Extracting ecmascript_simd-%s.tar.gz ..." % revision + md5 = hashlib.md5() + with open(archive_name, "rb") as f: + for chunk in iter(lambda: f.read(8192), ""): + md5.update(chunk) + print "MD5 hash is %s" % md5.hexdigest() + if md5.hexdigest() != SIMDJS_ARCHIVE_MD5: + os.remove(archive_name) + print "MD5 expected %s" % SIMDJS_ARCHIVE_MD5 + raise Exception("MD5 hash mismatch of test data file") + archive = tarfile.open(archive_name, "r:gz") + if sys.platform in ("win32", "cygwin"): + # Magic incantation to allow longer path names on Windows. + archive.extractall(u"\\\\?\\%s" % self.root) + else: + archive.extractall(self.root) + os.rename(os.path.join(self.root, "ecmascript_simd-%s" % revision), + directory_name) + + +def GetSuite(name, root): + return SimdJsTestSuite(name, root) diff --git a/deps/v8/test/test262-es6/README b/deps/v8/test/test262-es6/README index 531189719b..fe3ab232ba 100644 --- a/deps/v8/test/test262-es6/README +++ b/deps/v8/test/test262-es6/README @@ -4,13 +4,13 @@ tests from https://github.com/tc39/test262 -at hash 43acf61 (2015/03/31 revision) as 'data' in this directory. Using later +at hash c6ac390 (2015/07/06 revision) as 'data' in this directory. Using later version may be possible but the tests are only known to pass (and indeed run) with that revision. git clone https://github.com/tc39/test262 data cd data - git checkout 43acf61 + git checkout c6ac390 If you do update to a newer revision you may have to change the test harness adapter code since it uses internal functionality from the diff --git a/deps/v8/test/test262-es6/test262-es6.status b/deps/v8/test/test262-es6/test262-es6.status index 31bb60bd22..65ded6d3f5 100644 --- a/deps/v8/test/test262-es6/test262-es6.status +++ b/deps/v8/test/test262-es6/test262-es6.status @@ -33,6 +33,30 @@ 'intl402/11.2.3_b': [FAIL], 'intl402/12.2.3_b': [FAIL], + # BUG(v8:4267) + 'built-ins/Object/defineProperty/15.2.3.6-4-116': [FAIL], + 'built-ins/Object/defineProperty/15.2.3.6-4-117': [FAIL], + 'built-ins/Object/defineProperty/15.2.3.6-4-168': [FAIL], + 'built-ins/Object/defineProperty/15.2.3.6-4-169': [FAIL], + 'built-ins/Object/defineProperty/15.2.3.6-4-170': [FAIL], + 'built-ins/Object/defineProperty/15.2.3.6-4-172': [FAIL], + 'built-ins/Object/defineProperty/15.2.3.6-4-173': [FAIL], + 'built-ins/Object/defineProperty/15.2.3.6-4-174': [FAIL], + 'built-ins/Object/defineProperty/15.2.3.6-4-176': [FAIL], + 'built-ins/Object/defineProperty/15.2.3.6-4-177': [FAIL], + 'built-ins/Object/defineProperties/15.2.3.7-6-a-112': [FAIL], + 'built-ins/Object/defineProperties/15.2.3.7-6-a-113': [FAIL], + 'built-ins/Object/defineProperties/15.2.3.7-6-a-164': [FAIL], + 'built-ins/Object/defineProperties/15.2.3.7-6-a-165': [FAIL], + 'built-ins/Object/defineProperties/15.2.3.7-6-a-166': [FAIL], + 'built-ins/Object/defineProperties/15.2.3.7-6-a-168': [FAIL], + 'built-ins/Object/defineProperties/15.2.3.7-6-a-169': [FAIL], + 'built-ins/Object/defineProperties/15.2.3.7-6-a-170': [FAIL], + 'built-ins/Object/defineProperties/15.2.3.7-6-a-172': [FAIL], + 'built-ins/Object/defineProperties/15.2.3.7-6-a-173': [FAIL], + 'built-ins/Object/defineProperties/15.2.3.7-6-a-175': [FAIL], + 'built-ins/Object/defineProperties/15.2.3.7-6-a-176': [FAIL], + # Unicode canonicalization is not available with i18n turned off. 'built-ins/String/prototype/localeCompare/15.5.4.9_CE': [['no_i18n', SKIP]], @@ -50,141 +74,222 @@ ###################### MISSING ES6 FEATURES ####################### - # Array.fill (currently requires --harmony-arrays) - 'built-ins/Array/prototype/fill/S22.1.3.6_T1': [FAIL], - - # Array.find (currently requires --harmony-arrays) - 'built-ins/Array/of/S22.1.2.3_T1': [FAIL], - 'built-ins/Array/of/S22.1.2.3_T2': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_empty-array-undefined': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_length-property': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_modify-after-start': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_non-returning-predicate': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_predicate-arguments': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_push-after-start': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_remove-after-start': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_return-found-value': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_skip-empty': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_this-defined': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_this-is-object': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_this-undefined': [FAIL], - - # Array.from - 'built-ins/Array/from/S22.1.2.1_T1': [FAIL], - 'built-ins/Array/from/S22.1.2.1_T2': [FAIL], - - # Direct proxies - 'built-ins/Array/prototype/find/Array.prototype.find_callable-predicate': [FAIL], - - # --harmony-computed-property-names is not yet enabled - 'language/computed-property-names/class/accessor/getter': [FAIL], - 'language/computed-property-names/class/accessor/getter-duplicates': [FAIL], - 'language/computed-property-names/class/accessor/setter': [FAIL], - 'language/computed-property-names/class/accessor/setter-duplicates': [FAIL], - 'language/computed-property-names/class/method/constructor': [FAIL], - 'language/computed-property-names/class/method/generator': [FAIL], - 'language/computed-property-names/class/method/number': [FAIL], - 'language/computed-property-names/class/method/string': [FAIL], - 'language/computed-property-names/class/method/symbol': [FAIL], - 'language/computed-property-names/class/static/method-number': [FAIL], - 'language/computed-property-names/class/static/method-string': [FAIL], - 'language/computed-property-names/class/static/method-symbol': [FAIL], - 'language/computed-property-names/to-name-side-effects/class': [FAIL], - 'language/computed-property-names/to-name-side-effects/numbers-class': [FAIL], - - # Number.prototype is a plain object in ES6 + # Class, let, const in sloppy mode. + # https://code.google.com/p/v8/issues/detail?id=3305 + 'built-ins/Array/prototype/concat/Array.prototype.concat_non-array': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/finally-block-let-declaration-only-shadows-outer-parameter-value-1': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/finally-block-let-declaration-only-shadows-outer-parameter-value-2': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/for-loop-block-let-declaration-only-shadows-outer-parameter-value-1': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/for-loop-block-let-declaration-only-shadows-outer-parameter-value-2': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/nested-block-let-declaration-only-shadows-outer-parameter-value-1': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/nested-block-let-declaration-only-shadows-outer-parameter-value-2': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/outermost-binding-updated-in-catch-block-nested-block-let-declaration-unseen-outside-of-block': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/try-block-let-declaration-only-shadows-outer-parameter-value-1': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/try-block-let-declaration-only-shadows-outer-parameter-value-2': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/verify-context-in-finally-block': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/verify-context-in-for-loop-block': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/verify-context-in-labelled-block': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/verify-context-in-try-block': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/x-after-break-to-label': [PASS, FAIL_SLOPPY], + 'language/block-scope/leave/x-before-continue': [PASS, FAIL_SLOPPY], + 'language/block-scope/return-from/block-let': [PASS, FAIL_SLOPPY], + 'language/block-scope/shadowing/catch-parameter-shadowing-let-declaration': [PASS, FAIL_SLOPPY], + 'language/block-scope/shadowing/const-declaration-shadowing-catch-parameter': [PASS, FAIL_SLOPPY], + 'language/block-scope/shadowing/const-declarations-shadowing-parameter-name-let-const-and-var-variables': [PASS, FAIL_SLOPPY], + 'language/block-scope/shadowing/dynamic-lookup-from-closure': [PASS, FAIL_SLOPPY], + 'language/block-scope/shadowing/dynamic-lookup-in-and-through-block-contexts': [PASS, FAIL_SLOPPY], + 'language/block-scope/shadowing/let-declaration-shadowing-catch-parameter': [PASS, FAIL_SLOPPY], + 'language/block-scope/shadowing/let-declarations-shadowing-parameter-name-let-const-and-var': [PASS, FAIL_SLOPPY], + 'language/block-scope/shadowing/lookup-from-closure': [PASS, FAIL_SLOPPY], + 'language/block-scope/shadowing/lookup-in-and-through-block-contexts': [PASS, FAIL_SLOPPY], + 'language/block-scope/shadowing/parameter-name-shadowing-parameter-name-let-const-and-var': [PASS, FAIL_SLOPPY], + 'language/block-scope/syntax/for-in/acquire-properties-from-array': [PASS, FAIL_SLOPPY], + 'language/block-scope/syntax/for-in/acquire-properties-from-object': [PASS, FAIL_SLOPPY], + 'language/block-scope/syntax/for-in/mixed-values-in-iteration': [PASS, FAIL_SLOPPY], + 'language/block-scope/syntax/redeclaration-in-block/attempt-to-redeclare-function-declaration-with-function-declaration': [PASS, FAIL_SLOPPY], + 'language/block-scope/syntax/redeclaration-in-block/attempt-to-redeclare-function-declaration-with-var': [PASS, FAIL_SLOPPY], + 'language/block-scope/syntax/redeclaration-in-block/attempt-to-redeclare-var-with-function-declaration': [PASS, FAIL_SLOPPY], + 'language/class/definition/ClassDeclaration_restricted-properties': [PASS, FAIL_SLOPPY], + 'language/class/definition/ClassExpression_restricted-properties': [PASS, FAIL_SLOPPY], + 'language/class/definition/ClassMethod_restricted-properties': [PASS, FAIL_SLOPPY], + 'language/class/method-definition/generator-no-yield': [PASS, FAIL_SLOPPY], + 'language/class/method-definition/generator-return': [PASS, FAIL_SLOPPY], + 'language/class/method-definition/yield-as-expression-with-rhs': [PASS, FAIL_SLOPPY], + 'language/class/method-definition/yield-as-expression-without-rhs': [PASS, FAIL_SLOPPY], + 'language/class/method-definition/yield-as-generator-method-binding-identifier': [PASS, FAIL_SLOPPY], + 'language/class/method-definition/yield-as-literal-property-name': [PASS, FAIL_SLOPPY], + 'language/class/method-definition/yield-as-property-name': [PASS, FAIL_SLOPPY], + 'language/class/method-definition/yield-as-statement': [PASS, FAIL_SLOPPY], + 'language/class/method-definition/yield-as-yield-operand': [PASS, FAIL_SLOPPY], + 'language/class/method-definition/yield-newline': [PASS, FAIL_SLOPPY], + 'language/class/method-definition/yield-star-before-newline': [PASS, FAIL_SLOPPY], + 'language/computed-property-names/class/accessor/*': [PASS, FAIL_SLOPPY], + 'language/computed-property-names/class/method/*': [PASS, FAIL_SLOPPY], + 'language/computed-property-names/class/static/generator-constructor': [PASS, FAIL_SLOPPY], + 'language/computed-property-names/class/static/generator-prototype': [PASS, FAIL_SLOPPY], + 'language/computed-property-names/class/static/getter-constructor': [PASS, FAIL_SLOPPY], + 'language/computed-property-names/class/static/getter-prototype': [PASS, FAIL_SLOPPY], + 'language/computed-property-names/class/static/method-constructor': [PASS, FAIL_SLOPPY], + 'language/computed-property-names/class/static/method-prototype': [PASS, FAIL_SLOPPY], + 'language/computed-property-names/class/static/setter-constructor': [PASS, FAIL_SLOPPY], + 'language/computed-property-names/class/static/setter-prototype': [PASS, FAIL_SLOPPY], + 'language/computed-property-names/to-name-side-effects/class': [PASS, FAIL_SLOPPY], + 'language/computed-property-names/to-name-side-effects/numbers-class': [PASS, FAIL_SLOPPY], + 'language/expressions/arrow-function/lexical-super-call-from-within-constructor':[PASS, FAIL_SLOPPY], + 'language/expressions/arrow-function/lexical-super-property-from-within-constructor': [PASS, FAIL_SLOPPY], + 'language/expressions/arrow-function/lexical-super-property': [PASS, FAIL_SLOPPY], + 'language/expressions/arrow-function/lexical-supercall-from-immediately-invoked-arrow': [PASS, FAIL_SLOPPY], + 'language/expressions/object/method-definition/generator-param-redecl-const': [PASS, FAIL_SLOPPY], + 'language/expressions/object/method-definition/generator-shadow-parameter-const': [PASS, FAIL_SLOPPY], + 'language/rest-parameters/with-new-target': [PASS, FAIL_SLOPPY], + 'language/statements/class/arguments/access': [PASS, FAIL_SLOPPY], + 'language/statements/class/arguments/default-constructor': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/accessors': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/constructable-but-no-prototype': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/constructor-property': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/constructor-strict-by-default': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/constructor': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/getters-2': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/getters': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/implicit-constructor': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/invalid-extends': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/methods-named-eval-arguments': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/methods': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/numeric-property-names': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/prototype-getter': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/prototype-property': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/prototype-setter': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/prototype-wiring': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/setters-2': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/setters': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/side-effects-in-extends': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/side-effects-in-property-define': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/this-access-restriction-2': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/this-access-restriction': [PASS, FAIL_SLOPPY], + 'language/statements/class/definition/this-check-ordering': [PASS, FAIL_SLOPPY], + 'language/statements/class/name-binding/basic': [PASS, FAIL_SLOPPY], + 'language/statements/class/name-binding/const': [PASS, FAIL_SLOPPY], + 'language/statements/class/name-binding/expression': [PASS, FAIL_SLOPPY], + 'language/statements/class/strict-mode/arguments-caller': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/binding': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/builtins': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/class-definition-evaluation-empty-constructor-heritage-present': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/class-definition-null-proto-contains-return-override': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/class-definition-null-proto-missing-return-override': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/class-definition-null-proto': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/class-definition-superclass-generator': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/default-constructor-2': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/default-constructor': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/derived-class-return-override-with-boolean': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/derived-class-return-override-with-empty': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/derived-class-return-override-with-null': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/derived-class-return-override-with-number': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/derived-class-return-override-with-object': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/derived-class-return-override-with-string': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/derived-class-return-override-with-symbol': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/derived-class-return-override-with-this': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/derived-class-return-override-with-undefined': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/superclass-prototype-setter-constructor': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/superclass-prototype-setter-method-override': [PASS, FAIL_SLOPPY], + 'language/statements/class/subclass/superclass-static-method-override': [PASS, FAIL_SLOPPY], + 'language/statements/class/super/in-constructor': [PASS, FAIL_SLOPPY], + 'language/statements/class/super/in-getter': [PASS, FAIL_SLOPPY], + 'language/statements/class/super/in-methods': [PASS, FAIL_SLOPPY], + 'language/statements/class/super/in-setter': [PASS, FAIL_SLOPPY], + 'language/statements/class/super/in-static-getter': [PASS, FAIL_SLOPPY], + 'language/statements/class/super/in-static-methods': [PASS, FAIL_SLOPPY], + 'language/statements/class/super/in-static-setter': [PASS, FAIL_SLOPPY], + 'language/statements/class/syntax/class-body-has-direct-super-class-heritage': [PASS, FAIL_SLOPPY], + 'language/statements/class/syntax/class-body-method-definition-super-property': [PASS, FAIL_SLOPPY], + 'language/statements/class/syntax/class-declaration-binding-identifier-class-element-list': [PASS, FAIL_SLOPPY], + 'language/statements/class/syntax/class-declaration-computed-method-definition': [PASS, FAIL_SLOPPY], + 'language/statements/class/syntax/class-declaration-computed-method-generator-definition': [PASS, FAIL_SLOPPY], + 'language/statements/class/syntax/class-declaration-heritage-identifier-reference-class-element-list': [PASS, FAIL_SLOPPY], + 'language/statements/class/syntax/class-expression-binding-identifier-opt-class-element-list': [PASS, FAIL_SLOPPY], + 'language/statements/class/syntax/class-expression-heritage-identifier-reference': [PASS, FAIL_SLOPPY], + 'language/statements/class/syntax/class-expression': [PASS, FAIL_SLOPPY], + 'language/statements/class/syntax/class-method-propname-constructor': [PASS, FAIL_SLOPPY], + 'language/statements/class/syntax/early-errors/class-body-constructor-empty-missing-class-heritage': [PASS, FAIL_SLOPPY], + 'language/statements/const/block-local-closure-get-before-initialization': [PASS, FAIL_SLOPPY], + 'language/statements/const/block-local-use-before-initialization-in-declaration-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/block-local-use-before-initialization-in-prior-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/function-local-closure-get-before-initialization': [PASS, FAIL_SLOPPY], + 'language/statements/const/function-local-use-before-initialization-in-declaration-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/function-local-use-before-initialization-in-prior-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/global-closure-get-before-initialization': [PASS, FAIL_SLOPPY], + 'language/statements/const/global-use-before-initialization-in-declaration-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/global-use-before-initialization-in-prior-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/block-scope-syntax-const-declarations-mixed-with-without-initialiser': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/block-scope-syntax-const-declarations-mixed-without-with-initialiser': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/block-scope-syntax-const-declarations-without-initialiser': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/const-invalid-assignment-statement-body-for-in': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/const-invalid-assignment-statement-body-for-of': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/const-outer-inner-let-bindings': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/const': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/with-initializer-do-statement-while-expression': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/with-initializer-for-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/with-initializer-if-expression-statement-else-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/with-initializer-if-expression-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/with-initializer-label-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/with-initializer-while-expression-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/without-initializer-case-expression-statement-list': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/without-initializer-default-statement-list': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/without-initializer-do-statement-while-expression': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/without-initializer-for-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/without-initializer-if-expression-statement-else-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/without-initializer-if-expression-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/without-initializer-label-statement': [PASS, FAIL_SLOPPY], + 'language/statements/const/syntax/without-initializer-while-expression-statement': [PASS, FAIL_SLOPPY], + 'language/statements/continue/labeled-continue': [PASS, FAIL_SLOPPY], + 'language/statements/continue/nested-let-bound-for-loops-inner-continue': [PASS, FAIL_SLOPPY], + 'language/statements/continue/nested-let-bound-for-loops-labeled-continue': [PASS, FAIL_SLOPPY], + 'language/statements/continue/nested-let-bound-for-loops-outer-continue': [PASS, FAIL_SLOPPY], + 'language/statements/continue/no-label-continue': [PASS, FAIL_SLOPPY], + 'language/statements/continue/shadowing-loop-variable-in-same-scope-as-continue': [PASS, FAIL_SLOPPY], + 'language/statements/continue/simple-and-labeled': [PASS, FAIL_SLOPPY], + 'language/statements/for-in/const-fresh-binding-per-iteration-for-in': [PASS, FAIL_SLOPPY], + 'language/statements/for-in/let-fresh-binding-per-iteration-for-in': [PASS, FAIL_SLOPPY], + 'language/statements/for-of/const-fresh-binding-per-iteration-for-of': [PASS, FAIL_SLOPPY], + 'language/statements/for-of/let-fresh-binding-per-iteration-for-of': [PASS, FAIL_SLOPPY], + 'language/statements/for/const-fresh-binding-per-iteration-for': [PASS, FAIL_SLOPPY], + 'language/statements/for/let-fresh-binding-per-iteration-for': [PASS, FAIL_SLOPPY], + 'language/statements/let/syntax/let-closure-inside-condition': [PASS, FAIL_SLOPPY], + 'language/statements/let/syntax/let-closure-inside-initialization': [PASS, FAIL_SLOPPY], + 'language/statements/let/syntax/let-closure-inside-next-expression': [PASS, FAIL_SLOPPY], + 'language/statements/let/syntax/let-iteration-variable-is-freshly-allocated-for-each-iteration-multi-let-binding': [PASS, FAIL_SLOPPY], + 'language/statements/let/syntax/let-iteration-variable-is-freshly-allocated-for-each-iteration-single-let-binding': [PASS, FAIL_SLOPPY], + 'language/statements/let/syntax/let-outer-inner-let-bindings': [PASS, FAIL_SLOPPY], + 'language/statements/let/syntax/let': [PASS, FAIL_SLOPPY], + 'language/statements/let/syntax/with-initialisers-in-statement-positions-case-expression-statement-list': [PASS, FAIL_SLOPPY], + 'language/statements/let/syntax/with-initialisers-in-statement-positions-default-statement-list': [PASS, FAIL_SLOPPY], + 'language/statements/let/syntax/without-initialisers-in-statement-positions-case-expression-statement-list': [PASS, FAIL_SLOPPY], + 'language/statements/let/syntax/without-initialisers-in-statement-positions-default-statement-list': [PASS, FAIL_SLOPPY], + + # https://code.google.com/p/v8/issues/detail?id=3305 + # This times out in sloppy mode because sloppy const assignment does not throw. + 'language/statements/const/syntax/const-invalid-assignment-next-expression-for': [PASS, FAIL, TIMEOUT], + + # Number/Boolean.prototype is a plain object in ES6 + # https://code.google.com/p/v8/issues/detail?id=4001 'built-ins/Number/15.7.4-1': [FAIL], - 'built-ins/Number/prototype/S15.7.3.1_A2_T1': [FAIL], - 'built-ins/Number/prototype/S15.7.3.1_A2_T2': [FAIL], + 'built-ins/Number/prototype/S15.7.3.1_A2_*': [FAIL], 'built-ins/Number/prototype/S15.7.3.1_A3': [FAIL], 'built-ins/Number/prototype/S15.7.4_A1': [FAIL], 'built-ins/Number/prototype/toFixed/S15.7.4.5_A1.1_T01': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A1_T01': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A1_T02': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A1_T03': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T01': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T02': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T03': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T04': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T05': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T06': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T07': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T08': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T09': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T10': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T11': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T12': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T13': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T14': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T15': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T16': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T17': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T18': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T19': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T20': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T21': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T22': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T23': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T24': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T25': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T26': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T27': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T28': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T29': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T30': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T31': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T32': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T33': [FAIL], - 'built-ins/Number/prototype/toString/S15.7.4.2_A2_T34': [FAIL], - 'built-ins/Number/prototype/valueOf/S15.7.4.4_A1_T01': [FAIL], - 'built-ins/Number/prototype/valueOf/S15.7.4.4_A1_T02': [FAIL], - - ######################## OBSOLETED BY ES6 ########################### - - # ES6 allows duplicate properties - 'language/expressions/object/11.1.5-4-4-a-1-s': [FAIL], - 'language/expressions/object/11.1.5_4-4-b-1': [FAIL], - 'language/expressions/object/11.1.5_4-4-b-2': [FAIL], - 'language/expressions/object/11.1.5_4-4-c-1': [FAIL], - 'language/expressions/object/11.1.5_4-4-c-2': [FAIL], - 'language/expressions/object/11.1.5_4-4-d-1': [FAIL], - 'language/expressions/object/11.1.5_4-4-d-2': [FAIL], - 'language/expressions/object/11.1.5_4-4-d-3': [FAIL], - 'language/expressions/object/11.1.5_4-4-d-4': [FAIL], - - ######################## NEEDS INVESTIGATION ########################### + 'built-ins/Number/prototype/toString/S15.7.4.2_A1_*': [FAIL], + 'built-ins/Number/prototype/toString/S15.7.4.2_A2_*': [FAIL], + 'built-ins/Number/prototype/valueOf/S15.7.4.4_A1_*': [FAIL], + 'built-ins/Boolean/prototype/S15.6.3.1_A1': [FAIL], + 'built-ins/Boolean/prototype/S15.6.4_A1': [FAIL], + 'built-ins/Boolean/prototype/toString/S15.6.4.2_A1_T1': [FAIL], + 'built-ins/Boolean/prototype/toString/S15.6.4.2_A1_T2': [FAIL], + 'built-ins/Boolean/prototype/valueOf/S15.6.4.3_A1_T1': [FAIL], + 'built-ins/Boolean/prototype/valueOf/S15.6.4.3_A1_T2': [FAIL], - # These test failures are specific to the intl402 suite and need investigation - # to be either marked as bugs with issues filed for them or as deliberate - # incompatibilities if the test cases turn out to be broken or ambiguous. - 'intl402/6.2.3': [FAIL], - 'intl402/9.2.1_2': [FAIL], - 'intl402/9.2.6_2': [FAIL], - 'intl402/10.1.1_a': [FAIL], - 'intl402/10.1.1_19_c': [PASS, FAIL, NO_VARIANTS], - 'intl402/10.1.2.1_4': [FAIL], - 'intl402/10.2.3_b': [PASS, FAIL], - 'intl402/10.3_a': [FAIL], - 'intl402/11.1.1_17': [PASS, FAIL], - 'intl402/11.1.1_19': [PASS, FAIL], - 'intl402/11.1.1_20_c': [FAIL], - 'intl402/11.1.1_a': [FAIL], - 'intl402/11.1.2.1_4': [FAIL], - 'intl402/11.3.2_FN_2': [PASS, FAIL], - 'intl402/11.3.2_TRF': [PASS, FAIL], - 'intl402/11.3_a': [FAIL], - 'intl402/12.1.1_a': [FAIL], - 'intl402/12.1.2.1_4': [FAIL], - 'intl402/12.3.2_FDT_7_a_iv': [FAIL], - 'intl402/12.3.3': [FAIL], - 'intl402/12.3_a': [FAIL], + # https://code.google.com/p/v8/issues/detail?id=4118 + 'built-ins/Object/getOwnPropertyNames/15.2.3.4-4-44': [FAIL], - # Test 262 update 2015-03-11 - 'built-ins/Array/isArray/15.4.3.2-0-5': [FAIL], - 'built-ins/Array/prototype/S15.4.3.1_A5': [FAIL], - 'built-ins/Array/prototype/S15.4.4_A1.1_T2': [FAIL], - 'built-ins/Array/prototype/S15.4.4_A1.2_T1': [FAIL], - 'built-ins/Array/prototype/S15.4.4_A1.3_T1': [FAIL], + # https://code.google.com/p/v8/issues/detail?id=3087 'built-ins/Array/prototype/every/15.4.4.16-3-12': [FAIL], 'built-ins/Array/prototype/every/15.4.4.16-3-14': [FAIL], 'built-ins/Array/prototype/every/15.4.4.16-3-25': [FAIL], @@ -194,11 +299,6 @@ 'built-ins/Array/prototype/filter/15.4.4.20-3-12': [FAIL], 'built-ins/Array/prototype/filter/15.4.4.20-3-25': [FAIL], 'built-ins/Array/prototype/filter/15.4.4.20-3-7': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_callable-Proxy-1': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_callable-Proxy-2': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_callable-arrowfunction': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_callable-forEach': [FAIL], - 'built-ins/Array/prototype/find/Array.prototype.find_this-global': [FAIL], 'built-ins/Array/prototype/forEach/15.4.4.18-3-12': [FAIL], 'built-ins/Array/prototype/forEach/15.4.4.18-3-25': [FAIL], 'built-ins/Array/prototype/forEach/15.4.4.18-3-7': [FAIL], @@ -250,26 +350,51 @@ 'built-ins/Array/prototype/splice/S15.4.4.12_A3_T1': [FAIL], 'built-ins/Array/prototype/splice/S15.4.4.12_A3_T3': [FAIL], 'built-ins/Array/prototype/unshift/S15.4.4.13_A3_T2': [FAIL], - 'built-ins/Boolean/prototype/S15.6.3.1_A1': [FAIL], - 'built-ins/Boolean/prototype/S15.6.4_A1': [FAIL], - 'built-ins/Boolean/prototype/toString/S15.6.4.2_A1_T1': [FAIL], - 'built-ins/Boolean/prototype/toString/S15.6.4.2_A1_T2': [FAIL], - 'built-ins/Boolean/prototype/valueOf/S15.6.4.3_A1_T1': [FAIL], - 'built-ins/Boolean/prototype/valueOf/S15.6.4.3_A1_T2': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=1543 + 'built-ins/Proxy/*': [FAIL], + 'built-ins/Array/prototype/find/Array.prototype.find_callable-Proxy-1': [FAIL], + 'built-ins/Array/prototype/find/Array.prototype.find_callable-Proxy-2': [FAIL], + 'built-ins/Object/assign/source-own-prop-desc-missing': [FAIL], + 'built-ins/Object/assign/source-own-prop-error': [FAIL], + 'built-ins/Object/assign/source-own-prop-keys-error': [FAIL], + 'built-ins/Object/setPrototypeOf/set-error': [FAIL], + 'language/expressions/object/prop-def-id-eval-error-2': [FAIL], + 'language/statements/for-of/iterator-as-proxy': [FAIL], + 'language/statements/for-of/iterator-next-result-type': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4093 + 'built-ins/Array/symbol-species': [FAIL], + 'built-ins/ArrayBuffer/symbol-species': [FAIL], + 'built-ins/Map/symbol-species': [FAIL], + 'built-ins/Promise/symbol-species': [FAIL], + 'built-ins/RegExp/symbol-species': [FAIL], + 'built-ins/Set/symbol-species': [FAIL], + 'built-ins/Symbol/species/basic': [FAIL], + 'built-ins/Symbol/species/builtin-getter-name': [FAIL], + 'built-ins/Symbol/species/subclassing': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4242 'built-ins/Date/15.9.1.15-1': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4004 'built-ins/Date/prototype/setFullYear/15.9.5.40_1': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4002 'built-ins/Error/prototype/S15.11.4_A2': [FAIL], - 'built-ins/Object/defineProperty/15.2.3.6-4-293-4': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4163 + 'built-ins/GeneratorPrototype/next/context-constructor-invocation': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=3566 + 'built-ins/Set/set-iterator-close-after-add-failure': [FAIL], + 'built-ins/WeakSet/iterator-close-after-add-failure': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=3715 'built-ins/Object/getOwnPropertyDescriptor/15.2.3.3-4-212': [FAIL], 'built-ins/Object/getOwnPropertyDescriptor/15.2.3.3-4-213': [FAIL], 'built-ins/Object/getOwnPropertyDescriptor/15.2.3.3-4-214': [FAIL], 'built-ins/Object/getOwnPropertyDescriptor/15.2.3.3-4-215': [FAIL], - 'built-ins/Promise/S25.4.3.1_A5.1_T2': [FAIL], - 'built-ins/Promise/prototype/then/S25.4.2.1_A3.1_T2': [FAIL], - 'built-ins/Promise/prototype/then/S25.4.2.1_A3.2_T2': [FAIL], - 'built-ins/Promise/race/S25.4.4.3_A3.1_T2': [FAIL], - 'built-ins/Promise/reject/S25.4.4.4_A3.1_T1': [FAIL], - 'built-ins/RegExp/prototype/15.10.6': [FAIL], 'built-ins/RegExp/prototype/global/15.10.7.2-1': [FAIL], 'built-ins/RegExp/prototype/global/15.10.7.2-2': [FAIL], 'built-ins/RegExp/prototype/global/S15.10.7.2_A9': [FAIL], @@ -284,302 +409,330 @@ 'built-ins/RegExp/prototype/source/15.10.7.1-1': [FAIL], 'built-ins/RegExp/prototype/source/15.10.7.1-2': [FAIL], 'built-ins/RegExp/prototype/source/S15.10.7.1_A9': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4243 + 'built-ins/Promise/race/S25.4.4.3_A3.1_T2': [FAIL], + 'built-ins/Promise/reject/S25.4.4.4_A3.1_T1': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4119 + 'built-ins/RegExp/15.10.4.1-1': [FAIL], + 'built-ins/RegExp/S15.10.3.1_A2_T1': [FAIL], + 'built-ins/RegExp/S15.10.3.1_A2_T2': [FAIL], + 'built-ins/RegExp/S15.10.4.1_A2_T1': [FAIL], + 'built-ins/RegExp/S15.10.4.1_A2_T2': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4003 + 'built-ins/RegExp/prototype/15.10.6': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4244 + 'built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T3': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4006 'built-ins/String/prototype/S15.5.4_A1': [FAIL], 'built-ins/String/prototype/S15.5.4_A2': [FAIL], 'built-ins/String/prototype/S15.5.4_A3': [FAIL], + 'language/expressions/property-accessors/S11.2.1_A4_T5': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4245 'built-ins/String/prototype/split/S15.5.4.14_A2_T37': [FAIL], - 'intl402/10.1_L15': [FAIL], - 'intl402/10.2.2_L15': [FAIL], - 'intl402/10.3.2_1_a_L15': [FAIL], - 'intl402/10.3.2_L15': [FAIL], - 'intl402/10.3.3_L15': [FAIL], - 'intl402/11.1_L15': [FAIL], - 'intl402/11.2.2_L15': [FAIL], - 'intl402/11.3.2_1_a_L15': [FAIL], - 'intl402/11.3.2_L15': [FAIL], - 'intl402/11.3.3_L15': [FAIL], - 'intl402/12.1_L15': [FAIL], - 'intl402/12.2.2_L15': [FAIL], - 'intl402/12.3.2_1_a_L15': [FAIL], - 'intl402/12.3.2_L15': [FAIL], - 'intl402/12.3.3_L15': [FAIL], - 'intl402/13.1.1_L15': [FAIL], - 'intl402/13.2.1_L15': [FAIL], - 'intl402/13.3.1_L15': [FAIL], - 'intl402/13.3.2_L15': [FAIL], - 'intl402/13.3.3_L15': [FAIL], - 'language/arrow-function/Arrow-Function_rules-for-prototype': [FAIL], - 'language/arrow-function/Arrow-Function_semantics': [FAIL], - 'language/arrow-function/Arrow-Function_syntax-variations': [FAIL], - 'language/class/arguments/access': [FAIL], - 'language/class/arguments/default-constructor': [FAIL], - 'language/class/definition/accessors': [FAIL], - 'language/class/definition/basics': [FAIL], - 'language/class/definition/constructable-but-no-prototype': [FAIL], - 'language/class/definition/constructor': [FAIL], - 'language/class/definition/constructor-property': [FAIL], - 'language/class/definition/constructor-strict-by-default': [FAIL], - 'language/class/definition/getters': [FAIL], - 'language/class/definition/getters-2': [FAIL], - 'language/class/definition/implicit-constructor': [FAIL], - 'language/class/definition/invalid-extends': [FAIL], - 'language/class/definition/methods': [FAIL], - 'language/class/definition/methods-named-eval-arguments': [FAIL], - 'language/class/definition/numeric-property-names': [FAIL], - 'language/class/definition/prototype-getter': [FAIL], - 'language/class/definition/prototype-property': [FAIL], - 'language/class/definition/prototype-setter': [FAIL], - 'language/class/definition/prototype-wiring': [FAIL], - 'language/class/definition/setters': [FAIL], - 'language/class/definition/setters-2': [FAIL], - 'language/class/definition/side-effects-in-extends': [FAIL], - 'language/class/definition/side-effects-in-property-define': [FAIL], - 'language/class/definition/this-access-restriction': [FAIL], - 'language/class/definition/this-access-restriction-2': [FAIL], - 'language/class/definition/this-check-ordering': [FAIL], - 'language/class/name-binding/basic': [FAIL], - 'language/class/name-binding/const': [FAIL], - 'language/class/name-binding/expression': [FAIL], - 'language/class/strict-mode/arguments-caller': [FAIL], - 'language/class/subclass/binding': [FAIL], - 'language/class/subclass/builtins': [FAIL], - 'language/class/subclass/default-constructor': [FAIL], - 'language/class/subclass/default-constructor-2': [FAIL], - 'language/class/subclass/null': [FAIL], - 'language/class/subclass/superclass-prototype-setter-constructor': [FAIL], - 'language/class/subclass/superclass-prototype-setter-method-override': [FAIL], - 'language/class/subclass/superclass-static-method-override': [FAIL], - 'language/class/super/in-constructor': [FAIL], - 'language/class/super/in-getter': [FAIL], - 'language/class/super/in-methods': [FAIL], - 'language/class/super/in-setter': [FAIL], - 'language/class/super/in-static-getter': [FAIL], - 'language/class/super/in-static-methods': [FAIL], - 'language/class/super/in-static-setter': [FAIL], - 'language/expressions/assignment/S11.13.1_A5_T1': [FAIL], - 'language/expressions/assignment/S11.13.1_A5_T2': [FAIL], - 'language/expressions/assignment/S11.13.1_A5_T3': [FAIL], - 'language/expressions/assignment/S11.13.1_A5_T4': [FAIL], - 'language/expressions/assignment/S11.13.1_A5_T5': [FAIL], - 'language/expressions/assignment/S11.13.1_A6_T1': [FAIL], - 'language/expressions/assignment/S11.13.1_A6_T2': [FAIL], - 'language/expressions/assignment/S11.13.1_A6_T3': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.10_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.10_T2': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.10_T3': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.10_T4': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.10_T5': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.11_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.11_T2': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.11_T3': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.11_T4': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.11_T5': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.1_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.1_T2': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.1_T3': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.1_T4': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.1_T5': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.2_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.2_T2': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.2_T3': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.2_T4': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.2_T5': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.3_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.3_T2': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.3_T3': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.3_T4': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.3_T5': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.4_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.4_T2': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.4_T3': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.4_T4': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.4_T5': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.5_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.5_T2': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.5_T3': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.5_T4': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.5_T5': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.6_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.6_T2': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.6_T3': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.6_T4': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.6_T5': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.7_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.7_T2': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.7_T3': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.7_T4': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.7_T5': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.8_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.8_T2': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.8_T3': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.8_T4': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.8_T5': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.9_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.9_T2': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.9_T3': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.9_T4': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A5.9_T5': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A6.10_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A6.11_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A6.1_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A6.2_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A6.3_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A6.4_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A6.5_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A6.6_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A6.7_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A6.8_T1': [FAIL], - 'language/expressions/compound-assignment/S11.13.2_A6.9_T1': [FAIL], - 'language/expressions/postfix-decrement/S11.3.2_A5_T1': [FAIL], - 'language/expressions/postfix-decrement/S11.3.2_A5_T2': [FAIL], - 'language/expressions/postfix-decrement/S11.3.2_A5_T3': [FAIL], - 'language/expressions/postfix-decrement/S11.3.2_A5_T4': [FAIL], - 'language/expressions/postfix-decrement/S11.3.2_A5_T5': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=3088 + 'built-ins/Symbol/auto-boxing-strict': [FAIL], + + # The order of adding the name property is wrong + # https://code.google.com/p/v8/issues/detail?id=4199 + 'language/computed-property-names/class/static/method-number': [FAIL, FAIL_SLOPPY], + 'language/computed-property-names/class/static/method-symbol': [FAIL, FAIL_SLOPPY], + 'language/computed-property-names/class/static/method-string': [FAIL, FAIL_SLOPPY], + + # new.target + # https://code.google.com/p/v8/issues/detail?id=3887 + 'language/expressions/arrow-function/lexical-new.target': [FAIL], + 'language/expressions/arrow-function/lexical-new.target-closure-returned': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=2160 + 'language/expressions/arrow-function/syntax/arrowparameters-cover-initialize-1': [FAIL], + 'language/expressions/arrow-function/syntax/arrowparameters-cover-initialize-2': [FAIL], + 'language/expressions/object/method-definition/generator-super-prop-param': [FAIL], + 'language/expressions/object/method-definition/name-param-init-yield': [FAIL], + 'language/expressions/object/method-definition/name-super-prop-param': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=3673 + 'language/statements/class/definition/basics': [FAIL], + + # Destructuring + # https://code.google.com/p/v8/issues/detail?id=811 + 'language/statements/for-of/body-dstr-assign': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=3566 + 'language/statements/for-of/body-dstr-assign-error': [FAIL], + 'language/statements/for-of/body-put-error': [FAIL], + 'language/statements/for-of/generator-close-via-break': [FAIL], + 'language/statements/for-of/generator-close-via-return': [FAIL], + 'language/statements/for-of/generator-close-via-throw': [FAIL], + 'language/statements/for-of/iterator-close-get-method-error': [FAIL], + 'language/statements/for-of/iterator-close-non-object': [FAIL], + 'language/statements/for-of/iterator-close-via-break': [FAIL], + 'language/statements/for-of/iterator-close-via-return': [FAIL], + 'language/statements/for-of/iterator-close-via-throw': [FAIL], + + # We do not expose Array.prototype.values + # https://code.google.com/p/v8/issues/detail?id=4247 + 'built-ins/Array/prototype/Symbol.iterator': [FAIL], + + #https://code.google.com/p/v8/issues/detail?id=3983 + 'language/expressions/generators/yield-as-function-expression-binding-identifier': [FAIL], + 'language/expressions/generators/yield-as-generator-expression-binding-identifier': [FAIL], + 'language/expressions/object/method-definition/generator-argSuperProperty': [FAIL], + 'language/expressions/object/method-definition/yield-as-function-expression-binding-identifier': [FAIL], + 'language/statements/generators/yield-as-function-expression-binding-identifier': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=3566 + 'built-ins/GeneratorPrototype/return/from-state-completed': [FAIL], + 'built-ins/GeneratorPrototype/return/from-state-suspended-start': [FAIL], + 'built-ins/GeneratorPrototype/return/property-descriptor': [FAIL], + 'built-ins/GeneratorPrototype/return/try-catch-before-try': [FAIL], + 'built-ins/GeneratorPrototype/return/try-catch-following-catch': [FAIL], + 'built-ins/GeneratorPrototype/return/try-catch-within-catch': [FAIL], + 'built-ins/GeneratorPrototype/return/try-catch-within-try': [FAIL], + 'built-ins/GeneratorPrototype/return/try-finally-before-try': [FAIL], + 'built-ins/GeneratorPrototype/return/try-finally-following-finally': [FAIL], + 'built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-catch': [FAIL], + 'built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-finally': [FAIL], + 'built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-inner-try': [FAIL], + 'built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-outer-try-after-nested': [FAIL], + 'built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-outer-try-before-nested': [FAIL], + 'built-ins/GeneratorPrototype/return/try-finally-within-finally': [FAIL], + 'built-ins/GeneratorPrototype/return/try-finally-within-try': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4177 + 'language/arguments-object/mapped/mapped-arguments-nonconfigurable-2': [FAIL], + 'language/arguments-object/mapped/mapped-arguments-nonconfigurable-3': [FAIL], + 'language/arguments-object/mapped/mapped-arguments-nonconfigurable-4': [FAIL], + 'language/arguments-object/mapped/mapped-arguments-nonconfigurable-delete-2': [FAIL], + 'language/arguments-object/mapped/mapped-arguments-nonconfigurable-delete-3': [FAIL], + 'language/arguments-object/mapped/mapped-arguments-nonconfigurable-delete-4': [FAIL], + 'language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-3': [FAIL], + 'language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-4': [FAIL], + 'language/arguments-object/mapped/mapped-arguments-nonconfigurable-nonwritable-5': [FAIL], + 'language/arguments-object/mapped/mapped-arguments-nonconfigurable-strict-delete-2': [FAIL], + 'language/arguments-object/mapped/mapped-arguments-nonconfigurable-strict-delete-3': [FAIL], + 'language/arguments-object/mapped/mapped-arguments-nonconfigurable-strict-delete-4': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=811 + 'language/expressions/assignment/destructuring/array-elem-elision': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-init-assignment': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-init-evaluation': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-init-in': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-init-let': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-init-order': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-init-simple-no-strict': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-init-yield-expr': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-init-yield-ident-valid': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-nested-array': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-nested-array-null': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-nested-array-undefined': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-nested-array-undefined-hole': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-nested-array-undefined-own': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-nested-array-yield-expr': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-nested-array-yield-ident-valid': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-nested-obj': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-nested-obj-null': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-nested-obj-undefined': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-nested-obj-undefined-hole': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-nested-obj-undefined-own': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-nested-obj-yield-expr': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-nested-obj-yield-ident-valid': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-put-const': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-put-let': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-put-prop-ref': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-put-prop-ref-no-get': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-put-prop-ref-user-err': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-put-unresolvable-no-strict': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-put-unresolvable-strict': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-target-identifier': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-target-simple-no-strict': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-target-yield-expr': [FAIL], + 'language/expressions/assignment/destructuring/array-elem-target-yield-valid': [FAIL], + 'language/expressions/assignment/destructuring/array-empty': [FAIL], + 'language/expressions/assignment/destructuring/array-iteration': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-after-element': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-after-elision': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-elision': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-iteration': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-nested-array': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-nested-array-null': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-nested-array-undefined': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-nested-array-undefined-hole': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-nested-array-undefined-own': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-nested-array-yield-expr': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-nested-array-yield-ident-valid': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-nested-obj': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-nested-obj-null': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-nested-obj-undefined': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-nested-obj-undefined-hole': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-nested-obj-undefined-own': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-nested-obj-yield-expr': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-nested-obj-yield-ident-valid': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-put-const': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-put-let': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-put-prop-ref': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-put-prop-ref-no-get': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-put-prop-ref-user-err': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-put-unresolvable-no-strict': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-put-unresolvable-strict': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-yield-expr': [FAIL], + 'language/expressions/assignment/destructuring/array-rest-yield-ident-valid': [FAIL], + 'language/expressions/assignment/destructuring/array-sparse': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-identifier-resolution': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-identifier-yield-ident-valid': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-init-assignment': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-init-evaluation': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-init-in': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-init-let': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-init-order': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-init-simple-no-strict': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-init-yield-expr': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-init-yield-ident-valid': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-put-const': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-put-let': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-put-unresolvable-no-strict': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-put-unresolvable-strict': [FAIL], + 'language/expressions/assignment/destructuring/obj-id-simple-no-strict': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-elem-init-assignment': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-elem-init-evaluation': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-elem-init-in': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-elem-init-let': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-elem-init-yield-expr': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-elem-init-yield-ident-valid': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-elem-target-yield-expr': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-elem-target-yield-ident-valid': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-identifier-resolution': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-name-evaluation': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-name-evaluation-error': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-nested-array': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-nested-array-null': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-nested-array-undefined': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-nested-array-undefined-own': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-nested-array-yield-expr': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-nested-array-yield-ident-valid': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-nested-obj': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-nested-obj-null': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-nested-obj-undefined': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-nested-obj-undefined-own': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-nested-obj-yield-expr': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-nested-obj-yield-ident-valid': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-put-const': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-put-let': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-put-order': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-put-prop-ref': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-put-prop-ref-no-get': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-put-prop-ref-user-err': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-put-unresolvable-no-strict': [FAIL], + 'language/expressions/assignment/destructuring/obj-prop-put-unresolvable-strict': [FAIL], + 'language/expressions/assignment/destructuring/object-empty': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4248 + 'language/expressions/compound-assignment/S11.13.2_A5.*': [FAIL], + 'language/expressions/compound-assignment/S11.13.2_A6.*': [FAIL], + 'language/expressions/compound-assignment/S11.13.2_A7.10_T4': [FAIL], + 'language/expressions/compound-assignment/S11.13.2_A7.11_T4': [FAIL], + 'language/expressions/compound-assignment/S11.13.2_A7.1_T4': [FAIL], + 'language/expressions/compound-assignment/S11.13.2_A7.2_T4': [FAIL], + 'language/expressions/compound-assignment/S11.13.2_A7.3_T4': [FAIL], + 'language/expressions/compound-assignment/S11.13.2_A7.4_T4': [FAIL], + 'language/expressions/compound-assignment/S11.13.2_A7.5_T4': [FAIL], + 'language/expressions/compound-assignment/S11.13.2_A7.6_T4': [FAIL], + 'language/expressions/compound-assignment/S11.13.2_A7.7_T4': [FAIL], + 'language/expressions/compound-assignment/S11.13.2_A7.8_T4': [FAIL], + 'language/expressions/compound-assignment/S11.13.2_A7.9_T4': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4249 + 'language/expressions/assignment/S11.13.1_A7_T1': [FAIL], + 'language/expressions/assignment/S11.13.1_A7_T2': [FAIL], + 'language/expressions/assignment/S11.13.1_A7_T3': [FAIL], + 'language/expressions/postfix-increment/S11.3.1_A6_T3': [FAIL], + 'language/expressions/postfix-decrement/S11.3.2_A6_T3': [FAIL], + 'language/expressions/prefix-decrement/S11.4.5_A6_T3': [FAIL], + 'language/expressions/prefix-increment/S11.4.4_A6_T3': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4250 + 'language/expressions/assignment/S11.13.1_A5*': [FAIL], + 'language/expressions/assignment/S11.13.1_A6*': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=3699 + 'language/expressions/generators/implicit-name': [FAIL], + 'language/expressions/generators/name-property-descriptor': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4251 'language/expressions/postfix-increment/S11.3.1_A5_T1': [FAIL], 'language/expressions/postfix-increment/S11.3.1_A5_T2': [FAIL], 'language/expressions/postfix-increment/S11.3.1_A5_T3': [FAIL], 'language/expressions/postfix-increment/S11.3.1_A5_T4': [FAIL], 'language/expressions/postfix-increment/S11.3.1_A5_T5': [FAIL], - 'language/expressions/prefix-decrement/S11.4.5_A5_T1': [FAIL], - 'language/expressions/prefix-decrement/S11.4.5_A5_T2': [FAIL], - 'language/expressions/prefix-decrement/S11.4.5_A5_T3': [FAIL], - 'language/expressions/prefix-decrement/S11.4.5_A5_T4': [FAIL], - 'language/expressions/prefix-decrement/S11.4.5_A5_T5': [FAIL], - 'language/expressions/prefix-increment/S11.4.4_A5_T1': [FAIL], - 'language/expressions/prefix-increment/S11.4.4_A5_T2': [FAIL], - 'language/expressions/prefix-increment/S11.4.4_A5_T3': [FAIL], - 'language/expressions/prefix-increment/S11.4.4_A5_T4': [FAIL], - 'language/expressions/prefix-increment/S11.4.4_A5_T5': [FAIL], - 'language/expressions/property-accessors/S11.2.1_A4_T5': [FAIL], - 'language/generators/generator.declareMethod.argSuperProperty': [FAIL], - 'language/generators/generator.declareMethod.shadow-parameter-const': [FAIL], - 'language/generators/generator.expression.implicit-name': [FAIL], - - # Test 262 update 2015-03-31 - 'built-ins/Array/prototype/concat/Array.prototype.concat_array-like': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_array-like-length-to-string-throws': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_array-like-length-value-of-throws': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_array-like-negative-length': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_array-like-primitive-non-number-length': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_array-like-string-length': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_array-like-to-length-throws': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_holey-sloppy-arguments': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_large-typed-array': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_length-throws': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_non-array': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments-throws': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_sloppy-arguments-with-dupes': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_small-typed-array': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-boolean-wrapper': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-function': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-getter-throws': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-number-wrapper': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-reg-exp': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-sparse-object': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-string-wrapper': [FAIL], - 'built-ins/Array/prototype/concat/Array.prototype.concat_strict-arguments': [FAIL], - 'built-ins/Symbol/species/Symbol.species.builtin-getter-name': [FAIL], - 'built-ins/Symbol/species/Symbol.species.exists': [FAIL], - 'built-ins/Symbol/species/Symbol.species.in_Array': [FAIL], - 'built-ins/Symbol/species/Symbol.species.in_ArrayBuffer': [FAIL], - 'built-ins/Symbol/species/Symbol.species.in_Map': [FAIL], - 'built-ins/Symbol/species/Symbol.species.in_Promise': [FAIL], - 'built-ins/Symbol/species/Symbol.species.in_RegExp': [FAIL], - 'built-ins/Symbol/species/Symbol.species.in_Set': [FAIL], - 'built-ins/Symbol/species/Symbol.species.notChangedByExtends': [FAIL], + 'language/expressions/postfix-decrement/S11.3.2_A5_*': [FAIL], + 'language/expressions/prefix-decrement/S11.4.5_A5_*': [FAIL], + 'language/expressions/prefix-increment/S11.4.4_A5_*': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=4253 'language/asi/S7.9_A5.7_T1': [PASS, FAIL_OK], - 'language/block-scope/leave/finally-block-let-declaration-only-shadows-outer-parameter-value-1': [FAIL], - 'language/block-scope/leave/finally-block-let-declaration-only-shadows-outer-parameter-value-2': [FAIL], - 'language/block-scope/leave/for-loop-block-let-declaration-only-shadows-outer-parameter-value-1': [FAIL], - 'language/block-scope/leave/for-loop-block-let-declaration-only-shadows-outer-parameter-value-2': [FAIL], - 'language/block-scope/leave/nested-block-let-declaration-only-shadows-outer-parameter-value-1': [FAIL], - 'language/block-scope/leave/nested-block-let-declaration-only-shadows-outer-parameter-value-2': [FAIL], - 'language/block-scope/leave/outermost-binding-updated-in-catch-block-nested-block-let-declaration-unseen-outside-of-block': [FAIL], - 'language/block-scope/leave/try-block-let-declaration-only-shadows-outer-parameter-value-1': [FAIL], - 'language/block-scope/leave/try-block-let-declaration-only-shadows-outer-parameter-value-2': [FAIL], - 'language/block-scope/leave/verify-context-in-finally-block': [FAIL], - 'language/block-scope/leave/verify-context-in-for-loop-block': [FAIL], - 'language/block-scope/leave/verify-context-in-labelled-block': [FAIL], - 'language/block-scope/leave/verify-context-in-try-block': [FAIL], - 'language/block-scope/leave/x-after-break-to-label': [FAIL], - 'language/block-scope/leave/x-before-continue': [FAIL], - 'language/block-scope/return-from/block-let': [FAIL], - 'language/block-scope/semantics/const/block-local-closure-get-before-initialization': [FAIL], - 'language/block-scope/semantics/const/block-local-use-before-initialization-in-declaration-statement': [FAIL], - 'language/block-scope/semantics/const/block-local-use-before-initialization-in-prior-statement': [FAIL], - 'language/block-scope/semantics/const/function-local-closure-get-before-initialization': [FAIL], - 'language/block-scope/semantics/const/function-local-use-before-initialization-in-declaration-statement': [FAIL], - 'language/block-scope/semantics/const/function-local-use-before-initialization-in-prior-statement': [FAIL], - 'language/block-scope/semantics/const/global-closure-get-before-initialization': [FAIL], - 'language/block-scope/semantics/const/global-use-before-initialization-in-declaration-statement': [FAIL], - 'language/block-scope/semantics/const/global-use-before-initialization-in-prior-statement': [FAIL], - 'language/block-scope/shadowing/catch-parameter-shadowing-let-declaration': [FAIL], - 'language/block-scope/shadowing/const-declaration-shadowing-catch-parameter': [FAIL], - 'language/block-scope/shadowing/const-declarations-shadowing-parameter-name-let-const-and-var-variables': [FAIL], - 'language/block-scope/shadowing/dynamic-lookup-from-closure': [FAIL], - 'language/block-scope/shadowing/dynamic-lookup-in-and-through-block-contexts': [FAIL], - 'language/block-scope/shadowing/let-declaration-shadowing-catch-parameter': [FAIL], - 'language/block-scope/shadowing/let-declarations-shadowing-parameter-name-let-const-and-var': [FAIL], - 'language/block-scope/shadowing/lookup-from-closure': [FAIL], - 'language/block-scope/shadowing/lookup-in-and-through-block-contexts': [FAIL], - 'language/block-scope/shadowing/parameter-name-shadowing-parameter-name-let-const-and-var': [FAIL], - 'language/block-scope/syntax/const-declaration/block-scope-syntax-const-declarations-mixed-with-without-initialiser': [FAIL], - 'language/block-scope/syntax/const-declaration/block-scope-syntax-const-declarations-mixed-without-with-initialiser': [FAIL], - 'language/block-scope/syntax/const-declaration/block-scope-syntax-const-declarations-without-initialiser': [FAIL], - 'language/block-scope/syntax/const-declaration/with-initializer-do-statement-while-expression': [FAIL], - 'language/block-scope/syntax/const-declaration/with-initializer-for-statement': [FAIL], - 'language/block-scope/syntax/const-declaration/with-initializer-if-expression-statement': [FAIL], - 'language/block-scope/syntax/const-declaration/with-initializer-if-expression-statement-else-statement': [FAIL], - 'language/block-scope/syntax/const-declaration/with-initializer-label-statement': [FAIL], - 'language/block-scope/syntax/const-declaration/with-initializer-while-expression-statement': [FAIL], - 'language/block-scope/syntax/const-declaration/without-initializer-case-expression-statement-list': [FAIL], - 'language/block-scope/syntax/const-declaration/without-initializer-default-statement-list': [FAIL], - 'language/block-scope/syntax/const-declaration/without-initializer-do-statement-while-expression': [FAIL], - 'language/block-scope/syntax/const-declaration/without-initializer-for-statement': [FAIL], - 'language/block-scope/syntax/const-declaration/without-initializer-if-expression-statement': [FAIL], - 'language/block-scope/syntax/const-declaration/without-initializer-if-expression-statement-else-statement': [FAIL], - 'language/block-scope/syntax/const-declaration/without-initializer-label-statement': [FAIL], - 'language/block-scope/syntax/const-declaration/without-initializer-while-expression-statement': [FAIL], - 'language/block-scope/syntax/for-in/acquire-properties-from-array': [FAIL], - 'language/block-scope/syntax/for-in/acquire-properties-from-object': [FAIL], - 'language/block-scope/syntax/for-in/missing-identifier-let-disallowed-as-bound-name': [FAIL], - 'language/block-scope/syntax/for-loop/const-invalid-assignment-next-expression': [SKIP], # iloops - 'language/block-scope/syntax/for-loop/const-outer-inner-let-bindings': [FAIL], - 'language/block-scope/syntax/for-loop/let-closure-inside-condition': [FAIL], - 'language/block-scope/syntax/for-loop/let-closure-inside-initialization': [FAIL], - 'language/block-scope/syntax/for-loop/let-closure-inside-next-expression': [FAIL], - 'language/block-scope/syntax/for-loop/let-iteration-variable-is-freshly-allocated-for-each-iteration-multi-let-binding': [FAIL], - 'language/block-scope/syntax/for-loop/let-iteration-variable-is-freshly-allocated-for-each-iteration-single-let-binding': [FAIL], - 'language/block-scope/syntax/for-loop/let-outer-inner-let-bindings': [FAIL], - 'language/block-scope/syntax/function-declarations/in-statement-position-do-statement-while-expression': [FAIL], - 'language/block-scope/syntax/function-declarations/in-statement-position-for-statement': [FAIL], - 'language/block-scope/syntax/function-declarations/in-statement-position-if-expression-statement': [FAIL], - 'language/block-scope/syntax/function-declarations/in-statement-position-if-expression-statement-else-statement': [FAIL], - 'language/block-scope/syntax/function-declarations/in-statement-position-while-expression-statement': [FAIL], - 'language/block-scope/syntax/global-and-block/const': [FAIL], - 'language/block-scope/syntax/global-and-block/let': [FAIL], - 'language/block-scope/syntax/let-declarations/with-initialisers-in-statement-positions-case-expression-statement-list': [FAIL], - 'language/block-scope/syntax/let-declarations/with-initialisers-in-statement-positions-default-statement-list': [FAIL], - 'language/block-scope/syntax/redeclaration-in-block/attempt-to-redeclare-function-declaration-with-function-declaration': [FAIL], - 'language/block-scope/syntax/redeclaration-in-block/attempt-to-redeclare-function-declaration-with-var': [FAIL], - 'language/block-scope/syntax/redeclaration-in-block/attempt-to-redeclare-var-with-function-declaration': [FAIL], - 'language/computed-property-names/class/method/constructor-can-be-generator': [FAIL], - 'language/computed-property-names/class/method/constructor-can-be-getter': [FAIL], - 'language/computed-property-names/class/method/constructor-can-be-setter': [FAIL], - 'language/computed-property-names/class/method/constructor-duplicate-1': [FAIL], - 'language/computed-property-names/class/method/constructor-duplicate-2': [FAIL], - 'language/computed-property-names/class/method/constructor-duplicate-3': [FAIL], - 'language/computed-property-names/class/static/generator-constructor': [FAIL], - 'language/computed-property-names/class/static/generator-prototype': [FAIL], - 'language/computed-property-names/class/static/getter-constructor': [FAIL], - 'language/computed-property-names/class/static/getter-prototype': [FAIL], - 'language/computed-property-names/class/static/method-constructor': [FAIL], - 'language/computed-property-names/class/static/method-prototype': [FAIL], - 'language/computed-property-names/class/static/setter-constructor': [FAIL], - 'language/computed-property-names/class/static/setter-prototype': [FAIL], - 'language/for-of/iterator-as-proxy': [FAIL], - 'language/for-of/iterator-next-result-type': [FAIL], + + # https://code.google.com/p/v8/issues/detail?id=3761 + 'language/expressions/object/method-definition/generator-name-prop-symbol': [FAIL], + 'language/expressions/object/method-definition/name-name-prop-symbol': [FAIL], + + ######################## NEEDS INVESTIGATION ########################### + + # These test failures are specific to the intl402 suite and need investigation + # to be either marked as bugs with issues filed for them or as deliberate + # incompatibilities if the test cases turn out to be broken or ambiguous. + 'intl402/6.2.3': [FAIL], + 'intl402/9.2.1_2': [FAIL], + 'intl402/9.2.6_2': [FAIL], + 'intl402/10.1.1_a': [FAIL], + 'intl402/10.1.2.1_4': [FAIL], + 'intl402/10.1.2_a': [PASS, FAIL], + 'intl402/10.2.3_b': [PASS, FAIL], + 'intl402/10.3.2_1_c': [PASS, FAIL], + 'intl402/10.3.2_CS_b_NN': [PASS, FAIL], + 'intl402/10.3.2_CS_c_NN': [PASS, FAIL], + 'intl402/10.3.2_CS_d_NN': [PASS, FAIL], + 'intl402/10.3_a': [FAIL], + 'intl402/11.1.1_20_c': [FAIL], + 'intl402/11.1.1_a': [FAIL], + 'intl402/11.1.2': [PASS, FAIL], + 'intl402/11.1.2.1_4': [FAIL], + 'intl402/11.3_a': [FAIL], + 'intl402/12.1.1_a': [FAIL], + 'intl402/12.1.2': [PASS, FAIL], + 'intl402/12.1.2.1_4': [FAIL], + 'intl402/12.3.2_FDT_7_a_iv': [FAIL], + 'intl402/12.3.3': [FAIL], + 'intl402/12.3_a': [FAIL], + 'intl402/13.1.1_7': [PASS, FAIL], + 'intl402/13.2.1_5': [PASS, FAIL], + 'intl402/13.3.0_7': [PASS, FAIL], + + # These tests fail in nosnap in strict mode + # https://code.google.com/p/v8/issues/detail?id=4198 + 'built-ins/String/S15.5.1.1_A1_T6': [PASS, FAIL_OK], + 'built-ins/eval/S15.1.2.1_A1.1_T1': [PASS, FAIL_OK], + 'built-ins/eval/S15.1.2.1_A1.1_T2': [PASS, FAIL_OK], + 'built-ins/eval/S15.1.2.1_A4.3': [PASS, FAIL_OK], + 'built-ins/eval/S15.1.2.1_A4.4': [PASS, FAIL_OK], + 'language/eval-code/10.4.2-1-1': [PASS, FAIL_OK], + 'language/eval-code/10.4.2-1-2': [PASS, FAIL_OK], + 'language/eval-code/10.4.2-1-3': [PASS, FAIL_OK], + 'language/eval-code/10.4.2-1-5': [PASS, FAIL_OK], + 'language/eval-code/S10.4.2.1_A1': [PASS, FAIL_OK], + 'language/function-code/10.4.3-1-19-s': [PASS, FAIL_OK], + 'language/function-code/10.4.3-1-19gs': [PASS, FAIL_OK], + 'language/function-code/10.4.3-1-20-s': [PASS, FAIL_OK], + 'language/function-code/10.4.3-1-20gs': [PASS, FAIL_OK], + 'language/statements/variable/12.2.1-10-s': [PASS, FAIL_OK], + 'language/statements/variable/12.2.1-20-s': [PASS, FAIL_OK], + 'language/statements/variable/12.2.1-21-s': [PASS, FAIL_OK], + 'language/statements/variable/12.2.1-9-s': [PASS, FAIL_OK], ##################### DELIBERATE INCOMPATIBILITIES ##################### @@ -614,38 +767,25 @@ 'built-ins/Object/keys/15.2.3.14-1-2': [PASS, FAIL_OK], 'built-ins/Object/keys/15.2.3.14-1-3': [PASS, FAIL_OK], - # # String.prototype.contains renamed to 'S.p.includes' - # 'es6/String.prototype.contains/String.prototype.contains_FailBadLocation' : [FAIL_OK], - # 'es6/String.prototype.contains/String.prototype.contains_FailLocation' : [FAIL_OK], - # 'es6/String.prototype.contains/String.prototype.contains_FailMissingLetter' : [FAIL_OK], - # 'es6/String.prototype.contains/String.prototype.contains_lengthProp' : [FAIL_OK], - # 'es6/String.prototype.contains/String.prototype.contains_Success' : [FAIL_OK], - # 'es6/String.prototype.contains/String.prototype.contains_SuccessNoLocation' : [FAIL_OK], - - # Function restricted "caller" and "arguments" properties are defined only on - # the intrinsic %FunctionPrototype% (and sloppy functions) in ES6 - 'language/statements/function/13.2-29-s': [FAIL_OK], - 'language/statements/function/13.2-30-s': [FAIL_OK], - 'language/statements/function/13.2-31-s': [FAIL_OK], - 'language/statements/function/13.2-32-s': [FAIL_OK], - 'language/statements/function/13.2-33-s': [FAIL_OK], - 'language/statements/function/13.2-34-s': [FAIL_OK], - 'language/statements/function/13.2-35-s': [FAIL_OK], - 'language/statements/function/13.2-36-s': [FAIL_OK], - 'language/statements/function/S13.2.3_A1': [FAIL_OK], - 'built-ins/Function/prototype/bind/15.3.4.5-20-1': [FAIL_OK], - 'built-ins/Function/prototype/bind/15.3.4.5-20-4': [FAIL_OK], - 'built-ins/Function/prototype/bind/15.3.4.5-20-5': [FAIL_OK], - 'built-ins/Function/prototype/bind/15.3.4.5-21-1': [FAIL_OK], - 'built-ins/Function/prototype/bind/15.3.4.5-21-4': [FAIL_OK], - 'built-ins/Function/prototype/bind/15.3.4.5-21-5': [FAIL_OK], - - ############################ SKIPPED TESTS ############################# - # These tests take a looong time to run in debug mode. - 'built-ins/decodeURI/S15.1.3.1_A2.5_T1': [PASS, ['mode == debug', SKIP]], - 'built-ins/decodeURIComponent/S15.1.3.2_A2.5_T1': [PASS, ['mode == debug', SKIP]], + # These tests take a looong time to run. + 'built-ins/decodeURI/S15.1.3.1_A1.10_T1': [SKIP], + 'built-ins/decodeURI/S15.1.3.1_A1.11_T1': [SKIP], + 'built-ins/decodeURI/S15.1.3.1_A1.11_T2': [SKIP], + 'built-ins/decodeURI/S15.1.3.1_A1.12_T1': [SKIP], + 'built-ins/decodeURI/S15.1.3.1_A1.12_T2': [SKIP], + 'built-ins/decodeURI/S15.1.3.1_A2.5_T1': [SKIP], + 'built-ins/decodeURIComponent/S15.1.3.2_A1.11_T1': [SKIP], + 'built-ins/decodeURIComponent/S15.1.3.2_A1.12_T1': [SKIP], + 'built-ins/decodeURIComponent/S15.1.3.2_A2.5_T1': [SKIP], + 'built-ins/RegExp/S15.10.2.12_A3_T1': [SKIP], + 'intl402/9.2.6_4_b': [SKIP], + 'language/literals/regexp/S7.8.5_A1.1_T2': [SKIP], + 'language/literals/regexp/S7.8.5_A1.4_T2': [SKIP], + 'language/literals/regexp/S7.8.5_A2.1_T2': [SKIP], + 'language/literals/regexp/S7.8.5_A2.4_T2': [SKIP], + 'language/statements/const/syntax/const-invalid-assignment-next-expression-for': [SKIP], }], # ALWAYS ['system == macos', { diff --git a/deps/v8/test/test262-es6/testcfg.py b/deps/v8/test/test262-es6/testcfg.py index 0519dc0e0e..91491b3907 100644 --- a/deps/v8/test/test262-es6/testcfg.py +++ b/deps/v8/test/test262-es6/testcfg.py @@ -33,12 +33,14 @@ import sys import tarfile import imp +from testrunner.local import statusfile from testrunner.local import testsuite from testrunner.local import utils from testrunner.objects import testcase -TEST_262_ARCHIVE_REVISION = "43acf61" # This is the 2015-03-31 revision. -TEST_262_ARCHIVE_MD5 = "a77a0352a0462be98e50522a15b7a3c4" +# The revision hash needs to be 7 characters? +TEST_262_ARCHIVE_REVISION = "c6ac390" # This is the 2015-07-06 revision. +TEST_262_ARCHIVE_MD5 = "e1393ef330f38e9cb1bfa4e3eada5ba8" TEST_262_URL = "https://github.com/tc39/test262/tarball/%s" TEST_262_HARNESS_FILES = ["sta.js", "assert.js"] @@ -79,6 +81,16 @@ class Test262TestSuite(testsuite.TestSuite): self.GetIncludesForTest(testcase) + ["--harmony"] + [os.path.join(self.testroot, testcase.path + ".js")]) + def VariantFlags(self, testcase, default_flags): + flags = super(Test262TestSuite, self).VariantFlags(testcase, default_flags) + test_record = self.GetTestRecord(testcase) + if "noStrict" in test_record: + return flags + strict_flags = [f + ["--use-strict"] for f in flags] + if "onlyStrict" in test_record: + return strict_flags + return flags + strict_flags + def LoadParseTestRecord(self): if not self.ParseTestRecord: root = os.path.join(self.root, *TEST_262_TOOLS_PATH) @@ -125,12 +137,30 @@ class Test262TestSuite(testsuite.TestSuite): return True return "FAILED!" in output.stdout + def HasUnexpectedOutput(self, testcase): + outcome = self.GetOutcome(testcase) + if (statusfile.FAIL_SLOPPY in testcase.outcomes and + "--use-strict" not in testcase.flags): + return outcome != statusfile.FAIL + return not outcome in (testcase.outcomes or [statusfile.PASS]) + def DownloadData(self): revision = TEST_262_ARCHIVE_REVISION archive_url = TEST_262_URL % revision archive_name = os.path.join(self.root, "tc39-test262-%s.tar.gz" % revision) directory_name = os.path.join(self.root, "data") directory_old_name = os.path.join(self.root, "data.old") + + # Clobber if the test is in an outdated state, i.e. if there are any other + # archive files present. + archive_files = [f for f in os.listdir(self.root) + if f.startswith("tc39-test262-")] + if (len(archive_files) > 1 or + os.path.basename(archive_name) not in archive_files): + print "Clobber outdated test archives ..." + for f in archive_files: + os.remove(os.path.join(self.root, f)) + if not os.path.exists(archive_name): print "Downloading test data from %s ..." % archive_url utils.URLRetrieve(archive_url, archive_name) diff --git a/deps/v8/test/test262/test262.status b/deps/v8/test/test262/test262.status index 4ae13dacdd..feed1a3206 100644 --- a/deps/v8/test/test262/test262.status +++ b/deps/v8/test/test262/test262.status @@ -36,6 +36,30 @@ '11.2.3_b': [FAIL], '12.2.3_b': [FAIL], + # BUG(v8:4267) + '15.2.3.6-4-116': [FAIL], + '15.2.3.6-4-117': [FAIL], + '15.2.3.6-4-168': [FAIL], + '15.2.3.6-4-169': [FAIL], + '15.2.3.6-4-170': [FAIL], + '15.2.3.6-4-172': [FAIL], + '15.2.3.6-4-173': [FAIL], + '15.2.3.6-4-174': [FAIL], + '15.2.3.6-4-176': [FAIL], + '15.2.3.6-4-177': [FAIL], + '15.2.3.7-6-a-112': [FAIL], + '15.2.3.7-6-a-113': [FAIL], + '15.2.3.7-6-a-164': [FAIL], + '15.2.3.7-6-a-165': [FAIL], + '15.2.3.7-6-a-166': [FAIL], + '15.2.3.7-6-a-168': [FAIL], + '15.2.3.7-6-a-169': [FAIL], + '15.2.3.7-6-a-170': [FAIL], + '15.2.3.7-6-a-172': [FAIL], + '15.2.3.7-6-a-173': [FAIL], + '15.2.3.7-6-a-175': [FAIL], + '15.2.3.7-6-a-176': [FAIL], + ############################### ES6 ################################### # ES6 allows block-local functions. 'Sbp_A1_T1': [PASS, FAIL_OK], @@ -197,6 +221,7 @@ 'S15.9.5.7_A3_T2': [FAIL], 'S15.9.5.8_A3_T2': [FAIL], 'S15.9.5.9_A3_T2': [FAIL], + '15.3.4.5-15-2': [FAIL], # Object.getPrototypeOf wraps primitive values in ES6. '15.2.3.2-1': [FAIL], diff --git a/deps/v8/test/test262/testcfg.py b/deps/v8/test/test262/testcfg.py index de3c9ad7b9..a0c2cd6568 100644 --- a/deps/v8/test/test262/testcfg.py +++ b/deps/v8/test/test262/testcfg.py @@ -95,6 +95,17 @@ class Test262TestSuite(testsuite.TestSuite): archive_name = os.path.join(self.root, "tc39-test262-%s.tar.gz" % revision) directory_name = os.path.join(self.root, "data") directory_old_name = os.path.join(self.root, "data.old") + + # Clobber if the test is in an outdated state, i.e. if there are any other + # archive files present. + archive_files = [f for f in os.listdir(self.root) + if f.startswith("tc39-test262-")] + if (len(archive_files) > 1 or + os.path.basename(archive_name) not in archive_files): + print "Clobber outdated test archives ..." + for f in archive_files: + os.remove(os.path.join(self.root, f)) + if not os.path.exists(archive_name): print "Downloading test data from %s ..." % archive_url utils.URLRetrieve(archive_url, archive_name) @@ -108,8 +119,10 @@ class Test262TestSuite(testsuite.TestSuite): with open(archive_name, "rb") as f: for chunk in iter(lambda: f.read(8192), ""): md5.update(chunk) + print "MD5 hash is %s" % md5.hexdigest() if md5.hexdigest() != TEST_262_ARCHIVE_MD5: os.remove(archive_name) + print "MD5 expected %s" % TEST_262_ARCHIVE_MD5 raise Exception("Hash mismatch of test data file") archive = tarfile.open(archive_name, "r:gz") if sys.platform in ("win32", "cygwin"): diff --git a/deps/v8/test/unittests/base/bits-unittest.cc b/deps/v8/test/unittests/base/bits-unittest.cc index 9caba8484e..3d17a050db 100644 --- a/deps/v8/test/unittests/base/bits-unittest.cc +++ b/deps/v8/test/unittests/base/bits-unittest.cc @@ -255,6 +255,25 @@ TEST(Bits, SignedMod32) { } +TEST(Bits, UnsignedAddOverflow32) { + uint32_t val = 0; + EXPECT_FALSE(UnsignedAddOverflow32(0, 0, &val)); + EXPECT_EQ(0u, val); + EXPECT_TRUE( + UnsignedAddOverflow32(std::numeric_limits<uint32_t>::max(), 1u, &val)); + EXPECT_EQ(std::numeric_limits<uint32_t>::min(), val); + EXPECT_TRUE(UnsignedAddOverflow32(std::numeric_limits<uint32_t>::max(), + std::numeric_limits<uint32_t>::max(), + &val)); + TRACED_FORRANGE(uint32_t, i, 1, 50) { + TRACED_FORRANGE(uint32_t, j, 1, i) { + EXPECT_FALSE(UnsignedAddOverflow32(i, j, &val)); + EXPECT_EQ(i + j, val); + } + } +} + + TEST(Bits, UnsignedDiv32) { TRACED_FORRANGE(uint32_t, i, 0, 50) { EXPECT_EQ(0u, UnsignedDiv32(i, 0)); diff --git a/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc b/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc index 744f18f0bd..7e67b31616 100644 --- a/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc +++ b/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc @@ -47,7 +47,7 @@ Node* BuildConstant(InstructionSelectorTest::StreamBuilder& m, MachineType type, int64_t value) { switch (type) { case kMachInt32: - return m.Int32Constant(value); + return m.Int32Constant(static_cast<int32_t>(value)); break; case kMachInt64: @@ -642,7 +642,9 @@ TEST_F(InstructionSelectorTest, AddShiftByImmediateOnLeft) { if (shift.mi.machine_type != kMachInt32) continue; if (shift.mi.arch_opcode == kArm64Ror32) continue; - TRACED_FORRANGE(int, imm, 0, 31) { + // The available shift operand range is `0 <= imm < 32`, but we also test + // that immediates outside this range are handled properly (modulo-32). + TRACED_FORRANGE(int, imm, -32, 63) { StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); m.Return((m.Int32Add)( (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)), @@ -663,7 +665,9 @@ TEST_F(InstructionSelectorTest, AddShiftByImmediateOnLeft) { if (shift.mi.machine_type != kMachInt64) continue; if (shift.mi.arch_opcode == kArm64Ror) continue; - TRACED_FORRANGE(int, imm, 0, 63) { + // The available shift operand range is `0 <= imm < 64`, but we also test + // that immediates outside this range are handled properly (modulo-64). + TRACED_FORRANGE(int, imm, -64, 127) { StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64); m.Return((m.Int64Add)( (m.*shift.mi.constructor)(m.Parameter(1), m.Int64Constant(imm)), @@ -1641,6 +1645,102 @@ TEST_F(InstructionSelectorTest, Int32MulWithImmediate) { EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); EXPECT_EQ(1U, s[0]->OutputCount()); } + // x * (2^k + 1) + c -> x + (x << k) + c + TRACED_FORRANGE(int32_t, k, 1, 30) { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + m.Return( + m.Int32Add(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1)), + m.Parameter(1))); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kArm64Add32, s[0]->arch_opcode()); + EXPECT_EQ(kArm64Add32, s[1]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); + EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); + EXPECT_EQ(1U, s[0]->OutputCount()); + } + // (2^k + 1) * x + c -> x + (x << k) + c + TRACED_FORRANGE(int32_t, k, 1, 30) { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + m.Return( + m.Int32Add(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0)), + m.Parameter(1))); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kArm64Add32, s[0]->arch_opcode()); + EXPECT_EQ(kArm64Add32, s[1]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); + EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); + EXPECT_EQ(1U, s[0]->OutputCount()); + } + // c + x * (2^k + 1) -> c + x + (x << k) + TRACED_FORRANGE(int32_t, k, 1, 30) { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + m.Return( + m.Int32Add(m.Parameter(0), + m.Int32Mul(m.Parameter(1), m.Int32Constant((1 << k) + 1)))); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kArm64Add32, s[0]->arch_opcode()); + EXPECT_EQ(kArm64Add32, s[1]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1))); + EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); + EXPECT_EQ(1U, s[0]->OutputCount()); + } + // c + (2^k + 1) * x -> c + x + (x << k) + TRACED_FORRANGE(int32_t, k, 1, 30) { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + m.Return( + m.Int32Add(m.Parameter(0), + m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(1)))); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kArm64Add32, s[0]->arch_opcode()); + EXPECT_EQ(kArm64Add32, s[1]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1))); + EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); + EXPECT_EQ(1U, s[0]->OutputCount()); + } + // c - x * (2^k + 1) -> c - x + (x << k) + TRACED_FORRANGE(int32_t, k, 1, 30) { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + m.Return( + m.Int32Sub(m.Parameter(0), + m.Int32Mul(m.Parameter(1), m.Int32Constant((1 << k) + 1)))); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kArm64Add32, s[0]->arch_opcode()); + EXPECT_EQ(kArm64Sub32, s[1]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1))); + EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); + EXPECT_EQ(1U, s[0]->OutputCount()); + } + // c - (2^k + 1) * x -> c - x + (x << k) + TRACED_FORRANGE(int32_t, k, 1, 30) { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + m.Return( + m.Int32Sub(m.Parameter(0), + m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(1)))); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kArm64Add32, s[0]->arch_opcode()); + EXPECT_EQ(kArm64Sub32, s[1]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[0]->InputAt(1))); + EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); + EXPECT_EQ(1U, s[0]->OutputCount()); + } } @@ -1671,6 +1771,102 @@ TEST_F(InstructionSelectorTest, Int64MulWithImmediate) { EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2))); EXPECT_EQ(1U, s[0]->OutputCount()); } + // x * (2^k + 1) + c -> x + (x << k) + c + TRACED_FORRANGE(int64_t, k, 1, 62) { + StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64); + m.Return( + m.Int64Add(m.Int64Mul(m.Parameter(0), m.Int64Constant((1L << k) + 1)), + m.Parameter(1))); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kArm64Add, s[0]->arch_opcode()); + EXPECT_EQ(kArm64Add, s[1]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); + EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2))); + EXPECT_EQ(1U, s[0]->OutputCount()); + } + // (2^k + 1) * x + c -> x + (x << k) + c + TRACED_FORRANGE(int64_t, k, 1, 62) { + StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64); + m.Return( + m.Int64Add(m.Int64Mul(m.Int64Constant((1L << k) + 1), m.Parameter(0)), + m.Parameter(1))); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kArm64Add, s[0]->arch_opcode()); + EXPECT_EQ(kArm64Add, s[1]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); + EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2))); + EXPECT_EQ(1U, s[0]->OutputCount()); + } + // c + x * (2^k + 1) -> c + x + (x << k) + TRACED_FORRANGE(int64_t, k, 1, 62) { + StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64); + m.Return( + m.Int64Add(m.Parameter(0), + m.Int64Mul(m.Parameter(1), m.Int64Constant((1L << k) + 1)))); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kArm64Add, s[0]->arch_opcode()); + EXPECT_EQ(kArm64Add, s[1]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); + EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2))); + EXPECT_EQ(1U, s[0]->OutputCount()); + } + // c + (2^k + 1) * x -> c + x + (x << k) + TRACED_FORRANGE(int64_t, k, 1, 62) { + StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64); + m.Return( + m.Int64Add(m.Parameter(0), + m.Int64Mul(m.Int64Constant((1L << k) + 1), m.Parameter(1)))); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kArm64Add, s[0]->arch_opcode()); + EXPECT_EQ(kArm64Add, s[1]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); + EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2))); + EXPECT_EQ(1U, s[0]->OutputCount()); + } + // c - x * (2^k + 1) -> c - x + (x << k) + TRACED_FORRANGE(int64_t, k, 1, 62) { + StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64); + m.Return( + m.Int64Sub(m.Parameter(0), + m.Int64Mul(m.Parameter(1), m.Int64Constant((1L << k) + 1)))); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kArm64Add, s[0]->arch_opcode()); + EXPECT_EQ(kArm64Sub, s[1]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); + EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2))); + EXPECT_EQ(1U, s[0]->OutputCount()); + } + // c - (2^k + 1) * x -> c - x + (x << k) + TRACED_FORRANGE(int64_t, k, 1, 62) { + StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64); + m.Return( + m.Int64Sub(m.Parameter(0), + m.Int64Mul(m.Int64Constant((1L << k) + 1), m.Parameter(1)))); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kArm64Add, s[0]->arch_opcode()); + EXPECT_EQ(kArm64Sub, s[1]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); + EXPECT_EQ(k, s.ToInt64(s[0]->InputAt(2))); + EXPECT_EQ(1U, s[0]->OutputCount()); + } } @@ -2041,6 +2237,190 @@ TEST_F(InstructionSelectorTest, Word64EqualWithZero) { } +TEST_F(InstructionSelectorTest, Word32EqualWithWord32Shift) { + TRACED_FOREACH(Shift, shift, kShiftInstructions) { + // Skip non 32-bit shifts or ror operations. + if (shift.mi.machine_type != kMachInt32 || + shift.mi.arch_opcode == kArm64Ror32) { + continue; + } + + TRACED_FORRANGE(int32_t, imm, -32, 63) { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const p1 = m.Parameter(1); + Node* r = (m.*shift.mi.constructor)(p1, m.Int32Constant(imm)); + m.Return(m.Word32Equal(p0, r)); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode()); + EXPECT_EQ(shift.mode, s[0]->addressing_mode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); + EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); + ASSERT_EQ(1U, s[0]->OutputCount()); + } + TRACED_FORRANGE(int32_t, imm, -32, 63) { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const p1 = m.Parameter(1); + Node* r = (m.*shift.mi.constructor)(p1, m.Int32Constant(imm)); + m.Return(m.Word32Equal(r, p0)); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode()); + EXPECT_EQ(shift.mode, s[0]->addressing_mode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); + EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); + ASSERT_EQ(1U, s[0]->OutputCount()); + } + } +} + + +TEST_F(InstructionSelectorTest, Word32EqualWithUnsignedExtendByte) { + { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const p1 = m.Parameter(1); + Node* r = m.Word32And(p1, m.Int32Constant(0xff)); + m.Return(m.Word32Equal(p0, r)); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode()); + ASSERT_EQ(2U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); + ASSERT_EQ(1U, s[0]->OutputCount()); + } + { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const p1 = m.Parameter(1); + Node* r = m.Word32And(p1, m.Int32Constant(0xff)); + m.Return(m.Word32Equal(r, p0)); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_UXTB, s[0]->addressing_mode()); + ASSERT_EQ(2U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); + ASSERT_EQ(1U, s[0]->OutputCount()); + } +} + + +TEST_F(InstructionSelectorTest, Word32EqualWithUnsignedExtendHalfword) { + { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const p1 = m.Parameter(1); + Node* r = m.Word32And(p1, m.Int32Constant(0xffff)); + m.Return(m.Word32Equal(p0, r)); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode()); + ASSERT_EQ(2U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); + ASSERT_EQ(1U, s[0]->OutputCount()); + } + { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const p1 = m.Parameter(1); + Node* r = m.Word32And(p1, m.Int32Constant(0xffff)); + m.Return(m.Word32Equal(r, p0)); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_UXTH, s[0]->addressing_mode()); + ASSERT_EQ(2U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); + ASSERT_EQ(1U, s[0]->OutputCount()); + } +} + + +TEST_F(InstructionSelectorTest, Word32EqualWithSignedExtendByte) { + { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const p1 = m.Parameter(1); + Node* r = + m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(24)), m.Int32Constant(24)); + m.Return(m.Word32Equal(p0, r)); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode()); + ASSERT_EQ(2U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); + ASSERT_EQ(1U, s[0]->OutputCount()); + } + { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const p1 = m.Parameter(1); + Node* r = + m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(24)), m.Int32Constant(24)); + m.Return(m.Word32Equal(r, p0)); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_SXTB, s[0]->addressing_mode()); + ASSERT_EQ(2U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); + ASSERT_EQ(1U, s[0]->OutputCount()); + } +} + + +TEST_F(InstructionSelectorTest, Word32EqualWithSignedExtendHalfword) { + { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const p1 = m.Parameter(1); + Node* r = + m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(16)), m.Int32Constant(16)); + m.Return(m.Word32Equal(p0, r)); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_SXTH, s[0]->addressing_mode()); + ASSERT_EQ(2U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); + ASSERT_EQ(1U, s[0]->OutputCount()); + } + { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const p1 = m.Parameter(1); + Node* r = + m.Word32Sar(m.Word32Shl(p1, m.Int32Constant(16)), m.Int32Constant(16)); + m.Return(m.Word32Equal(r, p0)); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_SXTH, s[0]->addressing_mode()); + ASSERT_EQ(2U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); + ASSERT_EQ(1U, s[0]->OutputCount()); + } +} + + // ----------------------------------------------------------------------------- // Miscellaneous @@ -2202,14 +2582,17 @@ TEST_F(InstructionSelectorTest, Word64XorMinusOneWithParameter) { TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) { - TRACED_FORRANGE(int32_t, lsb, 1, 31) { + // The available shift operand range is `0 <= imm < 32`, but we also test + // that immediates outside this range are handled properly (modulo-32). + TRACED_FORRANGE(int32_t, shift, -32, 63) { + int32_t lsb = shift & 0x1f; TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { uint32_t jnk = rng()->NextInt(); - jnk >>= 32 - lsb; + jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0; uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk; StreamBuilder m(this, kMachInt32, kMachInt32); m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)), - m.Int32Constant(lsb))); + m.Int32Constant(shift))); Stream s = m.Build(); ASSERT_EQ(1U, s.size()); EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode()); @@ -2218,14 +2601,15 @@ TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) { EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); } } - TRACED_FORRANGE(int32_t, lsb, 1, 31) { + TRACED_FORRANGE(int32_t, shift, -32, 63) { + int32_t lsb = shift & 0x1f; TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { uint32_t jnk = rng()->NextInt(); - jnk >>= 32 - lsb; + jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0; uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk; StreamBuilder m(this, kMachInt32, kMachInt32); m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)), - m.Int32Constant(lsb))); + m.Int32Constant(shift))); Stream s = m.Build(); ASSERT_EQ(1U, s.size()); EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode()); @@ -2238,15 +2622,18 @@ TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) { TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) { - TRACED_FORRANGE(int32_t, lsb, 1, 63) { + // The available shift operand range is `0 <= imm < 64`, but we also test + // that immediates outside this range are handled properly (modulo-64). + TRACED_FORRANGE(int32_t, shift, -64, 127) { + int32_t lsb = shift & 0x3f; TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) { uint64_t jnk = rng()->NextInt64(); - jnk >>= 64 - lsb; + jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0; uint64_t msk = ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk; StreamBuilder m(this, kMachInt64, kMachInt64); m.Return(m.Word64Shr(m.Word64And(m.Parameter(0), m.Int64Constant(msk)), - m.Int64Constant(lsb))); + m.Int64Constant(shift))); Stream s = m.Build(); ASSERT_EQ(1U, s.size()); EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode()); @@ -2255,15 +2642,16 @@ TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) { EXPECT_EQ(width, s.ToInt64(s[0]->InputAt(2))); } } - TRACED_FORRANGE(int32_t, lsb, 1, 63) { + TRACED_FORRANGE(int32_t, shift, -64, 127) { + int32_t lsb = shift & 0x3f; TRACED_FORRANGE(int32_t, width, 1, 64 - lsb) { uint64_t jnk = rng()->NextInt64(); - jnk >>= 64 - lsb; + jnk = (lsb > 0) ? (jnk >> (64 - lsb)) : 0; uint64_t msk = ((V8_UINT64_C(0xffffffffffffffff) >> (64 - width)) << lsb) | jnk; StreamBuilder m(this, kMachInt64, kMachInt64); m.Return(m.Word64Shr(m.Word64And(m.Int64Constant(msk), m.Parameter(0)), - m.Int64Constant(lsb))); + m.Int64Constant(shift))); Stream s = m.Build(); ASSERT_EQ(1U, s.size()); EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode()); @@ -2276,11 +2664,14 @@ TEST_F(InstructionSelectorTest, Word64ShrWithWord64AndWithImmediate) { TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) { - TRACED_FORRANGE(int32_t, lsb, 1, 31) { + // The available shift operand range is `0 <= imm < 32`, but we also test + // that immediates outside this range are handled properly (modulo-32). + TRACED_FORRANGE(int32_t, shift, -32, 63) { + int32_t lsb = shift & 0x1f; TRACED_FORRANGE(int32_t, width, 1, 31) { uint32_t msk = (1 << width) - 1; StreamBuilder m(this, kMachInt32, kMachInt32); - m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)), + m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)), m.Int32Constant(msk))); Stream s = m.Build(); ASSERT_EQ(1U, s.size()); @@ -2291,12 +2682,14 @@ TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) { EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2))); } } - TRACED_FORRANGE(int32_t, lsb, 1, 31) { + TRACED_FORRANGE(int32_t, shift, -32, 63) { + int32_t lsb = shift & 0x1f; TRACED_FORRANGE(int32_t, width, 1, 31) { uint32_t msk = (1 << width) - 1; StreamBuilder m(this, kMachInt32, kMachInt32); - m.Return(m.Word32And(m.Int32Constant(msk), - m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)))); + m.Return( + m.Word32And(m.Int32Constant(msk), + m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)))); Stream s = m.Build(); ASSERT_EQ(1U, s.size()); EXPECT_EQ(kArm64Ubfx32, s[0]->arch_opcode()); @@ -2310,11 +2703,14 @@ TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) { TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) { - TRACED_FORRANGE(int64_t, lsb, 1, 63) { + // The available shift operand range is `0 <= imm < 64`, but we also test + // that immediates outside this range are handled properly (modulo-64). + TRACED_FORRANGE(int64_t, shift, -64, 127) { + int64_t lsb = shift & 0x3f; TRACED_FORRANGE(int64_t, width, 1, 63) { uint64_t msk = (V8_UINT64_C(1) << width) - 1; StreamBuilder m(this, kMachInt64, kMachInt64); - m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(lsb)), + m.Return(m.Word64And(m.Word64Shr(m.Parameter(0), m.Int64Constant(shift)), m.Int64Constant(msk))); Stream s = m.Build(); ASSERT_EQ(1U, s.size()); @@ -2325,12 +2721,14 @@ TEST_F(InstructionSelectorTest, Word64AndWithImmediateWithWord64Shr) { EXPECT_EQ(actual_width, s.ToInt64(s[0]->InputAt(2))); } } - TRACED_FORRANGE(int64_t, lsb, 1, 63) { + TRACED_FORRANGE(int64_t, shift, -64, 127) { + int64_t lsb = shift & 0x3f; TRACED_FORRANGE(int64_t, width, 1, 63) { uint64_t msk = (V8_UINT64_C(1) << width) - 1; StreamBuilder m(this, kMachInt64, kMachInt64); - m.Return(m.Word64And(m.Int64Constant(msk), - m.Word64Shr(m.Parameter(0), m.Int64Constant(lsb)))); + m.Return( + m.Word64And(m.Int64Constant(msk), + m.Word64Shr(m.Parameter(0), m.Int64Constant(shift)))); Stream s = m.Build(); ASSERT_EQ(1U, s.size()); EXPECT_EQ(kArm64Ubfx, s[0]->arch_opcode()); @@ -2365,6 +2763,87 @@ TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) { } +TEST_F(InstructionSelectorTest, Int32MulHighWithSar) { + TRACED_FORRANGE(int32_t, shift, -32, 63) { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const p1 = m.Parameter(1); + Node* const n = m.Word32Sar(m.Int32MulHigh(p0, p1), m.Int32Constant(shift)); + m.Return(n); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kArm64Smull, s[0]->arch_opcode()); + ASSERT_EQ(2U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); + ASSERT_EQ(1U, s[0]->OutputCount()); + EXPECT_EQ(kArm64Asr, s[1]->arch_opcode()); + ASSERT_EQ(2U, s[1]->InputCount()); + EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0))); + EXPECT_EQ((shift & 0x1f) + 32, s.ToInt64(s[1]->InputAt(1))); + ASSERT_EQ(1U, s[1]->OutputCount()); + EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output())); + } +} + + +TEST_F(InstructionSelectorTest, Int32MulHighWithAdd) { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const p1 = m.Parameter(1); + Node* const a = m.Int32Add(m.Int32MulHigh(p0, p1), p0); + // Test only one shift constant here, as we're only interested in it being a + // 32-bit operation; the shift amount is irrelevant. + Node* const n = m.Word32Sar(a, m.Int32Constant(1)); + m.Return(n); + Stream s = m.Build(); + ASSERT_EQ(3U, s.size()); + EXPECT_EQ(kArm64Smull, s[0]->arch_opcode()); + ASSERT_EQ(2U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); + ASSERT_EQ(1U, s[0]->OutputCount()); + EXPECT_EQ(kArm64Add, s[1]->arch_opcode()); + EXPECT_EQ(kMode_Operand2_R_ASR_I, s[1]->addressing_mode()); + ASSERT_EQ(3U, s[1]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[1]->InputAt(0))); + EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(1))); + EXPECT_EQ(32, s.ToInt64(s[1]->InputAt(2))); + ASSERT_EQ(1U, s[1]->OutputCount()); + EXPECT_EQ(kArm64Asr32, s[2]->arch_opcode()); + ASSERT_EQ(2U, s[2]->InputCount()); + EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(0))); + EXPECT_EQ(1, s.ToInt64(s[2]->InputAt(1))); + ASSERT_EQ(1U, s[2]->OutputCount()); + EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[2]->Output())); +} + + +TEST_F(InstructionSelectorTest, Uint32MulHighWithShr) { + TRACED_FORRANGE(int32_t, shift, -32, 63) { + StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const p1 = m.Parameter(1); + Node* const n = + m.Word32Shr(m.Uint32MulHigh(p0, p1), m.Int32Constant(shift)); + m.Return(n); + Stream s = m.Build(); + ASSERT_EQ(2U, s.size()); + EXPECT_EQ(kArm64Umull, s[0]->arch_opcode()); + ASSERT_EQ(2U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); + ASSERT_EQ(1U, s[0]->OutputCount()); + EXPECT_EQ(kArm64Lsr, s[1]->arch_opcode()); + ASSERT_EQ(2U, s[1]->InputCount()); + EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0))); + EXPECT_EQ((shift & 0x1f) + 32, s.ToInt64(s[1]->InputAt(1))); + ASSERT_EQ(1U, s[1]->OutputCount()); + EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[1]->Output())); + } +} + + TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) { TRACED_FORRANGE(int32_t, shift, 1, 31) { StreamBuilder m(this, kMachInt32, kMachInt32); @@ -2429,6 +2908,40 @@ TEST_F(InstructionSelectorTest, Word32ShrWithWord32Shl) { } +TEST_F(InstructionSelectorTest, Word32ShlWithWord32And) { + TRACED_FORRANGE(int32_t, shift, 1, 30) { + StreamBuilder m(this, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const r = + m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)), + m.Int32Constant(shift)); + m.Return(r); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kArm64Ubfiz32, s[0]->arch_opcode()); + ASSERT_EQ(3U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + ASSERT_EQ(1U, s[0]->OutputCount()); + EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); + } + TRACED_FORRANGE(int32_t, shift, 0, 30) { + StreamBuilder m(this, kMachInt32, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const r = + m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)), + m.Int32Constant(shift + 1)); + m.Return(r); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kArm64Lsl32, s[0]->arch_opcode()); + ASSERT_EQ(2U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + ASSERT_EQ(1U, s[0]->OutputCount()); + EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); + } +} + + TEST_F(InstructionSelectorTest, Word32Clz) { StreamBuilder m(this, kMachUint32, kMachUint32); Node* const p0 = m.Parameter(0); diff --git a/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc b/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc index d6822e8b09..13d2d6707a 100644 --- a/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc +++ b/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc @@ -4,14 +4,16 @@ #include "src/compiler/common-operator.h" #include "src/compiler/common-operator-reducer.h" -#include "src/compiler/js-graph.h" -#include "src/compiler/js-operator.h" #include "src/compiler/machine-operator.h" #include "src/compiler/machine-type.h" #include "src/compiler/operator.h" +#include "src/compiler/simplified-operator.h" +#include "test/unittests/compiler/graph-reducer-unittest.h" #include "test/unittests/compiler/graph-unittest.h" #include "test/unittests/compiler/node-test-utils.h" +using testing::StrictMock; + namespace v8 { namespace internal { namespace compiler { @@ -19,23 +21,30 @@ namespace compiler { class CommonOperatorReducerTest : public GraphTest { public: explicit CommonOperatorReducerTest(int num_parameters = 1) - : GraphTest(num_parameters), machine_(zone()) {} + : GraphTest(num_parameters), machine_(zone()), simplified_(zone()) {} ~CommonOperatorReducerTest() override {} protected: - Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags = - MachineOperatorBuilder::kNoFlags) { - JSOperatorBuilder javascript(zone()); + Reduction Reduce( + AdvancedReducer::Editor* editor, Node* node, + MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::kNoFlags) { MachineOperatorBuilder machine(zone(), kMachPtr, flags); - JSGraph jsgraph(isolate(), graph(), common(), &javascript, &machine); - CommonOperatorReducer reducer(&jsgraph); + CommonOperatorReducer reducer(editor, graph(), common(), &machine); return reducer.Reduce(node); } + Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags = + MachineOperatorBuilder::kNoFlags) { + StrictMock<MockAdvancedReducerEditor> editor; + return Reduce(&editor, node, flags); + } + MachineOperatorBuilder* machine() { return &machine_; } + SimplifiedOperatorBuilder* simplified() { return &simplified_; } private: MachineOperatorBuilder machine_; + SimplifiedOperatorBuilder simplified_; }; @@ -58,32 +67,213 @@ const Operator kOp0(0, Operator::kNoProperties, "Op0", 0, 0, 0, 1, 1, 0); // ----------------------------------------------------------------------------- +// Branch + + +TEST_F(CommonOperatorReducerTest, BranchWithInt32ZeroConstant) { + TRACED_FOREACH(BranchHint, hint, kBranchHints) { + Node* const control = graph()->start(); + Node* const branch = + graph()->NewNode(common()->Branch(hint), Int32Constant(0), control); + Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); + Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Replace(if_true, IsDead())); + EXPECT_CALL(editor, Replace(if_false, control)); + Reduction const r = Reduce(&editor, branch); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + } +} + + +TEST_F(CommonOperatorReducerTest, BranchWithInt32OneConstant) { + TRACED_FOREACH(BranchHint, hint, kBranchHints) { + Node* const control = graph()->start(); + Node* const branch = + graph()->NewNode(common()->Branch(hint), Int32Constant(1), control); + Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); + Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Replace(if_true, control)); + EXPECT_CALL(editor, Replace(if_false, IsDead())); + Reduction const r = Reduce(&editor, branch); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + } +} + + +TEST_F(CommonOperatorReducerTest, BranchWithInt64ZeroConstant) { + TRACED_FOREACH(BranchHint, hint, kBranchHints) { + Node* const control = graph()->start(); + Node* const branch = + graph()->NewNode(common()->Branch(hint), Int64Constant(0), control); + Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); + Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Replace(if_true, IsDead())); + EXPECT_CALL(editor, Replace(if_false, control)); + Reduction const r = Reduce(&editor, branch); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + } +} + + +TEST_F(CommonOperatorReducerTest, BranchWithInt64OneConstant) { + TRACED_FOREACH(BranchHint, hint, kBranchHints) { + Node* const control = graph()->start(); + Node* const branch = + graph()->NewNode(common()->Branch(hint), Int64Constant(1), control); + Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); + Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Replace(if_true, control)); + EXPECT_CALL(editor, Replace(if_false, IsDead())); + Reduction const r = Reduce(&editor, branch); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + } +} + + +TEST_F(CommonOperatorReducerTest, BranchWithFalseConstant) { + TRACED_FOREACH(BranchHint, hint, kBranchHints) { + Node* const control = graph()->start(); + Node* const branch = + graph()->NewNode(common()->Branch(hint), FalseConstant(), control); + Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); + Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Replace(if_true, IsDead())); + EXPECT_CALL(editor, Replace(if_false, control)); + Reduction const r = Reduce(&editor, branch); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + } +} + + +TEST_F(CommonOperatorReducerTest, BranchWithTrueConstant) { + TRACED_FOREACH(BranchHint, hint, kBranchHints) { + Node* const control = graph()->start(); + Node* const branch = + graph()->NewNode(common()->Branch(hint), TrueConstant(), control); + Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); + Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Replace(if_true, control)); + EXPECT_CALL(editor, Replace(if_false, IsDead())); + Reduction const r = Reduce(&editor, branch); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + } +} + + +TEST_F(CommonOperatorReducerTest, BranchWithBooleanNot) { + Node* const value = Parameter(0); + TRACED_FOREACH(BranchHint, hint, kBranchHints) { + Node* const control = graph()->start(); + Node* const branch = graph()->NewNode( + common()->Branch(hint), + graph()->NewNode(simplified()->BooleanNot(), value), control); + Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); + Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); + Reduction const r = Reduce(branch); + ASSERT_TRUE(r.Changed()); + EXPECT_EQ(branch, r.replacement()); + EXPECT_THAT(branch, IsBranch(value, control)); + EXPECT_THAT(if_false, IsIfTrue(branch)); + EXPECT_THAT(if_true, IsIfFalse(branch)); + EXPECT_EQ(NegateBranchHint(hint), BranchHintOf(branch->op())); + } +} + + +// ----------------------------------------------------------------------------- +// Merge + + +TEST_F(CommonOperatorReducerTest, MergeOfUnusedDiamond0) { + Node* const value = Parameter(0); + Node* const control = graph()->start(); + Node* const branch = graph()->NewNode(common()->Branch(), value, control); + Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); + Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); + Reduction const r = + Reduce(graph()->NewNode(common()->Merge(2), if_true, if_false)); + ASSERT_TRUE(r.Changed()); + EXPECT_EQ(control, r.replacement()); + EXPECT_THAT(branch, IsDead()); +} + + +TEST_F(CommonOperatorReducerTest, MergeOfUnusedDiamond1) { + Node* const value = Parameter(0); + Node* const control = graph()->start(); + Node* const branch = graph()->NewNode(common()->Branch(), value, control); + Node* const if_true = graph()->NewNode(common()->IfTrue(), branch); + Node* const if_false = graph()->NewNode(common()->IfFalse(), branch); + Reduction const r = + Reduce(graph()->NewNode(common()->Merge(2), if_false, if_true)); + ASSERT_TRUE(r.Changed()); + EXPECT_EQ(control, r.replacement()); + EXPECT_THAT(branch, IsDead()); +} + + +// ----------------------------------------------------------------------------- // EffectPhi -TEST_F(CommonOperatorReducerTest, RedundantEffectPhi) { +TEST_F(CommonOperatorReducerTest, EffectPhiWithMerge) { const int kMaxInputs = 64; Node* inputs[kMaxInputs]; Node* const input = graph()->NewNode(&kOp0); TRACED_FORRANGE(int, input_count, 2, kMaxInputs - 1) { int const value_input_count = input_count - 1; for (int i = 0; i < value_input_count; ++i) { + inputs[i] = graph()->start(); + } + Node* const merge = graph()->NewNode(common()->Merge(value_input_count), + value_input_count, inputs); + for (int i = 0; i < value_input_count; ++i) { inputs[i] = input; } - inputs[value_input_count] = graph()->start(); - Reduction r = Reduce(graph()->NewNode( - common()->EffectPhi(value_input_count), input_count, inputs)); + inputs[value_input_count] = merge; + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Revisit(merge)); + Reduction r = + Reduce(&editor, graph()->NewNode(common()->EffectPhi(value_input_count), + input_count, inputs)); ASSERT_TRUE(r.Changed()); EXPECT_EQ(input, r.replacement()); } } +TEST_F(CommonOperatorReducerTest, EffectPhiWithLoop) { + Node* const e0 = graph()->NewNode(&kOp0); + Node* const loop = + graph()->NewNode(common()->Loop(2), graph()->start(), graph()->start()); + loop->ReplaceInput(1, loop); + Node* const ephi = graph()->NewNode(common()->EffectPhi(2), e0, e0, loop); + ephi->ReplaceInput(1, ephi); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Revisit(loop)); + Reduction const r = Reduce(&editor, ephi); + ASSERT_TRUE(r.Changed()); + EXPECT_EQ(e0, r.replacement()); +} + + // ----------------------------------------------------------------------------- // Phi -TEST_F(CommonOperatorReducerTest, RedundantPhi) { +TEST_F(CommonOperatorReducerTest, PhiWithMerge) { const int kMaxInputs = 64; Node* inputs[kMaxInputs]; Node* const input = graph()->NewNode(&kOp0); @@ -93,14 +283,17 @@ TEST_F(CommonOperatorReducerTest, RedundantPhi) { for (int i = 0; i < value_input_count; ++i) { inputs[i] = graph()->start(); } - Node* merge = graph()->NewNode(common()->Merge(value_input_count), - value_input_count, inputs); + Node* const merge = graph()->NewNode(common()->Merge(value_input_count), + value_input_count, inputs); for (int i = 0; i < value_input_count; ++i) { inputs[i] = input; } inputs[value_input_count] = merge; - Reduction r = Reduce(graph()->NewNode( - common()->Phi(type, value_input_count), input_count, inputs)); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Revisit(merge)); + Reduction r = Reduce( + &editor, graph()->NewNode(common()->Phi(type, value_input_count), + input_count, inputs)); ASSERT_TRUE(r.Changed()); EXPECT_EQ(input, r.replacement()); } @@ -108,6 +301,22 @@ TEST_F(CommonOperatorReducerTest, RedundantPhi) { } +TEST_F(CommonOperatorReducerTest, PhiWithLoop) { + Node* const p0 = Parameter(0); + Node* const loop = + graph()->NewNode(common()->Loop(2), graph()->start(), graph()->start()); + loop->ReplaceInput(1, loop); + Node* const phi = + graph()->NewNode(common()->Phi(kMachAnyTagged, 2), p0, p0, loop); + phi->ReplaceInput(1, phi); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Revisit(loop)); + Reduction const r = Reduce(&editor, phi); + ASSERT_TRUE(r.Changed()); + EXPECT_EQ(p0, r.replacement()); +} + + TEST_F(CommonOperatorReducerTest, PhiToFloat32Abs) { Node* p0 = Parameter(0); Node* c0 = Float32Constant(0.0); @@ -120,7 +329,9 @@ TEST_F(CommonOperatorReducerTest, PhiToFloat32Abs) { Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); Node* phi = graph()->NewNode(common()->Phi(kMachFloat32, 2), vtrue, vfalse, merge); - Reduction r = Reduce(phi); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Revisit(merge)); + Reduction r = Reduce(&editor, phi); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsFloat32Abs(p0)); } @@ -138,7 +349,9 @@ TEST_F(CommonOperatorReducerTest, PhiToFloat64Abs) { Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); Node* phi = graph()->NewNode(common()->Phi(kMachFloat64, 2), vtrue, vfalse, merge); - Reduction r = Reduce(phi); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Revisit(merge)); + Reduction r = Reduce(&editor, phi); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsFloat64Abs(p0)); } @@ -153,7 +366,9 @@ TEST_F(CommonOperatorReducerTest, PhiToFloat32Max) { Node* if_false = graph()->NewNode(common()->IfFalse(), branch); Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); Node* phi = graph()->NewNode(common()->Phi(kMachFloat32, 2), p1, p0, merge); - Reduction r = Reduce(phi, MachineOperatorBuilder::kFloat32Max); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Revisit(merge)); + Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat32Max); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsFloat32Max(p1, p0)); } @@ -168,7 +383,9 @@ TEST_F(CommonOperatorReducerTest, PhiToFloat64Max) { Node* if_false = graph()->NewNode(common()->IfFalse(), branch); Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); Node* phi = graph()->NewNode(common()->Phi(kMachFloat64, 2), p1, p0, merge); - Reduction r = Reduce(phi, MachineOperatorBuilder::kFloat64Max); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Revisit(merge)); + Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat64Max); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsFloat64Max(p1, p0)); } @@ -183,7 +400,9 @@ TEST_F(CommonOperatorReducerTest, PhiToFloat32Min) { Node* if_false = graph()->NewNode(common()->IfFalse(), branch); Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); Node* phi = graph()->NewNode(common()->Phi(kMachFloat32, 2), p0, p1, merge); - Reduction r = Reduce(phi, MachineOperatorBuilder::kFloat32Min); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Revisit(merge)); + Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat32Min); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsFloat32Min(p0, p1)); } @@ -198,17 +417,48 @@ TEST_F(CommonOperatorReducerTest, PhiToFloat64Min) { Node* if_false = graph()->NewNode(common()->IfFalse(), branch); Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); Node* phi = graph()->NewNode(common()->Phi(kMachFloat64, 2), p0, p1, merge); - Reduction r = Reduce(phi, MachineOperatorBuilder::kFloat64Min); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Revisit(merge)); + Reduction r = Reduce(&editor, phi, MachineOperatorBuilder::kFloat64Min); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsFloat64Min(p0, p1)); } // ----------------------------------------------------------------------------- +// Return + + +TEST_F(CommonOperatorReducerTest, ReturnWithPhiAndEffectPhiAndMerge) { + Node* cond = Parameter(2); + Node* branch = graph()->NewNode(common()->Branch(), cond, graph()->start()); + Node* if_true = graph()->NewNode(common()->IfTrue(), branch); + Node* etrue = graph()->start(); + Node* vtrue = Parameter(0); + Node* if_false = graph()->NewNode(common()->IfFalse(), branch); + Node* efalse = graph()->start(); + Node* vfalse = Parameter(1); + Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); + Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge); + Node* phi = + graph()->NewNode(common()->Phi(kMachAnyTagged, 2), vtrue, vfalse, merge); + Node* ret = graph()->NewNode(common()->Return(), phi, ephi, merge); + graph()->SetEnd(graph()->NewNode(common()->End(1), ret)); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Replace(merge, IsDead())); + Reduction const r = Reduce(&editor, ret); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + EXPECT_THAT(graph()->end(), IsEnd(ret, IsReturn(vtrue, etrue, if_true), + IsReturn(vfalse, efalse, if_false))); +} + + +// ----------------------------------------------------------------------------- // Select -TEST_F(CommonOperatorReducerTest, RedundantSelect) { +TEST_F(CommonOperatorReducerTest, SelectWithSameThenAndElse) { Node* const input = graph()->NewNode(&kOp0); TRACED_FOREACH(BranchHint, hint, kBranchHints) { TRACED_FOREACH(MachineType, type, kMachineTypes) { @@ -221,6 +471,50 @@ TEST_F(CommonOperatorReducerTest, RedundantSelect) { } +TEST_F(CommonOperatorReducerTest, SelectWithInt32ZeroConstant) { + Node* p0 = Parameter(0); + Node* p1 = Parameter(1); + Node* select = graph()->NewNode(common()->Select(kMachAnyTagged), + Int32Constant(0), p0, p1); + Reduction r = Reduce(select); + ASSERT_TRUE(r.Changed()); + EXPECT_EQ(p1, r.replacement()); +} + + +TEST_F(CommonOperatorReducerTest, SelectWithInt32OneConstant) { + Node* p0 = Parameter(0); + Node* p1 = Parameter(1); + Node* select = graph()->NewNode(common()->Select(kMachAnyTagged), + Int32Constant(1), p0, p1); + Reduction r = Reduce(select); + ASSERT_TRUE(r.Changed()); + EXPECT_EQ(p0, r.replacement()); +} + + +TEST_F(CommonOperatorReducerTest, SelectWithInt64ZeroConstant) { + Node* p0 = Parameter(0); + Node* p1 = Parameter(1); + Node* select = graph()->NewNode(common()->Select(kMachAnyTagged), + Int64Constant(0), p0, p1); + Reduction r = Reduce(select); + ASSERT_TRUE(r.Changed()); + EXPECT_EQ(p1, r.replacement()); +} + + +TEST_F(CommonOperatorReducerTest, SelectWithInt64OneConstant) { + Node* p0 = Parameter(0); + Node* p1 = Parameter(1); + Node* select = graph()->NewNode(common()->Select(kMachAnyTagged), + Int64Constant(1), p0, p1); + Reduction r = Reduce(select); + ASSERT_TRUE(r.Changed()); + EXPECT_EQ(p0, r.replacement()); +} + + TEST_F(CommonOperatorReducerTest, SelectWithFalseConstant) { Node* p0 = Parameter(0); Node* p1 = Parameter(1); diff --git a/deps/v8/test/unittests/compiler/common-operator-unittest.cc b/deps/v8/test/unittests/compiler/common-operator-unittest.cc index 4f4d9f70d0..8765c13271 100644 --- a/deps/v8/test/unittests/compiler/common-operator-unittest.cc +++ b/deps/v8/test/unittests/compiler/common-operator-unittest.cc @@ -48,15 +48,13 @@ const SharedOperator kSharedOperators[] = { value_input_count, effect_input_count, control_input_count, \ value_output_count, effect_output_count, control_output_count \ } - SHARED(Dead, Operator::kFoldable, 0, 0, 0, 0, 0, 1), - SHARED(End, Operator::kKontrol, 0, 0, 1, 0, 0, 0), + SHARED(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1), SHARED(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1), SHARED(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1), SHARED(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1), - SHARED(IfException, Operator::kKontrol, 0, 0, 1, 1, 0, 1), SHARED(Throw, Operator::kKontrol, 1, 1, 1, 0, 0, 1), SHARED(Return, Operator::kNoThrow, 1, 1, 1, 0, 0, 1), - SHARED(Terminate, Operator::kNoThrow, 0, 1, 1, 0, 0, 1) + SHARED(Terminate, Operator::kKontrol, 0, 1, 1, 0, 0, 1) #undef SHARED }; @@ -162,6 +160,9 @@ const double kDoubleValues[] = {-std::numeric_limits<double>::infinity(), std::numeric_limits<double>::signaling_NaN()}; +const size_t kInputCounts[] = {3, 4, 100, 255, 1024, 65000}; + + const int32_t kInt32Values[] = { std::numeric_limits<int32_t>::min(), -1914954528, -1698749618, -1578693386, -1577976073, -1573998034, -1529085059, -1499540537, -1299205097, @@ -176,14 +177,31 @@ const int32_t kInt32Values[] = { 2008792749, 2045320228, std::numeric_limits<int32_t>::max()}; -const BranchHint kHints[] = {BranchHint::kNone, BranchHint::kTrue, - BranchHint::kFalse}; +const BranchHint kBranchHints[] = {BranchHint::kNone, BranchHint::kTrue, + BranchHint::kFalse}; } // namespace +TEST_F(CommonOperatorTest, End) { + TRACED_FOREACH(size_t, input_count, kInputCounts) { + const Operator* const op = common()->End(input_count); + EXPECT_EQ(IrOpcode::kEnd, op->opcode()); + EXPECT_EQ(Operator::kKontrol, op->properties()); + EXPECT_EQ(0, op->ValueInputCount()); + EXPECT_EQ(0, op->EffectInputCount()); + EXPECT_EQ(input_count, static_cast<uint32_t>(op->ControlInputCount())); + EXPECT_EQ(input_count, static_cast<uint32_t>( + OperatorProperties::GetTotalInputCount(op))); + EXPECT_EQ(0, op->ValueOutputCount()); + EXPECT_EQ(0, op->EffectOutputCount()); + EXPECT_EQ(0, op->ControlOutputCount()); + } +} + + TEST_F(CommonOperatorTest, Branch) { - TRACED_FOREACH(BranchHint, hint, kHints) { + TRACED_FOREACH(BranchHint, hint, kBranchHints) { const Operator* const op = common()->Branch(hint); EXPECT_EQ(IrOpcode::kBranch, op->opcode()); EXPECT_EQ(Operator::kKontrol, op->properties()); @@ -199,6 +217,24 @@ TEST_F(CommonOperatorTest, Branch) { } +TEST_F(CommonOperatorTest, IfException) { + static const IfExceptionHint kIfExceptionHints[] = { + IfExceptionHint::kLocallyCaught, IfExceptionHint::kLocallyUncaught}; + TRACED_FOREACH(IfExceptionHint, hint, kIfExceptionHints) { + const Operator* const op = common()->IfException(hint); + EXPECT_EQ(IrOpcode::kIfException, op->opcode()); + EXPECT_EQ(Operator::kKontrol, op->properties()); + EXPECT_EQ(0, op->ValueInputCount()); + EXPECT_EQ(1, op->EffectInputCount()); + EXPECT_EQ(1, op->ControlInputCount()); + EXPECT_EQ(2, OperatorProperties::GetTotalInputCount(op)); + EXPECT_EQ(1, op->ValueOutputCount()); + EXPECT_EQ(1, op->EffectOutputCount()); + EXPECT_EQ(1, op->ControlOutputCount()); + } +} + + TEST_F(CommonOperatorTest, Switch) { TRACED_FOREACH(size_t, cases, kCases) { const Operator* const op = common()->Switch(cases); @@ -238,7 +274,7 @@ TEST_F(CommonOperatorTest, Select) { kMachInt32, kMachUint32, kMachInt64, kMachUint64, kMachFloat32, kMachFloat64, kMachAnyTagged}; TRACED_FOREACH(MachineType, type, kTypes) { - TRACED_FOREACH(BranchHint, hint, kHints) { + TRACED_FOREACH(BranchHint, hint, kBranchHints) { const Operator* const op = common()->Select(type, hint); EXPECT_EQ(IrOpcode::kSelect, op->opcode()); EXPECT_EQ(Operator::kPure, op->properties()); diff --git a/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc b/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc index 515bd061ef..47be5407f7 100644 --- a/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc +++ b/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc @@ -27,7 +27,7 @@ class ControlEquivalenceTest : public GraphTest { protected: void ComputeEquivalence(Node* node) { - graph()->SetEnd(graph()->NewNode(common()->End(), node)); + graph()->SetEnd(graph()->NewNode(common()->End(1), node)); if (FLAG_trace_turbo) { OFStream os(stdout); os << AsDOT(*graph()); @@ -41,7 +41,7 @@ class ControlEquivalenceTest : public GraphTest { } bool IsEquivalenceClass(size_t length, Node** nodes) { - BitVector in_class(graph()->NodeCount(), zone()); + BitVector in_class(static_cast<int>(graph()->NodeCount()), zone()); size_t expected_class = classes_[nodes[0]->id()]; for (size_t i = 0; i < length; ++i) { in_class.Add(nodes[i]->id()); @@ -79,7 +79,7 @@ class ControlEquivalenceTest : public GraphTest { } Node* End(Node* control) { - return Store(graph()->NewNode(common()->End(), control)); + return Store(graph()->NewNode(common()->End(1), control)); } private: diff --git a/deps/v8/test/unittests/compiler/control-flow-optimizer-unittest.cc b/deps/v8/test/unittests/compiler/control-flow-optimizer-unittest.cc index 190930edac..444f5f5fee 100644 --- a/deps/v8/test/unittests/compiler/control-flow-optimizer-unittest.cc +++ b/deps/v8/test/unittests/compiler/control-flow-optimizer-unittest.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "src/compiler/control-flow-optimizer.h" -#include "src/compiler/js-graph.h" #include "src/compiler/js-operator.h" #include "src/compiler/machine-operator.h" #include "test/unittests/compiler/graph-unittest.h" @@ -21,28 +20,21 @@ namespace compiler { class ControlFlowOptimizerTest : public GraphTest { public: explicit ControlFlowOptimizerTest(int num_parameters = 3) - : GraphTest(num_parameters), - machine_(zone()), - javascript_(zone()), - jsgraph_(isolate(), graph(), common(), javascript(), machine()) {} + : GraphTest(num_parameters), machine_(zone()), javascript_(zone()) {} ~ControlFlowOptimizerTest() override {} protected: void Optimize() { - ControlFlowOptimizer optimizer(jsgraph(), zone()); + ControlFlowOptimizer optimizer(graph(), common(), machine(), zone()); optimizer.Optimize(); } - Node* EmptyFrameState() { return jsgraph()->EmptyFrameState(); } - - JSGraph* jsgraph() { return &jsgraph_; } JSOperatorBuilder* javascript() { return &javascript_; } MachineOperatorBuilder* machine() { return &machine_; } private: MachineOperatorBuilder machine_; JSOperatorBuilder javascript_; - JSGraph jsgraph_; }; @@ -62,7 +54,7 @@ TEST_F(ControlFlowOptimizerTest, BuildSwitch1) { Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); Node* merge = graph()->NewNode(common()->Merge(3), if_true0, if_true1, if_false1); - graph()->SetEnd(graph()->NewNode(common()->End(), merge)); + graph()->SetEnd(graph()->NewNode(common()->End(1), merge)); Optimize(); Capture<Node*> switch_capture; EXPECT_THAT(end(), @@ -77,7 +69,7 @@ TEST_F(ControlFlowOptimizerTest, BuildSwitch2) { Node* input = Parameter(0); Node* context = Parameter(1); Node* index = graph()->NewNode(javascript()->ToNumber(), input, context, - EmptyFrameState(), start(), start()); + start(), start(), start()); Node* if_success = graph()->NewNode(common()->IfSuccess(), index); Node* branch0 = graph()->NewNode( common()->Branch(), @@ -93,7 +85,7 @@ TEST_F(ControlFlowOptimizerTest, BuildSwitch2) { Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); Node* merge = graph()->NewNode(common()->Merge(3), if_true0, if_true1, if_false1); - graph()->SetEnd(graph()->NewNode(common()->End(), merge)); + graph()->SetEnd(graph()->NewNode(common()->End(1), merge)); Optimize(); Capture<Node*> switch_capture; EXPECT_THAT( @@ -119,7 +111,7 @@ TEST_F(ControlFlowOptimizerTest, CloneBranch) { Node* if_true = graph()->NewNode(common()->IfTrue(), branch); Node* if_false = graph()->NewNode(common()->IfFalse(), branch); Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); - graph()->SetEnd(graph()->NewNode(common()->End(), merge)); + graph()->SetEnd(graph()->NewNode(common()->End(1), merge)); Optimize(); Capture<Node*> branch1_capture, branch2_capture; EXPECT_THAT( diff --git a/deps/v8/test/unittests/compiler/control-reducer-unittest.cc b/deps/v8/test/unittests/compiler/control-reducer-unittest.cc deleted file mode 100644 index 2f65caadc3..0000000000 --- a/deps/v8/test/unittests/compiler/control-reducer-unittest.cc +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright 2015 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "src/compiler/control-reducer.h" -#include "src/compiler/diamond.h" -#include "src/compiler/graph-visualizer.h" -#include "src/compiler/js-graph.h" -#include "src/compiler/js-operator.h" -#include "src/compiler/machine-operator.h" -#include "src/compiler/node.h" -#include "test/unittests/compiler/graph-unittest.h" -#include "test/unittests/compiler/node-test-utils.h" -#include "testing/gmock-support.h" - -using testing::_; -using testing::AllOf; -using testing::Capture; -using testing::CaptureEq; - -namespace v8 { -namespace internal { -namespace compiler { - -class ControlReducerTest : public TypedGraphTest { - public: - ControlReducerTest() - : TypedGraphTest(1), - machine_(zone()), - javascript_(zone()), - jsgraph_(isolate(), graph(), common(), &javascript_, &machine_) {} - - protected: - MachineOperatorBuilder machine_; - JSOperatorBuilder javascript_; - JSGraph jsgraph_; - - void ReduceGraph(int max_phis_for_select = 0) { - if (FLAG_trace_turbo_graph) { - OFStream os(stdout); - os << "-- Graph before control reduction" << std::endl; - os << AsRPO(*graph()); - } - ControlReducer::ReduceGraph(zone(), jsgraph(), max_phis_for_select); - if (FLAG_trace_turbo_graph) { - OFStream os(stdout); - os << "-- Graph after control reduction" << std::endl; - os << AsRPO(*graph()); - } - } - - JSGraph* jsgraph() { return &jsgraph_; } -}; - - -TEST_F(ControlReducerTest, NonTerminatingLoop) { - Node* loop = graph()->NewNode(common()->Loop(2), graph()->start()); - loop->AppendInput(graph()->zone(), loop); - ReduceGraph(); - EXPECT_THAT( - graph()->end(), - IsEnd(IsMerge(graph()->start(), - IsTerminate(graph()->start(), - AllOf(loop, IsLoop(graph()->start(), loop)))))); -} - - -TEST_F(ControlReducerTest, NonTerminatingLoopWithEffectPhi) { - Node* loop = graph()->NewNode(common()->Loop(2), graph()->start()); - loop->AppendInput(graph()->zone(), loop); - Node* ephi = graph()->NewNode(common()->EffectPhi(2), graph()->start()); - ephi->AppendInput(graph()->zone(), ephi); - ephi->AppendInput(graph()->zone(), loop); - ReduceGraph(); - EXPECT_THAT( - graph()->end(), - IsEnd(IsMerge( - graph()->start(), - IsTerminate(AllOf(ephi, IsEffectPhi(graph()->start(), ephi, loop)), - AllOf(loop, IsLoop(graph()->start(), loop)))))); -} - - -TEST_F(ControlReducerTest, NonTerminatingLoopWithTwoEffectPhis) { - Node* loop = graph()->NewNode(common()->Loop(2), graph()->start()); - loop->AppendInput(graph()->zone(), loop); - Node* ephi1 = graph()->NewNode(common()->EffectPhi(2), graph()->start()); - ephi1->AppendInput(graph()->zone(), ephi1); - ephi1->AppendInput(graph()->zone(), loop); - Node* ephi2 = graph()->NewNode(common()->EffectPhi(2), graph()->start()); - ephi2->AppendInput(graph()->zone(), ephi2); - ephi2->AppendInput(graph()->zone(), loop); - ReduceGraph(); - EXPECT_THAT( - graph()->end(), - IsEnd(IsMerge( - graph()->start(), - IsTerminate( - IsEffectSet( - AllOf(ephi1, IsEffectPhi(graph()->start(), ephi1, loop)), - AllOf(ephi2, IsEffectPhi(graph()->start(), ephi2, loop))), - AllOf(loop, IsLoop(graph()->start(), loop)))))); -} - - -TEST_F(ControlReducerTest, NonTerminatingLoopWithDeadEnd) { - Node* loop = graph()->NewNode(common()->Loop(2), graph()->start()); - loop->AppendInput(graph()->zone(), loop); - graph()->end()->ReplaceInput(0, graph()->NewNode(common()->Dead())); - ReduceGraph(); - EXPECT_THAT(graph()->end(), - IsEnd(IsTerminate(graph()->start(), - AllOf(loop, IsLoop(graph()->start(), loop))))); -} - - -TEST_F(ControlReducerTest, PhiAsInputToBranch_true) { - Node* p0 = Parameter(0); - Node* branch1 = graph()->NewNode(common()->Branch(), p0, graph()->start()); - Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); - Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); - Node* merge1 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); - Node* phi1 = graph()->NewNode(common()->Phi(kMachInt32, 2), - jsgraph()->Int32Constant(1), - jsgraph()->Int32Constant(2), merge1); - - Node* branch2 = graph()->NewNode(common()->Branch(), phi1, merge1); - Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); - Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); - Node* merge2 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); - Node* result = graph()->NewNode(common()->Phi(kMachInt32, 2), - jsgraph()->Int32Constant(11), - jsgraph()->Int32Constant(22), merge2); - - Node* ret = - graph()->NewNode(common()->Return(), result, graph()->start(), merge2); - graph()->end()->ReplaceInput(0, ret); - - ReduceGraph(); - - // First diamond is not reduced. - EXPECT_THAT(merge1, IsMerge(IsIfTrue(branch1), IsIfFalse(branch1))); - - // Second diamond should be folded away. - EXPECT_THAT(graph()->end(), - IsEnd(IsReturn(IsInt32Constant(11), graph()->start(), merge1))); -} - - -TEST_F(ControlReducerTest, PhiAsInputToBranch_false) { - Node* p0 = Parameter(0); - Node* branch1 = graph()->NewNode(common()->Branch(), p0, graph()->start()); - Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); - Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); - Node* merge1 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); - Node* phi1 = graph()->NewNode(common()->Phi(kMachInt32, 2), - jsgraph()->Int32Constant(0), - jsgraph()->BooleanConstant(false), merge1); - - Node* branch2 = graph()->NewNode(common()->Branch(), phi1, merge1); - Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); - Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); - Node* merge2 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); - Node* result = graph()->NewNode(common()->Phi(kMachInt32, 2), - jsgraph()->Int32Constant(11), - jsgraph()->Int32Constant(22), merge2); - - Node* ret = - graph()->NewNode(common()->Return(), result, graph()->start(), merge2); - graph()->end()->ReplaceInput(0, ret); - - ReduceGraph(); - - // First diamond is not reduced. - EXPECT_THAT(merge1, IsMerge(IsIfTrue(branch1), IsIfFalse(branch1))); - - // Second diamond should be folded away. - EXPECT_THAT(graph()->end(), - IsEnd(IsReturn(IsInt32Constant(22), graph()->start(), merge1))); -} - - -TEST_F(ControlReducerTest, PhiAsInputToBranch_unknown_true) { - Node* p0 = Parameter(0); - Node* phi0 = graph()->NewNode(common()->Phi(kMachInt32, 2), p0, - jsgraph()->Int32Constant(1), graph()->start()); - Node* branch1 = graph()->NewNode(common()->Branch(), phi0, graph()->start()); - Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); - Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); - Node* merge1 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); - Node* phi1 = graph()->NewNode(common()->Phi(kMachInt32, 2), - jsgraph()->Int32Constant(111), - jsgraph()->Int32Constant(222), merge1); - - Node* ret = - graph()->NewNode(common()->Return(), phi1, graph()->start(), merge1); - graph()->end()->ReplaceInput(0, ret); - - ReduceGraph(); - - // Branch should not be folded. - EXPECT_THAT(phi1, - IsPhi(kMachInt32, IsInt32Constant(111), IsInt32Constant(222), - IsMerge(IsIfTrue(branch1), IsIfFalse(branch1)))); - EXPECT_THAT(graph()->end(), IsEnd(IsReturn(phi1, graph()->start(), merge1))); -} - - -TEST_F(ControlReducerTest, RangeAsInputToBranch_true1) { - Node* p0 = Parameter(Type::Range(1, 2, zone()), 0); - Node* branch1 = graph()->NewNode(common()->Branch(), p0, graph()->start()); - Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); - Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); - Node* merge1 = graph()->NewNode(common()->Merge(1), if_true1, if_false1); - Node* result = graph()->NewNode(common()->Phi(kMachInt32, 2), - jsgraph()->Int32Constant(11), - jsgraph()->Int32Constant(44), merge1); - - Node* ret = - graph()->NewNode(common()->Return(), result, graph()->start(), merge1); - graph()->end()->ReplaceInput(0, ret); - - ReduceGraph(); - - // Diamond should be folded away. - EXPECT_THAT( - graph()->end(), - IsEnd(IsReturn(IsInt32Constant(11), graph()->start(), graph()->start()))); -} - - -TEST_F(ControlReducerTest, RangeAsInputToBranch_true2) { - Node* p0 = Parameter(Type::Range(-2, -1, zone()), 0); - Node* branch1 = graph()->NewNode(common()->Branch(), p0, graph()->start()); - Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); - Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); - Node* merge1 = graph()->NewNode(common()->Merge(1), if_true1, if_false1); - Node* result = graph()->NewNode(common()->Phi(kMachInt32, 2), - jsgraph()->Int32Constant(11), - jsgraph()->Int32Constant(44), merge1); - - Node* ret = - graph()->NewNode(common()->Return(), result, graph()->start(), merge1); - graph()->end()->ReplaceInput(0, ret); - - ReduceGraph(); - - // Diamond should be folded away. - EXPECT_THAT( - graph()->end(), - IsEnd(IsReturn(IsInt32Constant(11), graph()->start(), graph()->start()))); -} - - -TEST_F(ControlReducerTest, SelectPhi) { - Node* p0 = Parameter(0); - const MachineType kType = kMachInt32; - Diamond d(graph(), common(), p0); - Node* phi = - d.Phi(kType, jsgraph()->Int32Constant(1), jsgraph()->Int32Constant(2)); - - Node* ret = - graph()->NewNode(common()->Return(), phi, graph()->start(), d.merge); - graph()->end()->ReplaceInput(0, ret); - - ReduceGraph(1); - - // Phi should be replaced with a select. - EXPECT_THAT(graph()->end(), - IsEnd(IsReturn( - IsSelect(kType, p0, IsInt32Constant(1), IsInt32Constant(2)), - graph()->start(), graph()->start()))); -} - - -TEST_F(ControlReducerTest, SelectPhis_fail) { - Node* p0 = Parameter(0); - const MachineType kType = kMachInt32; - Diamond d(graph(), common(), p0); - Node* phi = - d.Phi(kType, jsgraph()->Int32Constant(1), jsgraph()->Int32Constant(2)); - Node* phi2 = - d.Phi(kType, jsgraph()->Int32Constant(11), jsgraph()->Int32Constant(22)); - USE(phi2); - Node* ret = - graph()->NewNode(common()->Return(), phi, graph()->start(), d.merge); - graph()->end()->ReplaceInput(0, ret); - - ReduceGraph(1); - - // Diamond should not be replaced with a select (too many phis). - EXPECT_THAT(ret, IsReturn(phi, graph()->start(), d.merge)); - EXPECT_THAT(graph()->end(), IsEnd(ret)); -} - - -TEST_F(ControlReducerTest, SelectTwoPhis) { - Node* p0 = Parameter(0); - const MachineType kType = kMachInt32; - Diamond d(graph(), common(), p0); - Node* phi1 = - d.Phi(kType, jsgraph()->Int32Constant(1), jsgraph()->Int32Constant(2)); - Node* phi2 = - d.Phi(kType, jsgraph()->Int32Constant(2), jsgraph()->Int32Constant(3)); - MachineOperatorBuilder machine(zone()); - Node* add = graph()->NewNode(machine.Int32Add(), phi1, phi2); - Node* ret = - graph()->NewNode(common()->Return(), add, graph()->start(), d.merge); - graph()->end()->ReplaceInput(0, ret); - - ReduceGraph(2); - - // Phis should be replaced with two selects. - EXPECT_THAT( - ret, - IsReturn(IsInt32Add( - IsSelect(kType, p0, IsInt32Constant(1), IsInt32Constant(2)), - IsSelect(kType, p0, IsInt32Constant(2), IsInt32Constant(3))), - graph()->start(), graph()->start())); - EXPECT_THAT(graph()->end(), IsEnd(ret)); -} - - -} // namespace compiler -} // namespace internal -} // namespace v8 diff --git a/deps/v8/test/unittests/compiler/dead-code-elimination-unittest.cc b/deps/v8/test/unittests/compiler/dead-code-elimination-unittest.cc new file mode 100644 index 0000000000..8284fd8775 --- /dev/null +++ b/deps/v8/test/unittests/compiler/dead-code-elimination-unittest.cc @@ -0,0 +1,375 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/compiler/common-operator.h" +#include "src/compiler/dead-code-elimination.h" +#include "test/unittests/compiler/graph-reducer-unittest.h" +#include "test/unittests/compiler/graph-unittest.h" +#include "test/unittests/compiler/node-test-utils.h" +#include "testing/gmock-support.h" + +using testing::StrictMock; + +namespace v8 { +namespace internal { +namespace compiler { + +class DeadCodeEliminationTest : public GraphTest { + public: + explicit DeadCodeEliminationTest(int num_parameters = 4) + : GraphTest(num_parameters) {} + ~DeadCodeEliminationTest() override {} + + protected: + Reduction Reduce(AdvancedReducer::Editor* editor, Node* node) { + DeadCodeElimination reducer(editor, graph(), common()); + return reducer.Reduce(node); + } + + Reduction Reduce(Node* node) { + StrictMock<MockAdvancedReducerEditor> editor; + return Reduce(&editor, node); + } +}; + + +namespace { + +const MachineType kMachineTypes[] = { + kMachFloat32, kMachFloat64, kMachInt8, kMachUint8, kMachInt16, + kMachUint16, kMachInt32, kMachUint32, kMachInt64, kMachUint64, + kMachPtr, kMachAnyTagged, kRepBit, kRepWord8, kRepWord16, + kRepWord32, kRepWord64, kRepFloat32, kRepFloat64, kRepTagged}; + + +const int kMaxInputs = 16; + + +const Operator kOp0(0, Operator::kNoProperties, "Op0", 1, 1, 1, 1, 1, 1); + +} // namespace + + +// ----------------------------------------------------------------------------- +// General dead propagation + + +TEST_F(DeadCodeEliminationTest, GeneralDeadPropagation) { + Node* const value = Parameter(0); + Node* const effect = graph()->start(); + Node* const dead = graph()->NewNode(common()->Dead()); + Node* const node = graph()->NewNode(&kOp0, value, effect, dead); + Reduction const r = Reduce(node); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); +} + + +// ----------------------------------------------------------------------------- +// Branch + + +TEST_F(DeadCodeEliminationTest, BranchWithDeadControlInput) { + BranchHint const kHints[] = {BranchHint::kNone, BranchHint::kTrue, + BranchHint::kFalse}; + TRACED_FOREACH(BranchHint, hint, kHints) { + Reduction const r = + Reduce(graph()->NewNode(common()->Branch(hint), Parameter(0), + graph()->NewNode(common()->Dead()))); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + } +} + + +// ----------------------------------------------------------------------------- +// IfTrue + + +TEST_F(DeadCodeEliminationTest, IfTrueWithDeadInput) { + Reduction const r = Reduce( + graph()->NewNode(common()->IfTrue(), graph()->NewNode(common()->Dead()))); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); +} + + +// ----------------------------------------------------------------------------- +// IfFalse + + +TEST_F(DeadCodeEliminationTest, IfFalseWithDeadInput) { + Reduction const r = Reduce(graph()->NewNode( + common()->IfFalse(), graph()->NewNode(common()->Dead()))); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); +} + + +// ----------------------------------------------------------------------------- +// IfSuccess + + +TEST_F(DeadCodeEliminationTest, IfSuccessWithDeadInput) { + Reduction const r = Reduce(graph()->NewNode( + common()->IfSuccess(), graph()->NewNode(common()->Dead()))); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); +} + + +// ----------------------------------------------------------------------------- +// IfException + + +TEST_F(DeadCodeEliminationTest, IfExceptionWithDeadControlInput) { + IfExceptionHint const kHints[] = {IfExceptionHint::kLocallyCaught, + IfExceptionHint::kLocallyUncaught}; + TRACED_FOREACH(IfExceptionHint, hint, kHints) { + Reduction const r = + Reduce(graph()->NewNode(common()->IfException(hint), graph()->start(), + graph()->NewNode(common()->Dead()))); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + } +} + + +// ----------------------------------------------------------------------------- +// End + + +TEST_F(DeadCodeEliminationTest, EndWithDeadAndStart) { + Node* const dead = graph()->NewNode(common()->Dead()); + Node* const start = graph()->start(); + Reduction const r = Reduce(graph()->NewNode(common()->End(2), dead, start)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsEnd(start)); +} + + +TEST_F(DeadCodeEliminationTest, EndWithOnlyDeadInputs) { + Node* inputs[kMaxInputs]; + TRACED_FORRANGE(int, input_count, 1, kMaxInputs - 1) { + for (int i = 0; i < input_count; ++i) { + inputs[i] = graph()->NewNode(common()->Dead()); + } + Reduction const r = Reduce( + graph()->NewNode(common()->End(input_count), input_count, inputs)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + } +} + + +// ----------------------------------------------------------------------------- +// Merge + + +TEST_F(DeadCodeEliminationTest, MergeWithOnlyDeadInputs) { + Node* inputs[kMaxInputs + 1]; + TRACED_FORRANGE(int, input_count, 1, kMaxInputs - 1) { + for (int i = 0; i < input_count; ++i) { + inputs[i] = graph()->NewNode(common()->Dead()); + } + Reduction const r = Reduce( + graph()->NewNode(common()->Merge(input_count), input_count, inputs)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + } +} + + +TEST_F(DeadCodeEliminationTest, MergeWithOneLiveAndOneDeadInput) { + Node* const v0 = Parameter(0); + Node* const v1 = Parameter(1); + Node* const c0 = + graph()->NewNode(&kOp0, v0, graph()->start(), graph()->start()); + Node* const c1 = graph()->NewNode(common()->Dead()); + Node* const e0 = graph()->NewNode(&kOp0, v0, graph()->start(), c0); + Node* const e1 = graph()->NewNode(&kOp0, v1, graph()->start(), c1); + Node* const merge = graph()->NewNode(common()->Merge(2), c0, c1); + Node* const phi = + graph()->NewNode(common()->Phi(kMachAnyTagged, 2), v0, v1, merge); + Node* const ephi = graph()->NewNode(common()->EffectPhi(2), e0, e1, merge); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Replace(phi, v0)); + EXPECT_CALL(editor, Replace(ephi, e0)); + Reduction const r = Reduce(&editor, merge); + ASSERT_TRUE(r.Changed()); + EXPECT_EQ(c0, r.replacement()); +} + + +TEST_F(DeadCodeEliminationTest, MergeWithTwoLiveAndTwoDeadInputs) { + Node* const v0 = Parameter(0); + Node* const v1 = Parameter(1); + Node* const v2 = Parameter(2); + Node* const v3 = Parameter(3); + Node* const c0 = + graph()->NewNode(&kOp0, v0, graph()->start(), graph()->start()); + Node* const c1 = graph()->NewNode(common()->Dead()); + Node* const c2 = graph()->NewNode(common()->Dead()); + Node* const c3 = graph()->NewNode(&kOp0, v3, graph()->start(), c0); + Node* const e0 = graph()->start(); + Node* const e1 = graph()->NewNode(&kOp0, v1, e0, c0); + Node* const e2 = graph()->NewNode(&kOp0, v2, e1, c0); + Node* const e3 = graph()->NewNode(&kOp0, v3, graph()->start(), c3); + Node* const merge = graph()->NewNode(common()->Merge(4), c0, c1, c2, c3); + Node* const phi = + graph()->NewNode(common()->Phi(kMachAnyTagged, 4), v0, v1, v2, v3, merge); + Node* const ephi = + graph()->NewNode(common()->EffectPhi(4), e0, e1, e2, e3, merge); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Revisit(phi)); + EXPECT_CALL(editor, Revisit(ephi)); + Reduction const r = Reduce(&editor, merge); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsMerge(c0, c3)); + EXPECT_THAT(phi, IsPhi(kMachAnyTagged, v0, v3, r.replacement())); + EXPECT_THAT(ephi, IsEffectPhi(e0, e3, r.replacement())); +} + + +// ----------------------------------------------------------------------------- +// Loop + + +TEST_F(DeadCodeEliminationTest, LoopWithDeadFirstInput) { + Node* inputs[kMaxInputs + 1]; + TRACED_FORRANGE(int, input_count, 1, kMaxInputs - 1) { + inputs[0] = graph()->NewNode(common()->Dead()); + for (int i = 1; i < input_count; ++i) { + inputs[i] = graph()->start(); + } + Reduction const r = Reduce( + graph()->NewNode(common()->Loop(input_count), input_count, inputs)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + } +} + + +TEST_F(DeadCodeEliminationTest, LoopWithOnlyDeadInputs) { + Node* inputs[kMaxInputs + 1]; + TRACED_FORRANGE(int, input_count, 1, kMaxInputs - 1) { + for (int i = 0; i < input_count; ++i) { + inputs[i] = graph()->NewNode(common()->Dead()); + } + Reduction const r = Reduce( + graph()->NewNode(common()->Loop(input_count), input_count, inputs)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + } +} + + +TEST_F(DeadCodeEliminationTest, LoopWithOneLiveAndOneDeadInput) { + Node* const v0 = Parameter(0); + Node* const v1 = Parameter(1); + Node* const c0 = + graph()->NewNode(&kOp0, v0, graph()->start(), graph()->start()); + Node* const c1 = graph()->NewNode(common()->Dead()); + Node* const e0 = graph()->NewNode(&kOp0, v0, graph()->start(), c0); + Node* const e1 = graph()->NewNode(&kOp0, v1, graph()->start(), c1); + Node* const loop = graph()->NewNode(common()->Loop(2), c0, c1); + Node* const phi = + graph()->NewNode(common()->Phi(kMachAnyTagged, 2), v0, v1, loop); + Node* const ephi = graph()->NewNode(common()->EffectPhi(2), e0, e1, loop); + Node* const terminate = graph()->NewNode(common()->Terminate(), ephi, loop); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Replace(phi, v0)); + EXPECT_CALL(editor, Replace(ephi, e0)); + EXPECT_CALL(editor, Replace(terminate, IsDead())); + Reduction const r = Reduce(&editor, loop); + ASSERT_TRUE(r.Changed()); + EXPECT_EQ(c0, r.replacement()); +} + + +TEST_F(DeadCodeEliminationTest, LoopWithTwoLiveAndTwoDeadInputs) { + Node* const v0 = Parameter(0); + Node* const v1 = Parameter(1); + Node* const v2 = Parameter(2); + Node* const v3 = Parameter(3); + Node* const c0 = + graph()->NewNode(&kOp0, v0, graph()->start(), graph()->start()); + Node* const c1 = graph()->NewNode(common()->Dead()); + Node* const c2 = graph()->NewNode(common()->Dead()); + Node* const c3 = graph()->NewNode(&kOp0, v3, graph()->start(), c0); + Node* const e0 = graph()->start(); + Node* const e1 = graph()->NewNode(&kOp0, v1, e0, c0); + Node* const e2 = graph()->NewNode(&kOp0, v2, e1, c0); + Node* const e3 = graph()->NewNode(&kOp0, v3, graph()->start(), c3); + Node* const loop = graph()->NewNode(common()->Loop(4), c0, c1, c2, c3); + Node* const phi = + graph()->NewNode(common()->Phi(kMachAnyTagged, 4), v0, v1, v2, v3, loop); + Node* const ephi = + graph()->NewNode(common()->EffectPhi(4), e0, e1, e2, e3, loop); + StrictMock<MockAdvancedReducerEditor> editor; + EXPECT_CALL(editor, Revisit(phi)); + EXPECT_CALL(editor, Revisit(ephi)); + Reduction const r = Reduce(&editor, loop); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsLoop(c0, c3)); + EXPECT_THAT(phi, IsPhi(kMachAnyTagged, v0, v3, r.replacement())); + EXPECT_THAT(ephi, IsEffectPhi(e0, e3, r.replacement())); +} + + +// ----------------------------------------------------------------------------- +// Phi + + +TEST_F(DeadCodeEliminationTest, PhiWithDeadControlInput) { + Node* inputs[kMaxInputs + 1]; + TRACED_FOREACH(MachineType, type, kMachineTypes) { + TRACED_FORRANGE(int, input_count, 1, kMaxInputs) { + for (int i = 0; i < input_count; ++i) { + inputs[i] = Parameter(i); + } + inputs[input_count] = graph()->NewNode(common()->Dead()); + Reduction const r = Reduce(graph()->NewNode( + common()->Phi(type, input_count), input_count + 1, inputs)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + } + } +} + + +// ----------------------------------------------------------------------------- +// EffectPhi + + +TEST_F(DeadCodeEliminationTest, EffectPhiWithDeadControlInput) { + Node* inputs[kMaxInputs + 1]; + TRACED_FORRANGE(int, input_count, 1, kMaxInputs) { + for (int i = 0; i < input_count; ++i) { + inputs[i] = graph()->start(); + } + inputs[input_count] = graph()->NewNode(common()->Dead()); + Reduction const r = Reduce(graph()->NewNode( + common()->EffectPhi(input_count), input_count + 1, inputs)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); + } +} + + +// ----------------------------------------------------------------------------- +// Terminate + + +TEST_F(DeadCodeEliminationTest, TerminateWithDeadControlInput) { + Reduction const r = + Reduce(graph()->NewNode(common()->Terminate(), graph()->start(), + graph()->NewNode(common()->Dead()))); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsDead()); +} + +} // namespace compiler +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/unittests/compiler/graph-reducer-unittest.cc b/deps/v8/test/unittests/compiler/graph-reducer-unittest.cc index ea981ccaf3..3ca6052af9 100644 --- a/deps/v8/test/unittests/compiler/graph-reducer-unittest.cc +++ b/deps/v8/test/unittests/compiler/graph-reducer-unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "src/compiler/common-operator.h" #include "src/compiler/graph.h" #include "src/compiler/node.h" #include "src/compiler/operator.h" @@ -10,9 +11,11 @@ using testing::_; using testing::DefaultValue; +using testing::ElementsAre; using testing::Return; using testing::Sequence; using testing::StrictMock; +using testing::UnorderedElementsAre; namespace v8 { namespace internal { @@ -264,6 +267,124 @@ TEST_F(AdvancedReducerTest, Revisit) { } +namespace { + +struct ReplaceWithValueReducer final : public AdvancedReducer { + explicit ReplaceWithValueReducer(Editor* editor) : AdvancedReducer(editor) {} + Reduction Reduce(Node* node) final { return NoChange(); } + using AdvancedReducer::ReplaceWithValue; +}; + +const Operator kMockOperator(IrOpcode::kDead, Operator::kNoProperties, + "MockOperator", 0, 0, 0, 1, 0, 0); +const Operator kMockOpEffect(IrOpcode::kDead, Operator::kNoProperties, + "MockOpEffect", 0, 1, 0, 1, 1, 0); +const Operator kMockOpControl(IrOpcode::kDead, Operator::kNoProperties, + "MockOpControl", 0, 0, 1, 1, 0, 1); + +const IfExceptionHint kNoHint = IfExceptionHint::kLocallyCaught; + +} // namespace + + +TEST_F(AdvancedReducerTest, ReplaceWithValue_ValueUse) { + CommonOperatorBuilder common(zone()); + Node* node = graph()->NewNode(&kMockOperator); + Node* use_value = graph()->NewNode(common.Return(), node); + Node* replacement = graph()->NewNode(&kMockOperator); + GraphReducer graph_reducer(zone(), graph(), nullptr); + ReplaceWithValueReducer r(&graph_reducer); + r.ReplaceWithValue(node, replacement); + EXPECT_EQ(replacement, use_value->InputAt(0)); + EXPECT_EQ(0, node->UseCount()); + EXPECT_EQ(1, replacement->UseCount()); + EXPECT_THAT(replacement->uses(), ElementsAre(use_value)); +} + + +TEST_F(AdvancedReducerTest, ReplaceWithValue_EffectUse) { + CommonOperatorBuilder common(zone()); + Node* start = graph()->NewNode(common.Start(1)); + Node* node = graph()->NewNode(&kMockOpEffect, start); + Node* use_effect = graph()->NewNode(common.EffectPhi(1), node); + Node* replacement = graph()->NewNode(&kMockOperator); + GraphReducer graph_reducer(zone(), graph(), nullptr); + ReplaceWithValueReducer r(&graph_reducer); + r.ReplaceWithValue(node, replacement); + EXPECT_EQ(start, use_effect->InputAt(0)); + EXPECT_EQ(0, node->UseCount()); + EXPECT_EQ(2, start->UseCount()); + EXPECT_EQ(0, replacement->UseCount()); + EXPECT_THAT(start->uses(), UnorderedElementsAre(use_effect, node)); +} + + +TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse1) { + CommonOperatorBuilder common(zone()); + Node* start = graph()->NewNode(common.Start(1)); + Node* node = graph()->NewNode(&kMockOpControl, start); + Node* success = graph()->NewNode(common.IfSuccess(), node); + Node* use_control = graph()->NewNode(common.Merge(1), success); + Node* replacement = graph()->NewNode(&kMockOperator); + GraphReducer graph_reducer(zone(), graph(), nullptr); + ReplaceWithValueReducer r(&graph_reducer); + r.ReplaceWithValue(node, replacement); + EXPECT_EQ(start, use_control->InputAt(0)); + EXPECT_EQ(0, node->UseCount()); + EXPECT_EQ(2, start->UseCount()); + EXPECT_EQ(0, replacement->UseCount()); + EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node)); +} + + +TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse2) { + CommonOperatorBuilder common(zone()); + Node* start = graph()->NewNode(common.Start(1)); + Node* effect = graph()->NewNode(&kMockOperator); + Node* dead = graph()->NewNode(&kMockOperator); + Node* node = graph()->NewNode(&kMockOpControl, start); + Node* success = graph()->NewNode(common.IfSuccess(), node); + Node* exception = graph()->NewNode(common.IfException(kNoHint), effect, node); + Node* use_control = graph()->NewNode(common.Merge(1), success); + Node* replacement = graph()->NewNode(&kMockOperator); + GraphReducer graph_reducer(zone(), graph(), dead); + ReplaceWithValueReducer r(&graph_reducer); + r.ReplaceWithValue(node, replacement); + EXPECT_EQ(start, use_control->InputAt(0)); + EXPECT_EQ(dead, exception->InputAt(1)); + EXPECT_EQ(0, node->UseCount()); + EXPECT_EQ(2, start->UseCount()); + EXPECT_EQ(1, dead->UseCount()); + EXPECT_EQ(0, replacement->UseCount()); + EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node)); + EXPECT_THAT(dead->uses(), ElementsAre(exception)); +} + + +TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse3) { + CommonOperatorBuilder common(zone()); + Node* start = graph()->NewNode(common.Start(1)); + Node* effect = graph()->NewNode(&kMockOperator); + Node* dead = graph()->NewNode(&kMockOperator); + Node* node = graph()->NewNode(&kMockOpControl, start); + Node* success = graph()->NewNode(common.IfSuccess(), node); + Node* exception = graph()->NewNode(common.IfException(kNoHint), effect, node); + Node* use_control = graph()->NewNode(common.Merge(1), success); + Node* replacement = graph()->NewNode(&kMockOperator); + GraphReducer graph_reducer(zone(), graph(), dead); + ReplaceWithValueReducer r(&graph_reducer); + r.ReplaceWithValue(node, replacement); + EXPECT_EQ(start, use_control->InputAt(0)); + EXPECT_EQ(dead, exception->InputAt(1)); + EXPECT_EQ(0, node->UseCount()); + EXPECT_EQ(2, start->UseCount()); + EXPECT_EQ(1, dead->UseCount()); + EXPECT_EQ(0, replacement->UseCount()); + EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node)); + EXPECT_THAT(dead->uses(), ElementsAre(exception)); +} + + class GraphReducerTest : public TestWithZone { public: GraphReducerTest() : graph_(zone()) {} @@ -280,20 +401,20 @@ class GraphReducerTest : public TestWithZone { protected: void ReduceNode(Node* node, Reducer* r) { - GraphReducer reducer(graph(), zone()); + GraphReducer reducer(zone(), graph()); reducer.AddReducer(r); reducer.ReduceNode(node); } void ReduceNode(Node* node, Reducer* r1, Reducer* r2) { - GraphReducer reducer(graph(), zone()); + GraphReducer reducer(zone(), graph()); reducer.AddReducer(r1); reducer.AddReducer(r2); reducer.ReduceNode(node); } void ReduceNode(Node* node, Reducer* r1, Reducer* r2, Reducer* r3) { - GraphReducer reducer(graph(), zone()); + GraphReducer reducer(zone(), graph()); reducer.AddReducer(r1); reducer.AddReducer(r2); reducer.AddReducer(r3); @@ -301,20 +422,20 @@ class GraphReducerTest : public TestWithZone { } void ReduceGraph(Reducer* r1) { - GraphReducer reducer(graph(), zone()); + GraphReducer reducer(zone(), graph()); reducer.AddReducer(r1); reducer.ReduceGraph(); } void ReduceGraph(Reducer* r1, Reducer* r2) { - GraphReducer reducer(graph(), zone()); + GraphReducer reducer(zone(), graph()); reducer.AddReducer(r1); reducer.AddReducer(r2); reducer.ReduceGraph(); } void ReduceGraph(Reducer* r1, Reducer* r2, Reducer* r3) { - GraphReducer reducer(graph(), zone()); + GraphReducer reducer(zone(), graph()); reducer.AddReducer(r1); reducer.AddReducer(r2); reducer.AddReducer(r3); @@ -401,7 +522,7 @@ TEST_F(GraphReducerTest, ReduceInPlace1) { // Tests A* => B* with in-place updates. InPlaceABReducer r; for (int i = 0; i < 3; i++) { - int before = graph()->NodeCount(); + size_t before = graph()->NodeCount(); ReduceGraph(&r); EXPECT_EQ(before, graph()->NodeCount()); EXPECT_EQ(&kOpB0, n1->op()); @@ -421,7 +542,7 @@ TEST_F(GraphReducerTest, ReduceInPlace2) { // Tests A* => B* with in-place updates. InPlaceABReducer r; for (int i = 0; i < 3; i++) { - int before = graph()->NodeCount(); + size_t before = graph()->NodeCount(); ReduceGraph(&r); EXPECT_EQ(before, graph()->NodeCount()); EXPECT_EQ(&kOpB0, n1->op()); @@ -446,7 +567,7 @@ TEST_F(GraphReducerTest, ReduceNew1) { NewABReducer r(graph()); // Tests A* => B* while creating new nodes. for (int i = 0; i < 3; i++) { - int before = graph()->NodeCount(); + size_t before = graph()->NodeCount(); ReduceGraph(&r); if (i == 0) { EXPECT_NE(before, graph()->NodeCount()); @@ -473,12 +594,12 @@ TEST_F(GraphReducerTest, ReduceNew1) { TEST_F(GraphReducerTest, Wrapping1) { Node* end = graph()->NewNode(&kOpA0); graph()->SetEnd(end); - EXPECT_EQ(1, graph()->NodeCount()); + EXPECT_EQ(1U, graph()->NodeCount()); A0Wrapper r(graph()); ReduceGraph(&r); - EXPECT_EQ(2, graph()->NodeCount()); + EXPECT_EQ(2U, graph()->NodeCount()); Node* nend = graph()->end(); EXPECT_NE(end, nend); @@ -491,12 +612,12 @@ TEST_F(GraphReducerTest, Wrapping1) { TEST_F(GraphReducerTest, Wrapping2) { Node* end = graph()->NewNode(&kOpB0); graph()->SetEnd(end); - EXPECT_EQ(1, graph()->NodeCount()); + EXPECT_EQ(1U, graph()->NodeCount()); B0Wrapper r(graph()); ReduceGraph(&r); - EXPECT_EQ(3, graph()->NodeCount()); + EXPECT_EQ(3U, graph()->NodeCount()); Node* nend = graph()->end(); EXPECT_NE(end, nend); @@ -520,7 +641,7 @@ TEST_F(GraphReducerTest, Forwarding1) { // Tests A1(x) => x for (int i = 0; i < 3; i++) { - int before = graph()->NodeCount(); + size_t before = graph()->NodeCount(); ReduceGraph(&r); EXPECT_EQ(before, graph()->NodeCount()); EXPECT_EQ(&kOpA0, n1->op()); @@ -540,7 +661,7 @@ TEST_F(GraphReducerTest, Forwarding2) { // Tests reducing A2(A1(x), A1(y)) => A2(x, y). for (int i = 0; i < 3; i++) { - int before = graph()->NodeCount(); + size_t before = graph()->NodeCount(); ReduceGraph(&r); EXPECT_EQ(before, graph()->NodeCount()); EXPECT_EQ(&kOpA0, n1->op()); @@ -565,8 +686,8 @@ TEST_F(GraphReducerTest, Forwarding3) { A1Forwarder r; - for (int i = 0; i < 3; i++) { - int before = graph()->NodeCount(); + for (size_t i = 0; i < 3; i++) { + size_t before = graph()->NodeCount(); ReduceGraph(&r); EXPECT_EQ(before, graph()->NodeCount()); EXPECT_EQ(&kOpA0, n1->op()); @@ -587,8 +708,8 @@ TEST_F(GraphReducerTest, ReduceForward1) { B1Forwarder f; // Tests first reducing A => B, then B1(x) => x. - for (int i = 0; i < 3; i++) { - int before = graph()->NodeCount(); + for (size_t i = 0; i < 3; i++) { + size_t before = graph()->NodeCount(); ReduceGraph(&r, &f); EXPECT_EQ(before, graph()->NodeCount()); EXPECT_EQ(&kOpB0, n1->op()); @@ -620,7 +741,7 @@ TEST_F(GraphReducerTest, Sorter1) { graph()->SetEnd(end); - int before = graph()->NodeCount(); + size_t before = graph()->NodeCount(); ReduceGraph(&r); EXPECT_EQ(before, graph()->NodeCount()); EXPECT_EQ(&kOpA0, n1->op()); @@ -715,8 +836,8 @@ TEST_F(GraphReducerTest, Order) { InPlaceBCReducer bcr; // Tests A* => C* with in-place updates. - for (int j = 0; j < 3; j++) { - int before = graph()->NodeCount(); + for (size_t j = 0; j < 3; j++) { + size_t before = graph()->NodeCount(); if (i == 0) { ReduceGraph(&abr, &bcr); } else { diff --git a/deps/v8/test/unittests/compiler/graph-reducer-unittest.h b/deps/v8/test/unittests/compiler/graph-reducer-unittest.h index 4cde964709..2b0651da13 100644 --- a/deps/v8/test/unittests/compiler/graph-reducer-unittest.h +++ b/deps/v8/test/unittests/compiler/graph-reducer-unittest.h @@ -15,6 +15,7 @@ namespace compiler { struct MockAdvancedReducerEditor : public AdvancedReducer::Editor { MOCK_METHOD1(Revisit, void(Node*)); MOCK_METHOD2(Replace, void(Node*, Node*)); + MOCK_METHOD4(ReplaceWithValue, void(Node*, Node*, Node*, Node*)); }; } // namespace compiler diff --git a/deps/v8/test/unittests/compiler/graph-trimmer-unittest.cc b/deps/v8/test/unittests/compiler/graph-trimmer-unittest.cc new file mode 100644 index 0000000000..36892e6ee8 --- /dev/null +++ b/deps/v8/test/unittests/compiler/graph-trimmer-unittest.cc @@ -0,0 +1,85 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/compiler/graph-trimmer.h" +#include "test/unittests/compiler/graph-unittest.h" +#include "testing/gmock-support.h" + +using testing::ElementsAre; +using testing::UnorderedElementsAre; + +namespace v8 { +namespace internal { +namespace compiler { + +class GraphTrimmerTest : public GraphTest { + public: + GraphTrimmerTest() : GraphTest(1) {} + + protected: + void TrimGraph(Node* root) { + Node* const roots[1] = {root}; + GraphTrimmer trimmer(zone(), graph()); + trimmer.TrimGraph(&roots[0], &roots[arraysize(roots)]); + } + void TrimGraph() { + GraphTrimmer trimmer(zone(), graph()); + trimmer.TrimGraph(); + } +}; + + +namespace { + +const Operator kDead0(IrOpcode::kDead, Operator::kNoProperties, "Dead0", 0, 0, + 1, 0, 0, 0); +const Operator kLive0(IrOpcode::kDead, Operator::kNoProperties, "Live0", 0, 0, + 1, 0, 0, 1); + +} // namespace + + +TEST_F(GraphTrimmerTest, Empty) { + Node* const start = graph()->NewNode(common()->Start(0)); + Node* const end = graph()->NewNode(common()->End(1), start); + graph()->SetStart(start); + graph()->SetEnd(end); + TrimGraph(); + EXPECT_EQ(end, graph()->end()); + EXPECT_EQ(start, graph()->start()); + EXPECT_EQ(start, end->InputAt(0)); +} + + +TEST_F(GraphTrimmerTest, DeadUseOfStart) { + Node* const dead0 = graph()->NewNode(&kDead0, graph()->start()); + graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start())); + TrimGraph(); + EXPECT_THAT(dead0->inputs(), ElementsAre(nullptr)); + EXPECT_THAT(graph()->start()->uses(), ElementsAre(graph()->end())); +} + + +TEST_F(GraphTrimmerTest, DeadAndLiveUsesOfStart) { + Node* const dead0 = graph()->NewNode(&kDead0, graph()->start()); + Node* const live0 = graph()->NewNode(&kLive0, graph()->start()); + graph()->SetEnd(graph()->NewNode(common()->End(1), live0)); + TrimGraph(); + EXPECT_THAT(dead0->inputs(), ElementsAre(nullptr)); + EXPECT_THAT(graph()->start()->uses(), ElementsAre(live0)); + EXPECT_THAT(live0->uses(), ElementsAre(graph()->end())); +} + + +TEST_F(GraphTrimmerTest, Roots) { + Node* const live0 = graph()->NewNode(&kLive0, graph()->start()); + Node* const live1 = graph()->NewNode(&kLive0, graph()->start()); + graph()->SetEnd(graph()->NewNode(common()->End(1), live0)); + TrimGraph(live1); + EXPECT_THAT(graph()->start()->uses(), UnorderedElementsAre(live0, live1)); +} + +} // namespace compiler +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/unittests/compiler/graph-unittest.cc b/deps/v8/test/unittests/compiler/graph-unittest.cc index 9da3950e54..6b8546b95a 100644 --- a/deps/v8/test/unittests/compiler/graph-unittest.cc +++ b/deps/v8/test/unittests/compiler/graph-unittest.cc @@ -13,7 +13,7 @@ namespace compiler { GraphTest::GraphTest(int num_parameters) : common_(zone()), graph_(zone()) { graph()->SetStart(graph()->NewNode(common()->Start(num_parameters))); - graph()->SetEnd(graph()->NewNode(common()->End(), graph()->start())); + graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start())); } @@ -81,6 +81,16 @@ Node* GraphTest::UndefinedConstant() { } +Node* GraphTest::EmptyFrameState() { + Node* state_values = graph()->NewNode(common()->StateValues(0)); + return graph()->NewNode( + common()->FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(), + nullptr), + state_values, state_values, state_values, NumberConstant(0), + UndefinedConstant(), graph()->start()); +} + + Matcher<Node*> GraphTest::IsFalseConstant() { return IsHeapConstant( Unique<HeapObject>::CreateImmovable(factory()->false_value())); @@ -100,8 +110,7 @@ Matcher<Node*> GraphTest::IsUndefinedConstant() { TypedGraphTest::TypedGraphTest(int num_parameters) - : GraphTest(num_parameters), - typer_(isolate(), graph(), MaybeHandle<Context>()) {} + : GraphTest(num_parameters), typer_(isolate(), graph()) {} TypedGraphTest::~TypedGraphTest() {} @@ -126,8 +135,8 @@ TEST_F(GraphTest, NewNode) { Node* n0 = graph()->NewNode(&kDummyOperator); Node* n1 = graph()->NewNode(&kDummyOperator); EXPECT_NE(n0, n1); - EXPECT_LT(0, n0->id()); - EXPECT_LT(0, n1->id()); + EXPECT_LT(0u, n0->id()); + EXPECT_LT(0u, n1->id()); EXPECT_NE(n0->id(), n1->id()); EXPECT_EQ(&kDummyOperator, n0->op()); EXPECT_EQ(&kDummyOperator, n1->op()); diff --git a/deps/v8/test/unittests/compiler/graph-unittest.h b/deps/v8/test/unittests/compiler/graph-unittest.h index c905f30c6a..2318fa61f8 100644 --- a/deps/v8/test/unittests/compiler/graph-unittest.h +++ b/deps/v8/test/unittests/compiler/graph-unittest.h @@ -50,6 +50,8 @@ class GraphTest : public TestWithContext, public TestWithIsolateAndZone { Node* TrueConstant(); Node* UndefinedConstant(); + Node* EmptyFrameState(); + Matcher<Node*> IsFalseConstant(); Matcher<Node*> IsTrueConstant(); Matcher<Node*> IsUndefinedConstant(); diff --git a/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc b/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc index dfdb4c2b1f..acab91b009 100644 --- a/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc +++ b/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc @@ -148,6 +148,15 @@ bool InstructionSelectorTest::Stream::IsUsedAtStart( } +const FrameStateFunctionInfo* +InstructionSelectorTest::StreamBuilder::GetFrameStateFunctionInfo( + int parameter_count, int local_count) { + return common()->CreateFrameStateFunctionInfo( + FrameStateType::kJavaScriptFunction, parameter_count, local_count, + Handle<SharedFunctionInfo>()); +} + + // ----------------------------------------------------------------------------- // Return. @@ -198,7 +207,8 @@ TARGET_TEST_F(InstructionSelectorTest, ReturnZero) { TARGET_TEST_F(InstructionSelectorTest, TruncateFloat64ToInt32WithParameter) { StreamBuilder m(this, kMachInt32, kMachFloat64); - m.Return(m.TruncateFloat64ToInt32(m.Parameter(0))); + m.Return( + m.TruncateFloat64ToInt32(TruncationMode::kJavaScript, m.Parameter(0))); Stream s = m.Build(kAllInstructions); ASSERT_EQ(4U, s.size()); EXPECT_EQ(kArchNop, s[0]->arch_opcode()); @@ -363,9 +373,10 @@ TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) { Node* context_dummy = m.Int32Constant(0); Node* state_node = m.NewNode( - m.common()->FrameState(JS_FRAME, bailout_id, - OutputFrameStateCombine::Push()), - parameters, locals, stack, context_dummy, m.UndefinedConstant()); + m.common()->FrameState(bailout_id, OutputFrameStateCombine::Push(), + m.GetFrameStateFunctionInfo(1, 0)), + parameters, locals, stack, context_dummy, function_node, + m.UndefinedConstant()); Node* call = m.CallJS0(function_node, receiver, context, state_node); m.Return(call); @@ -411,9 +422,10 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) { Node* context_sentinel = m.Int32Constant(0); Node* frame_state_before = m.NewNode( - m.common()->FrameState(JS_FRAME, bailout_id_before, - OutputFrameStateCombine::Push()), - parameters, locals, stack, context_sentinel, m.UndefinedConstant()); + m.common()->FrameState(bailout_id_before, OutputFrameStateCombine::Push(), + m.GetFrameStateFunctionInfo(1, 1)), + parameters, locals, stack, context_sentinel, function_node, + m.UndefinedConstant()); // Build the call. Node* call = m.CallFunctionStub0(function_node, receiver, context, @@ -437,7 +449,7 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) { size_t num_operands = 1 + // Code object. 1 + - 4 + // Frame state deopt id + one input for each value in frame state. + 5 + // Frame state deopt id + one input for each value in frame state. 1 + // Function. 1; // Context. ASSERT_EQ(num_operands, call_instr->InputCount()); @@ -455,21 +467,23 @@ TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) { EXPECT_EQ(1u, desc_before->parameters_count()); EXPECT_EQ(1u, desc_before->locals_count()); EXPECT_EQ(1u, desc_before->stack_count()); - EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(2))); - EXPECT_EQ(0, s.ToInt32(call_instr->InputAt(3))); // This should be a context. + EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(3))); + EXPECT_EQ(0, s.ToInt32(call_instr->InputAt(4))); // This should be a context. // We inserted 0 here. - EXPECT_EQ(0.5, s.ToFloat64(call_instr->InputAt(4))); - EXPECT_TRUE(s.ToHeapObject(call_instr->InputAt(5))->IsUndefined()); - EXPECT_EQ(kMachInt32, desc_before->GetType(0)); - EXPECT_EQ(kMachAnyTagged, desc_before->GetType(1)); // context is always + EXPECT_EQ(0.5, s.ToFloat64(call_instr->InputAt(5))); + EXPECT_TRUE(s.ToHeapObject(call_instr->InputAt(6))->IsUndefined()); + EXPECT_EQ(kMachAnyTagged, desc_before->GetType(0)); // function is always // tagged/any. - EXPECT_EQ(kMachFloat64, desc_before->GetType(2)); - EXPECT_EQ(kMachAnyTagged, desc_before->GetType(3)); + EXPECT_EQ(kMachInt32, desc_before->GetType(1)); + EXPECT_EQ(kMachAnyTagged, desc_before->GetType(2)); // context is always + // tagged/any. + EXPECT_EQ(kMachFloat64, desc_before->GetType(3)); + EXPECT_EQ(kMachAnyTagged, desc_before->GetType(4)); // Function. - EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(6))); + EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(7))); // Context. - EXPECT_EQ(s.ToVreg(context), s.ToVreg(call_instr->InputAt(7))); + EXPECT_EQ(s.ToVreg(context), s.ToVreg(call_instr->InputAt(8))); EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); @@ -501,10 +515,11 @@ TARGET_TEST_F(InstructionSelectorTest, m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(64)); Node* stack = m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(65)); - Node* frame_state_parent = - m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id_parent, - OutputFrameStateCombine::Ignore()), - parameters, locals, stack, context, m.UndefinedConstant()); + Node* frame_state_parent = m.NewNode( + m.common()->FrameState(bailout_id_parent, + OutputFrameStateCombine::Ignore(), + m.GetFrameStateFunctionInfo(1, 1)), + parameters, locals, stack, context, function_node, m.UndefinedConstant()); Node* context2 = m.Int32Constant(46); Node* parameters2 = @@ -513,10 +528,11 @@ TARGET_TEST_F(InstructionSelectorTest, m.Float64Constant(0.25)); Node* stack2 = m.NewNode(m.common()->TypedStateValues(&int32x2_type), m.Int32Constant(44), m.Int32Constant(45)); - Node* frame_state_before = - m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id_before, - OutputFrameStateCombine::Push()), - parameters2, locals2, stack2, context2, frame_state_parent); + Node* frame_state_before = m.NewNode( + m.common()->FrameState(bailout_id_before, OutputFrameStateCombine::Push(), + m.GetFrameStateFunctionInfo(1, 1)), + parameters2, locals2, stack2, context2, function_node, + frame_state_parent); // Build the call. Node* call = m.CallFunctionStub0(function_node, receiver, context2, @@ -540,8 +556,8 @@ TARGET_TEST_F(InstructionSelectorTest, size_t num_operands = 1 + // Code object. 1 + // Frame state deopt id - 5 + // One input for each value in frame state + context. - 4 + // One input for each value in the parent frame state + context. + 6 + // One input for each value in frame state + context. + 5 + // One input for each value in the parent frame state + context. 1 + // Function. 1; // Context. EXPECT_EQ(num_operands, call_instr->InputCount()); @@ -558,34 +574,36 @@ TARGET_TEST_F(InstructionSelectorTest, EXPECT_EQ(1u, desc_before_outer->locals_count()); EXPECT_EQ(1u, desc_before_outer->stack_count()); // Values from parent environment. - EXPECT_EQ(63, s.ToInt32(call_instr->InputAt(2))); - EXPECT_EQ(kMachInt32, desc_before_outer->GetType(0)); + EXPECT_EQ(kMachAnyTagged, desc_before->GetType(0)); + EXPECT_EQ(63, s.ToInt32(call_instr->InputAt(3))); + EXPECT_EQ(kMachInt32, desc_before_outer->GetType(1)); // Context: - EXPECT_EQ(66, s.ToInt32(call_instr->InputAt(3))); - EXPECT_EQ(kMachAnyTagged, desc_before_outer->GetType(1)); - EXPECT_EQ(64, s.ToInt32(call_instr->InputAt(4))); - EXPECT_EQ(kMachInt32, desc_before_outer->GetType(2)); - EXPECT_EQ(65, s.ToInt32(call_instr->InputAt(5))); + EXPECT_EQ(66, s.ToInt32(call_instr->InputAt(4))); + EXPECT_EQ(kMachAnyTagged, desc_before_outer->GetType(2)); + EXPECT_EQ(64, s.ToInt32(call_instr->InputAt(5))); EXPECT_EQ(kMachInt32, desc_before_outer->GetType(3)); + EXPECT_EQ(65, s.ToInt32(call_instr->InputAt(6))); + EXPECT_EQ(kMachInt32, desc_before_outer->GetType(4)); // Values from the nested frame. EXPECT_EQ(1u, desc_before->parameters_count()); EXPECT_EQ(1u, desc_before->locals_count()); EXPECT_EQ(2u, desc_before->stack_count()); - EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(6))); - EXPECT_EQ(kMachInt32, desc_before->GetType(0)); - EXPECT_EQ(46, s.ToInt32(call_instr->InputAt(7))); - EXPECT_EQ(kMachAnyTagged, desc_before->GetType(1)); - EXPECT_EQ(0.25, s.ToFloat64(call_instr->InputAt(8))); - EXPECT_EQ(kMachFloat64, desc_before->GetType(2)); - EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(9))); - EXPECT_EQ(kMachInt32, desc_before->GetType(3)); - EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(10))); + EXPECT_EQ(kMachAnyTagged, desc_before->GetType(0)); + EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(8))); + EXPECT_EQ(kMachInt32, desc_before->GetType(1)); + EXPECT_EQ(46, s.ToInt32(call_instr->InputAt(9))); + EXPECT_EQ(kMachAnyTagged, desc_before->GetType(2)); + EXPECT_EQ(0.25, s.ToFloat64(call_instr->InputAt(10))); + EXPECT_EQ(kMachFloat64, desc_before->GetType(3)); + EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(11))); EXPECT_EQ(kMachInt32, desc_before->GetType(4)); + EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(12))); + EXPECT_EQ(kMachInt32, desc_before->GetType(5)); // Function. - EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(11))); + EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(13))); // Context. - EXPECT_EQ(s.ToVreg(context2), s.ToVreg(call_instr->InputAt(12))); + EXPECT_EQ(s.ToVreg(context2), s.ToVreg(call_instr->InputAt(14))); // Continuation. EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); diff --git a/deps/v8/test/unittests/compiler/instruction-selector-unittest.h b/deps/v8/test/unittests/compiler/instruction-selector-unittest.h index a23d531a3a..15d3b2005f 100644 --- a/deps/v8/test/unittests/compiler/instruction-selector-unittest.h +++ b/deps/v8/test/unittests/compiler/instruction-selector-unittest.h @@ -37,22 +37,25 @@ class InstructionSelectorTest : public TestWithContext, class StreamBuilder final : public RawMachineAssembler { public: StreamBuilder(InstructionSelectorTest* test, MachineType return_type) - : RawMachineAssembler(test->isolate(), - new (test->zone()) Graph(test->zone()), - MakeMachineSignature(test->zone(), return_type)), + : RawMachineAssembler( + test->isolate(), new (test->zone()) Graph(test->zone()), + MakeMachineSignature(test->zone(), return_type), kMachPtr, + MachineOperatorBuilder::kAllOptionalOps), test_(test) {} StreamBuilder(InstructionSelectorTest* test, MachineType return_type, MachineType parameter0_type) : RawMachineAssembler( test->isolate(), new (test->zone()) Graph(test->zone()), - MakeMachineSignature(test->zone(), return_type, parameter0_type)), + MakeMachineSignature(test->zone(), return_type, parameter0_type), + kMachPtr, MachineOperatorBuilder::kAllOptionalOps), test_(test) {} StreamBuilder(InstructionSelectorTest* test, MachineType return_type, MachineType parameter0_type, MachineType parameter1_type) : RawMachineAssembler( test->isolate(), new (test->zone()) Graph(test->zone()), MakeMachineSignature(test->zone(), return_type, parameter0_type, - parameter1_type)), + parameter1_type), + kMachPtr, MachineOperatorBuilder::kAllOptionalOps), test_(test) {} StreamBuilder(InstructionSelectorTest* test, MachineType return_type, MachineType parameter0_type, MachineType parameter1_type, @@ -60,7 +63,8 @@ class InstructionSelectorTest : public TestWithContext, : RawMachineAssembler( test->isolate(), new (test->zone()) Graph(test->zone()), MakeMachineSignature(test->zone(), return_type, parameter0_type, - parameter1_type, parameter2_type)), + parameter1_type, parameter2_type), + kMachPtr, MachineOperatorBuilder::kAllOptionalOps), test_(test) {} Stream Build(CpuFeature feature) { @@ -77,6 +81,9 @@ class InstructionSelectorTest : public TestWithContext, InstructionSelector::SourcePositionMode source_position_mode = InstructionSelector::kAllSourcePositions); + const FrameStateFunctionInfo* GetFrameStateFunctionInfo(int parameter_count, + int local_count); + private: MachineSignature* MakeMachineSignature(Zone* zone, MachineType return_type) { diff --git a/deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc b/deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc index f659b07887..1ff441f746 100644 --- a/deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc +++ b/deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc @@ -429,8 +429,8 @@ InstructionBlock* InstructionSequenceTest::NewBlock() { } } // Construct instruction block. - auto instruction_block = - new (zone()) InstructionBlock(zone(), rpo, loop_header, loop_end, false); + auto instruction_block = new (zone()) + InstructionBlock(zone(), rpo, loop_header, loop_end, false, false); instruction_blocks_.push_back(instruction_block); current_block_ = instruction_block; sequence()->StartBlock(rpo); diff --git a/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc b/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc index 090f610066..b452ba56c5 100644 --- a/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc +++ b/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc @@ -26,7 +26,9 @@ class JSBuiltinReducerTest : public TypedGraphTest { MachineOperatorBuilder::Flag::kNoFlags) { MachineOperatorBuilder machine(zone(), kMachPtr, flags); JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine); - JSBuiltinReducer reducer(&jsgraph); + // TODO(titzer): mock the GraphReducer here for better unit testing. + GraphReducer graph_reducer(zone(), graph()); + JSBuiltinReducer reducer(&graph_reducer, &jsgraph); return reducer.Reduce(node); } @@ -77,10 +79,14 @@ Type* const kNumberTypes[] = { TEST_F(JSBuiltinReducerTest, MathMax0) { Node* function = MathFunction("max"); + Node* effect = graph()->start(); + Node* control = graph()->start(); + Node* frame_state = graph()->start(); TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { Node* call = graph()->NewNode( javascript()->CallFunction(2, NO_CALL_FUNCTION_FLAGS, language_mode), - function, UndefinedConstant()); + function, UndefinedConstant(), frame_state, frame_state, effect, + control); Reduction r = Reduce(call); ASSERT_TRUE(r.Changed()); @@ -92,12 +98,16 @@ TEST_F(JSBuiltinReducerTest, MathMax0) { TEST_F(JSBuiltinReducerTest, MathMax1) { Node* function = MathFunction("max"); + Node* effect = graph()->start(); + Node* control = graph()->start(); + Node* frame_state = graph()->start(); TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { TRACED_FOREACH(Type*, t0, kNumberTypes) { Node* p0 = Parameter(t0, 0); Node* call = graph()->NewNode( javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS, language_mode), - function, UndefinedConstant(), p0); + function, UndefinedConstant(), p0, frame_state, frame_state, effect, + control); Reduction r = Reduce(call); ASSERT_TRUE(r.Changed()); @@ -110,6 +120,9 @@ TEST_F(JSBuiltinReducerTest, MathMax1) { TEST_F(JSBuiltinReducerTest, MathMax2) { Node* function = MathFunction("max"); + Node* effect = graph()->start(); + Node* control = graph()->start(); + Node* frame_state = graph()->start(); TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { TRACED_FOREACH(Type*, t0, kIntegral32Types) { TRACED_FOREACH(Type*, t1, kIntegral32Types) { @@ -118,7 +131,8 @@ TEST_F(JSBuiltinReducerTest, MathMax2) { Node* call = graph()->NewNode(javascript()->CallFunction( 4, NO_CALL_FUNCTION_FLAGS, language_mode), - function, UndefinedConstant(), p0, p1); + function, UndefinedConstant(), p0, p1, frame_state, + frame_state, effect, control); Reduction r = Reduce(call); ASSERT_TRUE(r.Changed()); @@ -137,6 +151,9 @@ TEST_F(JSBuiltinReducerTest, MathMax2) { TEST_F(JSBuiltinReducerTest, MathImul) { Node* function = MathFunction("imul"); + Node* effect = graph()->start(); + Node* control = graph()->start(); + Node* frame_state = graph()->start(); TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { TRACED_FOREACH(Type*, t0, kIntegral32Types) { TRACED_FOREACH(Type*, t1, kIntegral32Types) { @@ -145,7 +162,8 @@ TEST_F(JSBuiltinReducerTest, MathImul) { Node* call = graph()->NewNode(javascript()->CallFunction( 4, NO_CALL_FUNCTION_FLAGS, language_mode), - function, UndefinedConstant(), p0, p1); + function, UndefinedConstant(), p0, p1, frame_state, + frame_state, effect, control); Reduction r = Reduce(call); ASSERT_TRUE(r.Changed()); @@ -163,12 +181,16 @@ TEST_F(JSBuiltinReducerTest, MathImul) { TEST_F(JSBuiltinReducerTest, MathFround) { Node* function = MathFunction("fround"); + Node* effect = graph()->start(); + Node* control = graph()->start(); + Node* frame_state = graph()->start(); TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { TRACED_FOREACH(Type*, t0, kNumberTypes) { Node* p0 = Parameter(t0, 0); Node* call = graph()->NewNode( javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS, language_mode), - function, UndefinedConstant(), p0); + function, UndefinedConstant(), p0, frame_state, frame_state, effect, + control); Reduction r = Reduce(call); ASSERT_TRUE(r.Changed()); diff --git a/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc b/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc index bc343060ca..92be4e43e0 100644 --- a/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc +++ b/deps/v8/test/unittests/compiler/js-intrinsic-lowering-unittest.cc @@ -33,7 +33,10 @@ class JSIntrinsicLoweringTest : public GraphTest { MachineOperatorBuilder::kNoFlags) { MachineOperatorBuilder machine(zone(), kMachPtr, flags); JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine); - JSIntrinsicLowering reducer(&jsgraph); + // TODO(titzer): mock the GraphReducer here for better unit testing. + GraphReducer graph_reducer(zone(), graph()); + JSIntrinsicLowering reducer(&graph_reducer, &jsgraph, + JSIntrinsicLowering::kDeoptimizationEnabled); return reducer.Reduce(node); } @@ -171,6 +174,68 @@ TEST_F(JSIntrinsicLoweringTest, InlineIsArray) { // ----------------------------------------------------------------------------- +// %_IsDate + + +TEST_F(JSIntrinsicLoweringTest, InlineIsDate) { + Node* const input = Parameter(0); + Node* const context = Parameter(1); + Node* const effect = graph()->start(); + Node* const control = graph()->start(); + Reduction const r = Reduce( + graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsDate, 1), + input, context, effect, control)); + ASSERT_TRUE(r.Changed()); + + Node* phi = r.replacement(); + Capture<Node*> branch, if_false; + EXPECT_THAT( + phi, + IsPhi( + static_cast<MachineType>(kTypeBool | kRepTagged), IsFalseConstant(), + IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(), + IsLoadField(AccessBuilder::ForMap(), input, + effect, CaptureEq(&if_false)), + effect, _), + IsInt32Constant(JS_DATE_TYPE)), + IsMerge(IsIfTrue(AllOf(CaptureEq(&branch), + IsBranch(IsObjectIsSmi(input), control))), + AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch)))))); +} + + +// ----------------------------------------------------------------------------- +// %_IsTypedArray + + +TEST_F(JSIntrinsicLoweringTest, InlineIsTypedArray) { + Node* const input = Parameter(0); + Node* const context = Parameter(1); + Node* const effect = graph()->start(); + Node* const control = graph()->start(); + Reduction const r = Reduce(graph()->NewNode( + javascript()->CallRuntime(Runtime::kInlineIsTypedArray, 1), input, + context, effect, control)); + ASSERT_TRUE(r.Changed()); + + Node* phi = r.replacement(); + Capture<Node*> branch, if_false; + EXPECT_THAT( + phi, + IsPhi( + static_cast<MachineType>(kTypeBool | kRepTagged), IsFalseConstant(), + IsWord32Equal(IsLoadField(AccessBuilder::ForMapInstanceType(), + IsLoadField(AccessBuilder::ForMap(), input, + effect, CaptureEq(&if_false)), + effect, _), + IsInt32Constant(JS_TYPED_ARRAY_TYPE)), + IsMerge(IsIfTrue(AllOf(CaptureEq(&branch), + IsBranch(IsObjectIsSmi(input), control))), + AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch)))))); +} + + +// ----------------------------------------------------------------------------- // %_IsFunction @@ -264,7 +329,7 @@ TEST_F(JSIntrinsicLoweringTest, Likely) { Node* const to_boolean = graph()->NewNode(javascript()->ToBoolean(), likely, context); Diamond d(graph(), common(), to_boolean); - graph()->SetEnd(graph()->NewNode(common()->End(), d.merge)); + graph()->SetEnd(graph()->NewNode(common()->End(1), d.merge)); ASSERT_EQ(BranchHint::kNone, BranchHintOf(d.branch->op())); Reduction const r = Reduce(likely); @@ -359,7 +424,7 @@ TEST_F(JSIntrinsicLoweringTest, Unlikely) { Node* const to_boolean = graph()->NewNode(javascript()->ToBoolean(), unlikely, context); Diamond d(graph(), common(), to_boolean); - graph()->SetEnd(graph()->NewNode(common()->End(), d.merge)); + graph()->SetEnd(graph()->NewNode(common()->End(1), d.merge)); ASSERT_EQ(BranchHint::kNone, BranchHintOf(d.branch->op())); Reduction const r = Reduce(unlikely); diff --git a/deps/v8/test/unittests/compiler/js-operator-unittest.cc b/deps/v8/test/unittests/compiler/js-operator-unittest.cc index a8a2d8c38a..0f33ddea8d 100644 --- a/deps/v8/test/unittests/compiler/js-operator-unittest.cc +++ b/deps/v8/test/unittests/compiler/js-operator-unittest.cc @@ -186,10 +186,10 @@ const SharedOperatorWithLanguageMode kSharedOperatorsWithLanguageMode[] = { control_input_count, value_output_count, effect_output_count, \ control_output_count \ } - SHARED(LessThan, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2), - SHARED(GreaterThan, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2), - SHARED(LessThanOrEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2), - SHARED(GreaterThanOrEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1, 2), + SHARED(LessThan, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2), + SHARED(GreaterThan, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2), + SHARED(LessThanOrEqual, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2), + SHARED(GreaterThanOrEqual, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2), SHARED(BitwiseOr, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2), SHARED(BitwiseXor, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2), SHARED(BitwiseAnd, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2), @@ -201,7 +201,6 @@ const SharedOperatorWithLanguageMode kSharedOperatorsWithLanguageMode[] = { SHARED(Multiply, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2), SHARED(Divide, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2), SHARED(Modulus, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2), - SHARED(StoreProperty, Operator::kNoProperties, 3, 2, 1, 1, 0, 1, 2), #undef SHARED }; diff --git a/deps/v8/test/unittests/compiler/js-type-feedback-unittest.cc b/deps/v8/test/unittests/compiler/js-type-feedback-unittest.cc index 08fe68a8ba..d52242ec7d 100644 --- a/deps/v8/test/unittests/compiler/js-type-feedback-unittest.cc +++ b/deps/v8/test/unittests/compiler/js-type-feedback-unittest.cc @@ -34,15 +34,18 @@ class JSTypeFeedbackTest : public TypedGraphTest { ~JSTypeFeedbackTest() override { dependencies_.Rollback(); } protected: - Reduction Reduce(Node* node) { + Reduction Reduce(Node* node, + JSTypeFeedbackSpecializer::DeoptimizationMode mode) { Handle<GlobalObject> global_object( isolate()->native_context()->global_object(), isolate()); MachineOperatorBuilder machine(zone()); JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine); JSTypeFeedbackTable table(zone()); - JSTypeFeedbackSpecializer reducer(&jsgraph, &table, nullptr, global_object, - &dependencies_); + // TODO(titzer): mock the GraphReducer here for better unit testing. + GraphReducer graph_reducer(zone(), graph()); + JSTypeFeedbackSpecializer reducer(&graph_reducer, &jsgraph, &table, nullptr, + global_object, mode, &dependencies_); return reducer.Reduce(node); } @@ -71,19 +74,23 @@ class JSTypeFeedbackTest : public TypedGraphTest { result.Assert(); } - Node* ReturnLoadNamedFromGlobal(const char* string, Node* effect, - Node* control) { - VectorSlotPair feedback(Handle<TypeFeedbackVector>::null(), - FeedbackVectorICSlot::Invalid()); - Node* global = Parameter(Type::GlobalObject()); + Node* ReturnLoadNamedFromGlobal( + const char* string, Node* effect, Node* control, + JSTypeFeedbackSpecializer::DeoptimizationMode mode) { + VectorSlotPair feedback; + Node* global = UndefinedConstant(); + Node* vector = UndefinedConstant(); Node* context = UndefinedConstant(); Unique<Name> name = Unique<Name>::CreateUninitialized( - isolate()->factory()->NewStringFromAsciiChecked(string)); - Node* load = graph()->NewNode(javascript()->LoadNamed(name, feedback), - global, context); - if (FLAG_turbo_deoptimization) { - load->AppendInput(zone(), EmptyFrameState()); + isolate()->factory()->InternalizeUtf8String(string)); + const Operator* op = javascript()->LoadGlobal(name, feedback); + Node* load = graph()->NewNode(op, global, vector, context); + if (mode == JSTypeFeedbackSpecializer::kDeoptimizationEnabled) { + for (int i = 0; i < OperatorProperties::GetFrameStateInputCount(op); + i++) { + load->AppendInput(zone(), EmptyFrameState()); + } } load->AppendInput(zone(), effect); load->AppendInput(zone(), control); @@ -98,180 +105,240 @@ class JSTypeFeedbackTest : public TypedGraphTest { CompilationDependencies dependencies_; }; -#define WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION \ - for (int i = FLAG_turbo_deoptimization = 0; i < 2; \ - FLAG_turbo_deoptimization = ++i) +TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstSmi) { + const int kValue = 111; + const char* kName = "banana"; + SetGlobalProperty(kName, kValue); -TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConst_smi) { - const int const_value = 111; - const char* property_name = "banana"; - SetGlobalProperty(property_name, const_value); + Node* ret = ReturnLoadNamedFromGlobal( + kName, graph()->start(), graph()->start(), + JSTypeFeedbackSpecializer::kDeoptimizationDisabled); + graph()->SetEnd(graph()->NewNode(common()->End(1), ret)); - WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION { - Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(), - graph()->start()); - graph()->SetEnd(graph()->NewNode(common()->End(), ret)); + Reduction r = Reduce(ret->InputAt(0), + JSTypeFeedbackSpecializer::kDeoptimizationDisabled); + EXPECT_FALSE(r.Changed()); + EXPECT_TRUE(dependencies()->IsEmpty()); +} - Reduction r = Reduce(ret->InputAt(0)); - if (FLAG_turbo_deoptimization) { - // Check LoadNamed(global) => HeapConstant[const_value] - ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsNumberConstant(const_value)); +TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstSmiWithDeoptimization) { + const int kValue = 111; + const char* kName = "banana"; + SetGlobalProperty(kName, kValue); - EXPECT_THAT(ret, IsReturn(IsNumberConstant(const_value), graph()->start(), - graph()->start())); - EXPECT_THAT(graph()->end(), IsEnd(ret)); + Node* ret = ReturnLoadNamedFromGlobal( + kName, graph()->start(), graph()->start(), + JSTypeFeedbackSpecializer::kDeoptimizationEnabled); + graph()->SetEnd(graph()->NewNode(common()->End(1), ret)); - EXPECT_FALSE(dependencies()->IsEmpty()); - dependencies()->Rollback(); - } else { - ASSERT_FALSE(r.Changed()); - EXPECT_TRUE(dependencies()->IsEmpty()); - } - } + Reduction r = Reduce(ret->InputAt(0), + JSTypeFeedbackSpecializer::kDeoptimizationEnabled); + + // Check LoadNamed(global) => HeapConstant[kValue] + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsNumberConstant(kValue)); + + EXPECT_THAT(ret, IsReturn(IsNumberConstant(kValue), graph()->start(), + graph()->start())); + EXPECT_THAT(graph()->end(), IsEnd(ret)); + + EXPECT_FALSE(dependencies()->IsEmpty()); + dependencies()->Rollback(); } -TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConst_derble) { - const double const_value = -11.25; - const char* property_name = "kiwi"; - SetGlobalProperty(property_name, const_value); +TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstNumber) { + const double kValue = -11.25; + const char* kName = "kiwi"; + SetGlobalProperty(kName, kValue); - WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION { - Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(), - graph()->start()); - graph()->SetEnd(graph()->NewNode(common()->End(), ret)); + Node* ret = ReturnLoadNamedFromGlobal( + kName, graph()->start(), graph()->start(), + JSTypeFeedbackSpecializer::kDeoptimizationDisabled); + graph()->SetEnd(graph()->NewNode(common()->End(1), ret)); - Reduction r = Reduce(ret->InputAt(0)); + Reduction r = Reduce(ret->InputAt(0), + JSTypeFeedbackSpecializer::kDeoptimizationDisabled); - if (FLAG_turbo_deoptimization) { - // Check LoadNamed(global) => HeapConstant[const_value] - ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsNumberConstant(const_value)); + EXPECT_FALSE(r.Changed()); + EXPECT_TRUE(dependencies()->IsEmpty()); +} - EXPECT_THAT(ret, IsReturn(IsNumberConstant(const_value), graph()->start(), - graph()->start())); - EXPECT_THAT(graph()->end(), IsEnd(ret)); - EXPECT_FALSE(dependencies()->IsEmpty()); - } else { - ASSERT_FALSE(r.Changed()); - EXPECT_TRUE(dependencies()->IsEmpty()); - } - } +TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstNumberWithDeoptimization) { + const double kValue = -11.25; + const char* kName = "kiwi"; + SetGlobalProperty(kName, kValue); + + Node* ret = ReturnLoadNamedFromGlobal( + kName, graph()->start(), graph()->start(), + JSTypeFeedbackSpecializer::kDeoptimizationEnabled); + graph()->SetEnd(graph()->NewNode(common()->End(1), ret)); + + Reduction r = Reduce(ret->InputAt(0), + JSTypeFeedbackSpecializer::kDeoptimizationEnabled); + + // Check LoadNamed(global) => HeapConstant[kValue] + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsNumberConstant(kValue)); + + EXPECT_THAT(ret, IsReturn(IsNumberConstant(kValue), graph()->start(), + graph()->start())); + EXPECT_THAT(graph()->end(), IsEnd(ret)); + + EXPECT_FALSE(dependencies()->IsEmpty()); } -TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConst_string) { - Unique<HeapObject> const_value = Unique<HeapObject>::CreateImmovable( +TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstString) { + Unique<HeapObject> kValue = Unique<HeapObject>::CreateImmovable( isolate()->factory()->undefined_string()); - const char* property_name = "mango"; - SetGlobalProperty(property_name, const_value.handle()); - - WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION { - Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(), - graph()->start()); - graph()->SetEnd(graph()->NewNode(common()->End(), ret)); - - Reduction r = Reduce(ret->InputAt(0)); - - if (FLAG_turbo_deoptimization) { - // Check LoadNamed(global) => HeapConstant[const_value] - ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsHeapConstant(const_value)); - - EXPECT_THAT(ret, IsReturn(IsHeapConstant(const_value), graph()->start(), - graph()->start())); - EXPECT_THAT(graph()->end(), IsEnd(ret)); - - EXPECT_FALSE(dependencies()->IsEmpty()); - dependencies()->Rollback(); - } else { - ASSERT_FALSE(r.Changed()); - EXPECT_TRUE(dependencies()->IsEmpty()); - } - } + const char* kName = "mango"; + SetGlobalProperty(kName, kValue.handle()); + + Node* ret = ReturnLoadNamedFromGlobal( + kName, graph()->start(), graph()->start(), + JSTypeFeedbackSpecializer::kDeoptimizationDisabled); + graph()->SetEnd(graph()->NewNode(common()->End(1), ret)); + + Reduction r = Reduce(ret->InputAt(0), + JSTypeFeedbackSpecializer::kDeoptimizationDisabled); + ASSERT_FALSE(r.Changed()); + EXPECT_TRUE(dependencies()->IsEmpty()); } -TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCell_smi) { - const char* property_name = "melon"; - SetGlobalProperty(property_name, 123); - SetGlobalProperty(property_name, 124); - - WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION { - Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(), - graph()->start()); - graph()->SetEnd(graph()->NewNode(common()->End(), ret)); - - Reduction r = Reduce(ret->InputAt(0)); - - if (FLAG_turbo_deoptimization) { - // Check LoadNamed(global) => LoadField[PropertyCell::value](cell) - ASSERT_TRUE(r.Changed()); - FieldAccess access = AccessBuilder::ForPropertyCellValue(); - Capture<Node*> cell_capture; - Matcher<Node*> load_field_match = IsLoadField( - access, CaptureEq(&cell_capture), graph()->start(), graph()->start()); - EXPECT_THAT(r.replacement(), load_field_match); - - HeapObjectMatcher<PropertyCell> cell(cell_capture.value()); - EXPECT_TRUE(cell.HasValue()); - EXPECT_TRUE(cell.Value().handle()->IsPropertyCell()); - - EXPECT_THAT( - ret, IsReturn(load_field_match, load_field_match, graph()->start())); - EXPECT_THAT(graph()->end(), IsEnd(ret)); - - EXPECT_FALSE(dependencies()->IsEmpty()); - dependencies()->Rollback(); - } else { - ASSERT_FALSE(r.Changed()); - EXPECT_TRUE(dependencies()->IsEmpty()); - } - } +TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstStringWithDeoptimization) { + Unique<HeapObject> kValue = Unique<HeapObject>::CreateImmovable( + isolate()->factory()->undefined_string()); + const char* kName = "mango"; + SetGlobalProperty(kName, kValue.handle()); + + Node* ret = ReturnLoadNamedFromGlobal( + kName, graph()->start(), graph()->start(), + JSTypeFeedbackSpecializer::kDeoptimizationEnabled); + graph()->SetEnd(graph()->NewNode(common()->End(1), ret)); + + Reduction r = Reduce(ret->InputAt(0), + JSTypeFeedbackSpecializer::kDeoptimizationEnabled); + + // Check LoadNamed(global) => HeapConstant[kValue] + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsHeapConstant(kValue)); + + EXPECT_THAT(ret, IsReturn(IsHeapConstant(kValue), graph()->start(), + graph()->start())); + EXPECT_THAT(graph()->end(), IsEnd(ret)); + + EXPECT_FALSE(dependencies()->IsEmpty()); + dependencies()->Rollback(); } -TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCell_string) { - const char* property_name = "pineapple"; - SetGlobalProperty(property_name, isolate()->factory()->undefined_string()); - SetGlobalProperty(property_name, isolate()->factory()->undefined_value()); - - WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION { - Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(), - graph()->start()); - graph()->SetEnd(graph()->NewNode(common()->End(), ret)); - - Reduction r = Reduce(ret->InputAt(0)); - - if (FLAG_turbo_deoptimization) { - // Check LoadNamed(global) => LoadField[PropertyCell::value](cell) - ASSERT_TRUE(r.Changed()); - FieldAccess access = AccessBuilder::ForPropertyCellValue(); - Capture<Node*> cell_capture; - Matcher<Node*> load_field_match = IsLoadField( - access, CaptureEq(&cell_capture), graph()->start(), graph()->start()); - EXPECT_THAT(r.replacement(), load_field_match); - - HeapObjectMatcher<PropertyCell> cell(cell_capture.value()); - EXPECT_TRUE(cell.HasValue()); - EXPECT_TRUE(cell.Value().handle()->IsPropertyCell()); - - EXPECT_THAT( - ret, IsReturn(load_field_match, load_field_match, graph()->start())); - EXPECT_THAT(graph()->end(), IsEnd(ret)); - - EXPECT_FALSE(dependencies()->IsEmpty()); - dependencies()->Rollback(); - } else { - ASSERT_FALSE(r.Changed()); - EXPECT_TRUE(dependencies()->IsEmpty()); - } - } +TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellSmi) { + const char* kName = "melon"; + SetGlobalProperty(kName, 123); + SetGlobalProperty(kName, 124); + + Node* ret = ReturnLoadNamedFromGlobal( + kName, graph()->start(), graph()->start(), + JSTypeFeedbackSpecializer::kDeoptimizationDisabled); + graph()->SetEnd(graph()->NewNode(common()->End(1), ret)); + + Reduction r = Reduce(ret->InputAt(0), + JSTypeFeedbackSpecializer::kDeoptimizationDisabled); + ASSERT_FALSE(r.Changed()); + EXPECT_TRUE(dependencies()->IsEmpty()); } + + +TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellSmiWithDeoptimization) { + const char* kName = "melon"; + SetGlobalProperty(kName, 123); + SetGlobalProperty(kName, 124); + + Node* ret = ReturnLoadNamedFromGlobal( + kName, graph()->start(), graph()->start(), + JSTypeFeedbackSpecializer::kDeoptimizationEnabled); + graph()->SetEnd(graph()->NewNode(common()->End(1), ret)); + + Reduction r = Reduce(ret->InputAt(0), + JSTypeFeedbackSpecializer::kDeoptimizationEnabled); + + // Check LoadNamed(global) => LoadField[PropertyCell::value](cell) + ASSERT_TRUE(r.Changed()); + FieldAccess access = AccessBuilder::ForPropertyCellValue(); + Capture<Node*> cell_capture; + Matcher<Node*> load_field_match = IsLoadField( + access, CaptureEq(&cell_capture), graph()->start(), graph()->start()); + EXPECT_THAT(r.replacement(), load_field_match); + + HeapObjectMatcher cell(cell_capture.value()); + EXPECT_TRUE(cell.HasValue()); + EXPECT_TRUE(cell.Value().handle()->IsPropertyCell()); + + EXPECT_THAT(ret, + IsReturn(load_field_match, load_field_match, graph()->start())); + EXPECT_THAT(graph()->end(), IsEnd(ret)); + + EXPECT_FALSE(dependencies()->IsEmpty()); + dependencies()->Rollback(); } + + +TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellString) { + const char* kName = "pineapple"; + SetGlobalProperty(kName, isolate()->factory()->undefined_string()); + SetGlobalProperty(kName, isolate()->factory()->undefined_value()); + + Node* ret = ReturnLoadNamedFromGlobal( + kName, graph()->start(), graph()->start(), + JSTypeFeedbackSpecializer::kDeoptimizationDisabled); + graph()->SetEnd(graph()->NewNode(common()->End(1), ret)); + + Reduction r = Reduce(ret->InputAt(0), + JSTypeFeedbackSpecializer::kDeoptimizationDisabled); + ASSERT_FALSE(r.Changed()); + EXPECT_TRUE(dependencies()->IsEmpty()); } + + +TEST_F(JSTypeFeedbackTest, + JSLoadNamedGlobalPropertyCellStringWithDeoptimization) { + const char* kName = "pineapple"; + SetGlobalProperty(kName, isolate()->factory()->undefined_string()); + SetGlobalProperty(kName, isolate()->factory()->undefined_value()); + + Node* ret = ReturnLoadNamedFromGlobal( + kName, graph()->start(), graph()->start(), + JSTypeFeedbackSpecializer::kDeoptimizationEnabled); + graph()->SetEnd(graph()->NewNode(common()->End(1), ret)); + + Reduction r = Reduce(ret->InputAt(0), + JSTypeFeedbackSpecializer::kDeoptimizationEnabled); + + // Check LoadNamed(global) => LoadField[PropertyCell::value](cell) + ASSERT_TRUE(r.Changed()); + FieldAccess access = AccessBuilder::ForPropertyCellValue(); + Capture<Node*> cell_capture; + Matcher<Node*> load_field_match = IsLoadField( + access, CaptureEq(&cell_capture), graph()->start(), graph()->start()); + EXPECT_THAT(r.replacement(), load_field_match); + + HeapObjectMatcher cell(cell_capture.value()); + EXPECT_TRUE(cell.HasValue()); + EXPECT_TRUE(cell.Value().handle()->IsPropertyCell()); + + EXPECT_THAT(ret, + IsReturn(load_field_match, load_field_match, graph()->start())); + EXPECT_THAT(graph()->end(), IsEnd(ret)); + + EXPECT_FALSE(dependencies()->IsEmpty()); + dependencies()->Rollback(); } + +} // namespace compiler +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc b/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc index 9e7b1eecbd..a12d79f02b 100644 --- a/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc +++ b/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc @@ -80,16 +80,12 @@ class JSTypedLoweringTest : public TypedGraphTest { Reduction Reduce(Node* node) { MachineOperatorBuilder machine(zone()); JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine); - JSTypedLowering reducer(&jsgraph, zone()); + // TODO(titzer): mock the GraphReducer here for better unit testing. + GraphReducer graph_reducer(zone(), graph()); + JSTypedLowering reducer(&graph_reducer, &jsgraph, zone()); return reducer.Reduce(node); } - Node* EmptyFrameState() { - MachineOperatorBuilder machine(zone()); - JSGraph jsgraph(isolate(), graph(), common(), javascript(), &machine); - return jsgraph.EmptyFrameState(); - } - Handle<JSArrayBuffer> NewArrayBuffer(void* bytes, size_t byte_length) { Handle<JSArrayBuffer> buffer = factory()->NewJSArrayBuffer(); Runtime::SetupArrayBuffer(isolate(), buffer, true, bytes, byte_length); @@ -434,18 +430,27 @@ TEST_F(JSTypedLoweringTest, JSToNumberWithPlainPrimitive) { TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) { Node* const the_hole = HeapConstant(factory()->the_hole_value()); Node* const context = UndefinedConstant(); - Node* const effect = graph()->start(); - Node* const control = graph()->start(); TRACED_FOREACH(Type*, type, kJSTypes) { Node* const lhs = Parameter(type); - Reduction r = Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, - the_hole, context, effect, control)); + Reduction r = Reduce( + graph()->NewNode(javascript()->StrictEqual(), lhs, the_hole, context)); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsFalseConstant()); } } +TEST_F(JSTypedLoweringTest, JSStrictEqualWithUnique) { + Node* const lhs = Parameter(Type::Unique(), 0); + Node* const rhs = Parameter(Type::Unique(), 1); + Node* const context = Parameter(Type::Any(), 2); + Reduction r = + Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, rhs, context)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsReferenceEqual(Type::Unique(), lhs, rhs)); +} + + // ----------------------------------------------------------------------------- // JSShiftLeft @@ -457,13 +462,12 @@ TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndConstant) { Node* const control = graph()->start(); TRACED_FORRANGE(double, rhs, 0, 31) { TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { - Reduction r = - Reduce(graph()->NewNode(javascript()->ShiftLeft(language_mode), lhs, - NumberConstant(rhs), context, effect, - control)); + Reduction r = Reduce(graph()->NewNode( + javascript()->ShiftLeft(language_mode), lhs, NumberConstant(rhs), + context, EmptyFrameState(), EmptyFrameState(), effect, control)); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), - IsWord32Shl(lhs, IsNumberConstant(BitEq(rhs)))); + IsNumberShiftLeft(lhs, IsNumberConstant(BitEq(rhs)))); } } } @@ -476,12 +480,11 @@ TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndUnsigned32) { Node* const effect = graph()->start(); Node* const control = graph()->start(); TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { - Reduction r = - Reduce(graph()->NewNode(javascript()->ShiftLeft(language_mode), lhs, - rhs, context, effect, control)); + Reduction r = Reduce(graph()->NewNode( + javascript()->ShiftLeft(language_mode), lhs, rhs, context, + EmptyFrameState(), EmptyFrameState(), effect, control)); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), - IsWord32Shl(lhs, IsWord32And(rhs, IsInt32Constant(0x1f)))); + EXPECT_THAT(r.replacement(), IsNumberShiftLeft(lhs, rhs)); } } @@ -497,13 +500,12 @@ TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndConstant) { Node* const control = graph()->start(); TRACED_FORRANGE(double, rhs, 0, 31) { TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { - Reduction r = - Reduce(graph()->NewNode(javascript()-> ShiftRight(language_mode), lhs, - NumberConstant(rhs), context, effect, - control)); + Reduction r = Reduce(graph()->NewNode( + javascript()->ShiftRight(language_mode), lhs, NumberConstant(rhs), + context, EmptyFrameState(), EmptyFrameState(), effect, control)); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), - IsWord32Sar(lhs, IsNumberConstant(BitEq(rhs)))); + IsNumberShiftRight(lhs, IsNumberConstant(BitEq(rhs)))); } } } @@ -516,12 +518,11 @@ TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndUnsigned32) { Node* const effect = graph()->start(); Node* const control = graph()->start(); TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { - Reduction r = Reduce(graph()->NewNode(javascript()-> - ShiftRight(language_mode), lhs, rhs, - context, effect, control)); + Reduction r = Reduce(graph()->NewNode( + javascript()->ShiftRight(language_mode), lhs, rhs, context, + EmptyFrameState(), EmptyFrameState(), effect, control)); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), - IsWord32Sar(lhs, IsWord32And(rhs, IsInt32Constant(0x1f)))); + EXPECT_THAT(r.replacement(), IsNumberShiftRight(lhs, rhs)); } } @@ -538,14 +539,13 @@ TEST_F(JSTypedLoweringTest, Node* const control = graph()->start(); TRACED_FORRANGE(double, rhs, 0, 31) { TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { - Reduction r = - Reduce(graph()->NewNode(javascript()-> - ShiftRightLogical(language_mode), lhs, - NumberConstant(rhs), context, effect, - control)); + Reduction r = Reduce( + graph()->NewNode(javascript()->ShiftRightLogical(language_mode), lhs, + NumberConstant(rhs), context, EmptyFrameState(), + EmptyFrameState(), effect, control)); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), - IsWord32Shr(lhs, IsNumberConstant(BitEq(rhs)))); + IsNumberShiftRightLogical(lhs, IsNumberConstant(BitEq(rhs)))); } } } @@ -559,12 +559,11 @@ TEST_F(JSTypedLoweringTest, Node* const effect = graph()->start(); Node* const control = graph()->start(); TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { - Reduction r = Reduce(graph()->NewNode(javascript()-> - ShiftRightLogical(language_mode), lhs, - rhs, context, effect, control)); + Reduction r = Reduce(graph()->NewNode( + javascript()->ShiftRightLogical(language_mode), lhs, rhs, context, + EmptyFrameState(), EmptyFrameState(), effect, control)); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), - IsWord32Shr(lhs, IsWord32And(rhs, IsInt32Constant(0x1f)))); + EXPECT_THAT(r.replacement(), IsNumberShiftRightLogical(lhs, rhs)); } } @@ -646,36 +645,39 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) { double backing_store[kLength]; Handle<JSArrayBuffer> buffer = NewArrayBuffer(backing_store, sizeof(backing_store)); - VectorSlotPair feedback(Handle<TypeFeedbackVector>::null(), - FeedbackVectorICSlot::Invalid()); + VectorSlotPair feedback; TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) { - Handle<JSTypedArray> array = - factory()->NewJSTypedArray(type, buffer, 0, kLength); - int const element_size = static_cast<int>(array->element_size()); - - Node* key = Parameter( - Type::Range(kMinInt / element_size, kMaxInt / element_size, zone())); - Node* base = HeapConstant(array); - Node* context = UndefinedConstant(); - Node* effect = graph()->start(); - Node* control = graph()->start(); - Reduction r = - Reduce(graph()->NewNode(javascript()->LoadProperty(feedback), base, key, - context, EmptyFrameState(), effect, control)); + TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { + Handle<JSTypedArray> array = + factory()->NewJSTypedArray(type, buffer, 0, kLength); + int const element_size = static_cast<int>(array->element_size()); + + Node* key = Parameter( + Type::Range(kMinInt / element_size, kMaxInt / element_size, zone())); + Node* base = HeapConstant(array); + Node* vector = UndefinedConstant(); + Node* context = UndefinedConstant(); + Node* effect = graph()->start(); + Node* control = graph()->start(); + Reduction r = Reduce( + graph()->NewNode(javascript()->LoadProperty(feedback, language_mode), + base, key, vector, context, EmptyFrameState(), + EmptyFrameState(), effect, control)); - Matcher<Node*> offset_matcher = - element_size == 1 - ? key - : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size))); + Matcher<Node*> offset_matcher = + element_size == 1 + ? key + : IsWord32Shl(key, IsInt32Constant(WhichPowerOf2(element_size))); - ASSERT_TRUE(r.Changed()); - EXPECT_THAT( - r.replacement(), - IsLoadBuffer(BufferAccess(type), - IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])), - offset_matcher, - IsNumberConstant(array->byte_length()->Number()), effect, - control)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT( + r.replacement(), + IsLoadBuffer(BufferAccess(type), + IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])), + offset_matcher, + IsNumberConstant(array->byte_length()->Number()), effect, + control)); + } } } @@ -685,31 +687,34 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArrayWithSafeKey) { double backing_store[kLength]; Handle<JSArrayBuffer> buffer = NewArrayBuffer(backing_store, sizeof(backing_store)); - VectorSlotPair feedback(Handle<TypeFeedbackVector>::null(), - FeedbackVectorICSlot::Invalid()); + VectorSlotPair feedback; TRACED_FOREACH(ExternalArrayType, type, kExternalArrayTypes) { - Handle<JSTypedArray> array = - factory()->NewJSTypedArray(type, buffer, 0, kLength); - ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true); - - int min = random_number_generator()->NextInt(static_cast<int>(kLength)); - int max = random_number_generator()->NextInt(static_cast<int>(kLength)); - if (min > max) std::swap(min, max); - Node* key = Parameter(Type::Range(min, max, zone())); - Node* base = HeapConstant(array); - Node* context = UndefinedConstant(); - Node* effect = graph()->start(); - Node* control = graph()->start(); - Reduction r = - Reduce(graph()->NewNode(javascript()->LoadProperty(feedback), base, key, - context, EmptyFrameState(), effect, control)); + TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { + Handle<JSTypedArray> array = + factory()->NewJSTypedArray(type, buffer, 0, kLength); + ElementAccess access = AccessBuilder::ForTypedArrayElement(type, true); - ASSERT_TRUE(r.Changed()); - EXPECT_THAT( - r.replacement(), - IsLoadElement(access, - IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])), - key, effect, control)); + int min = random_number_generator()->NextInt(static_cast<int>(kLength)); + int max = random_number_generator()->NextInt(static_cast<int>(kLength)); + if (min > max) std::swap(min, max); + Node* key = Parameter(Type::Range(min, max, zone())); + Node* base = HeapConstant(array); + Node* vector = UndefinedConstant(); + Node* context = UndefinedConstant(); + Node* effect = graph()->start(); + Node* control = graph()->start(); + Reduction r = Reduce( + graph()->NewNode(javascript()->LoadProperty(feedback, language_mode), + base, key, vector, context, EmptyFrameState(), + EmptyFrameState(), effect, control)); + + ASSERT_TRUE(r.Changed()); + EXPECT_THAT( + r.replacement(), + IsLoadElement(access, + IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])), + key, effect, control)); + } } } @@ -734,11 +739,13 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArray) { Node* base = HeapConstant(array); Node* value = Parameter(AccessBuilder::ForTypedArrayElement(type, true).type); + Node* vector = UndefinedConstant(); Node* context = UndefinedConstant(); Node* effect = graph()->start(); Node* control = graph()->start(); - Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode), - base, key, value, context); + VectorSlotPair feedback; + const Operator* op = javascript()->StoreProperty(language_mode, feedback); + Node* node = graph()->NewNode(op, base, key, value, vector, context); for (int i = 0; i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) { node->AppendInput(zone(), EmptyFrameState()); @@ -780,11 +787,13 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithConversion) { Type::Range(kMinInt / element_size, kMaxInt / element_size, zone())); Node* base = HeapConstant(array); Node* value = Parameter(Type::Any()); + Node* vector = UndefinedConstant(); Node* context = UndefinedConstant(); Node* effect = graph()->start(); Node* control = graph()->start(); - Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode), - base, key, value, context); + VectorSlotPair feedback; + const Operator* op = javascript()->StoreProperty(language_mode, feedback); + Node* node = graph()->NewNode(op, base, key, value, vector, context); for (int i = 0; i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) { node->AppendInput(zone(), EmptyFrameState()); @@ -839,11 +848,13 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithSafeKey) { Node* key = Parameter(Type::Range(min, max, zone())); Node* base = HeapConstant(array); Node* value = Parameter(access.type); + Node* vector = UndefinedConstant(); Node* context = UndefinedConstant(); Node* effect = graph()->start(); Node* control = graph()->start(); - Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode), - base, key, value, context); + VectorSlotPair feedback; + const Operator* op = javascript()->StoreProperty(language_mode, feedback); + Node* node = graph()->NewNode(op, base, key, value, vector, context); for (int i = 0; i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) { node->AppendInput(zone(), EmptyFrameState()); @@ -876,18 +887,18 @@ TEST_F(JSTypedLoweringTest, JSLoadNamedGlobalConstants) { IsNumberConstant(IsNaN()) // -- }; - VectorSlotPair feedback(Handle<TypeFeedbackVector>::null(), - FeedbackVectorICSlot::Invalid()); - Node* global = Parameter(Type::GlobalObject()); + VectorSlotPair feedback; + Node* global = UndefinedConstant(); + Node* vector = UndefinedConstant(); Node* context = UndefinedConstant(); Node* effect = graph()->start(); Node* control = graph()->start(); for (size_t i = 0; i < arraysize(names); i++) { Unique<Name> name = Unique<Name>::CreateImmovable(names[i]); - Reduction r = - Reduce(graph()->NewNode(javascript()->LoadNamed(name, feedback), global, - context, EmptyFrameState(), effect, control)); + Reduction r = Reduce(graph()->NewNode( + javascript()->LoadGlobal(name, feedback), global, vector, context, + EmptyFrameState(), EmptyFrameState(), effect, control)); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), matches[i]); @@ -896,9 +907,106 @@ TEST_F(JSTypedLoweringTest, JSLoadNamedGlobalConstants) { // ----------------------------------------------------------------------------- -// JSCreateClosure +// JSLoadDynamicGlobal + + +TEST_F(JSTypedLoweringTest, JSLoadDynamicGlobal) { + Node* const context = Parameter(Type::Any()); + Node* const vector = UndefinedConstant(); + Node* const frame_state = EmptyFrameState(); + Node* const effect = graph()->start(); + Node* const control = graph()->start(); + Handle<String> name = factory()->object_string(); + VectorSlotPair feedback; + for (int i = 0; i < DynamicGlobalAccess::kMaxCheckDepth; ++i) { + uint32_t bitset = 1 << i; // Only single check. + Reduction r = Reduce(graph()->NewNode( + javascript()->LoadDynamicGlobal(name, bitset, feedback, NOT_CONTEXTUAL), + vector, context, context, frame_state, frame_state, effect, control)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT( + r.replacement(), + IsPhi(kMachAnyTagged, _, _, + IsMerge( + IsIfTrue(IsBranch( + IsReferenceEqual( + Type::Tagged(), + IsLoadContext( + ContextAccess(i, Context::EXTENSION_INDEX, false), + context), + IsNumberConstant(BitEq(0.0))), + control)), + _))); + } +} + + +// ----------------------------------------------------------------------------- +// JSLoadDynamicContext + + +TEST_F(JSTypedLoweringTest, JSLoadDynamicContext) { + Node* const context = Parameter(Type::Any()); + Node* const frame_state = EmptyFrameState(); + Node* const effect = graph()->start(); + Node* const control = graph()->start(); + Handle<String> name = factory()->object_string(); + for (int i = 0; i < DynamicContextAccess::kMaxCheckDepth; ++i) { + uint32_t bitset = 1 << i; // Only single check. + Reduction r = Reduce( + graph()->NewNode(javascript()->LoadDynamicContext(name, bitset, 23, 42), + context, context, frame_state, effect, control)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT( + r.replacement(), + IsPhi(kMachAnyTagged, + IsLoadContext(ContextAccess(23, 42, false), context), _, + IsMerge( + IsIfTrue(IsBranch( + IsReferenceEqual( + Type::Tagged(), + IsLoadContext( + ContextAccess(i, Context::EXTENSION_INDEX, false), + context), + IsNumberConstant(BitEq(0.0))), + control)), + _))); + } +} #if V8_TURBOFAN_TARGET + +// ----------------------------------------------------------------------------- +// JSAdd + + +TEST_F(JSTypedLoweringTest, JSAddWithString) { + TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { + Node* lhs = Parameter(Type::String(), 0); + Node* rhs = Parameter(Type::String(), 1); + Node* context = Parameter(Type::Any(), 2); + Node* frame_state0 = EmptyFrameState(); + Node* frame_state1 = EmptyFrameState(); + Node* effect = graph()->start(); + Node* control = graph()->start(); + Reduction r = Reduce(graph()->NewNode(javascript()->Add(language_mode), lhs, + rhs, context, frame_state0, + frame_state1, effect, control)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT( + r.replacement(), + IsCall(_, IsHeapConstant(Unique<HeapObject>::CreateImmovable( + CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, + NOT_TENURED).code())), + lhs, rhs, context, frame_state0, effect, control)); + } +} + + +// ----------------------------------------------------------------------------- +// JSCreateClosure + + TEST_F(JSTypedLoweringTest, JSCreateClosure) { Node* const context = UndefinedConstant(); Node* const effect = graph()->start(); @@ -965,7 +1073,8 @@ TEST_F(JSTypedLoweringTest, JSCreateLiteralObject) { CodeFactory::FastCloneShallowObject(isolate(), 6).code())), input0, input1, input2, _, context, frame_state, effect, control)); } -#endif + +#endif // V8_TURBOFAN_TARGET // ----------------------------------------------------------------------------- diff --git a/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc b/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc index d5a95ccd1d..1e142550d5 100644 --- a/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc +++ b/deps/v8/test/unittests/compiler/liveness-analyzer-unittest.cc @@ -57,8 +57,13 @@ class LivenessAnalysisTest : public GraphTest { Node* locals = graph()->NewNode(locals_op, locals_count_, &local_inputs.front()); + const FrameStateFunctionInfo* state_info = + common()->CreateFrameStateFunctionInfo( + FrameStateType::kJavaScriptFunction, 0, locals_count_, + Handle<SharedFunctionInfo>()); + const Operator* op = common()->FrameState( - JS_FRAME, BailoutId(ast_num), OutputFrameStateCombine::Ignore()); + BailoutId(ast_num), OutputFrameStateCombine::Ignore(), state_info); Node* result = graph()->NewNode(op, empty_values_, locals, empty_values_, jsgraph()->UndefinedConstant(), jsgraph()->UndefinedConstant()); @@ -93,8 +98,7 @@ class LivenessAnalysisTest : public GraphTest { } DCHECK(frame_state->opcode() == IrOpcode::kFrameState); - FrameStateCallInfo state_info = - OpParameter<FrameStateCallInfo>(frame_state); + FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); int ast_num = state_info.bailout_id().ToInt(); int first_const = intconst_from_bailout_id(ast_num, locals_count_); diff --git a/deps/v8/test/unittests/compiler/load-elimination-unittest.cc b/deps/v8/test/unittests/compiler/load-elimination-unittest.cc index 52c3143e2a..3ad11cf43f 100644 --- a/deps/v8/test/unittests/compiler/load-elimination-unittest.cc +++ b/deps/v8/test/unittests/compiler/load-elimination-unittest.cc @@ -19,7 +19,9 @@ class LoadEliminationTest : public GraphTest { protected: Reduction Reduce(Node* node) { - LoadElimination reducer; + // TODO(titzer): mock the GraphReducer here for better unit testing. + GraphReducer graph_reducer(zone(), graph()); + LoadElimination reducer(&graph_reducer); return reducer.Reduce(node); } diff --git a/deps/v8/test/unittests/compiler/loop-peeling-unittest.cc b/deps/v8/test/unittests/compiler/loop-peeling-unittest.cc index d3eff716a7..c725a27cc0 100644 --- a/deps/v8/test/unittests/compiler/loop-peeling-unittest.cc +++ b/deps/v8/test/unittests/compiler/loop-peeling-unittest.cc @@ -478,7 +478,8 @@ TEST_F(LoopPeelingTest, TwoExitLoopWithCall_nope) { Node* call = graph()->NewNode(&kMockCall, b1.if_true); Node* if_success = graph()->NewNode(common()->IfSuccess(), call); - Node* if_exception = graph()->NewNode(common()->IfException(), call); + Node* if_exception = graph()->NewNode( + common()->IfException(IfExceptionHint::kLocallyUncaught), call); loop->ReplaceInput(1, if_success); Node* merge = graph()->NewNode(common()->Merge(2), b1.if_false, if_exception); diff --git a/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc b/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc index 9836be4fb2..ce11fdef81 100644 --- a/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc +++ b/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc @@ -234,6 +234,10 @@ const uint32_t kUint32Values[] = { 0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff}; +const TruncationMode kTruncationModes[] = {TruncationMode::kJavaScript, + TruncationMode::kRoundToZero}; + + struct ComparisonBinaryOperator { const Operator* (MachineOperatorBuilder::*constructor)(); const char* constructor_name; @@ -258,53 +262,6 @@ const ComparisonBinaryOperator kComparisonBinaryOperators[] = { // ----------------------------------------------------------------------------- -// Unary operators - - -namespace { - -struct UnaryOperator { - const Operator* (MachineOperatorBuilder::*constructor)(); - const char* constructor_name; -}; - - -std::ostream& operator<<(std::ostream& os, const UnaryOperator& unop) { - return os << unop.constructor_name; -} - - -static const UnaryOperator kUnaryOperators[] = { - {&MachineOperatorBuilder::ChangeInt32ToFloat64, "ChangeInt32ToFloat64"}, - {&MachineOperatorBuilder::ChangeUint32ToFloat64, "ChangeUint32ToFloat64"}, - {&MachineOperatorBuilder::ChangeFloat64ToInt32, "ChangeFloat64ToInt32"}, - {&MachineOperatorBuilder::ChangeFloat64ToUint32, "ChangeFloat64ToUint32"}, - {&MachineOperatorBuilder::ChangeInt32ToInt64, "ChangeInt32ToInt64"}, - {&MachineOperatorBuilder::ChangeUint32ToUint64, "ChangeUint32ToUint64"}, - {&MachineOperatorBuilder::TruncateFloat64ToInt32, "TruncateFloat64ToInt32"}, - {&MachineOperatorBuilder::TruncateInt64ToInt32, "TruncateInt64ToInt32"}}; - -} // namespace - - -typedef MachineOperatorReducerTestWithParam<UnaryOperator> - MachineUnaryOperatorReducerTest; - - -TEST_P(MachineUnaryOperatorReducerTest, Parameter) { - const UnaryOperator unop = GetParam(); - Reduction reduction = - Reduce(graph()->NewNode((machine()->*unop.constructor)(), Parameter(0))); - EXPECT_FALSE(reduction.Changed()); -} - - -INSTANTIATE_TEST_CASE_P(MachineOperatorReducerTest, - MachineUnaryOperatorReducerTest, - ::testing::ValuesIn(kUnaryOperators)); - - -// ----------------------------------------------------------------------------- // ChangeFloat64ToFloat32 @@ -459,19 +416,22 @@ TEST_F(MachineOperatorReducerTest, TruncateFloat64ToFloat32WithConstant) { TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithChangeInt32ToFloat64) { - Node* value = Parameter(0); - Reduction reduction = Reduce(graph()->NewNode( - machine()->TruncateFloat64ToInt32(), - graph()->NewNode(machine()->ChangeInt32ToFloat64(), value))); - ASSERT_TRUE(reduction.Changed()); - EXPECT_EQ(value, reduction.replacement()); + TRACED_FOREACH(TruncationMode, mode, kTruncationModes) { + Node* value = Parameter(0); + Reduction reduction = Reduce(graph()->NewNode( + machine()->TruncateFloat64ToInt32(mode), + graph()->NewNode(machine()->ChangeInt32ToFloat64(), value))); + ASSERT_TRUE(reduction.Changed()); + EXPECT_EQ(value, reduction.replacement()); + } } TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithConstant) { TRACED_FOREACH(double, x, kFloat64Values) { Reduction reduction = Reduce(graph()->NewNode( - machine()->TruncateFloat64ToInt32(), Float64Constant(x))); + machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript), + Float64Constant(x))); ASSERT_TRUE(reduction.Changed()); EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x))); } @@ -482,13 +442,15 @@ TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithPhi) { Node* const p0 = Parameter(0); Node* const p1 = Parameter(1); Node* const merge = graph()->start(); - Reduction reduction = Reduce(graph()->NewNode( - machine()->TruncateFloat64ToInt32(), - graph()->NewNode(common()->Phi(kMachFloat64, 2), p0, p1, merge))); - ASSERT_TRUE(reduction.Changed()); - EXPECT_THAT(reduction.replacement(), - IsPhi(kMachInt32, IsTruncateFloat64ToInt32(p0), - IsTruncateFloat64ToInt32(p1), merge)); + TRACED_FOREACH(TruncationMode, mode, kTruncationModes) { + Reduction reduction = Reduce(graph()->NewNode( + machine()->TruncateFloat64ToInt32(mode), + graph()->NewNode(common()->Phi(kMachFloat64, 2), p0, p1, merge))); + ASSERT_TRUE(reduction.Changed()); + EXPECT_THAT(reduction.replacement(), + IsPhi(kMachInt32, IsTruncateFloat64ToInt32(p0), + IsTruncateFloat64ToInt32(p1), merge)); + } } diff --git a/deps/v8/test/unittests/compiler/machine-operator-unittest.cc b/deps/v8/test/unittests/compiler/machine-operator-unittest.cc index 31f55793c3..fca53e2bd8 100644 --- a/deps/v8/test/unittests/compiler/machine-operator-unittest.cc +++ b/deps/v8/test/unittests/compiler/machine-operator-unittest.cc @@ -149,130 +149,199 @@ INSTANTIATE_TEST_CASE_P( ::testing::Combine(::testing::ValuesIn(kMachineTypes), ::testing::Values(kNoWriteBarrier, kFullWriteBarrier)))); - +#endif // ----------------------------------------------------------------------------- // Pure operators. - namespace { struct PureOperator { const Operator* (MachineOperatorBuilder::*constructor)(); - IrOpcode::Value opcode; + char const* const constructor_name; int value_input_count; int control_input_count; int value_output_count; }; -std::ostream& operator<<(std::ostream& os, const PureOperator& pop) { - return os << IrOpcode::Mnemonic(pop.opcode); +std::ostream& operator<<(std::ostream& os, PureOperator const& pop) { + return os << pop.constructor_name; } - const PureOperator kPureOperators[] = { #define PURE(Name, value_input_count, control_input_count, value_output_count) \ { \ - &MachineOperatorBuilder::Name, IrOpcode::k##Name, value_input_count, \ + &MachineOperatorBuilder::Name, #Name, value_input_count, \ control_input_count, value_output_count \ } - PURE(Word32And, 2, 0, 1), PURE(Word32Or, 2, 0, 1), PURE(Word32Xor, 2, 0, 1), - PURE(Word32Shl, 2, 0, 1), PURE(Word32Shr, 2, 0, 1), - PURE(Word32Sar, 2, 0, 1), PURE(Word32Ror, 2, 0, 1), - PURE(Word32Equal, 2, 0, 1), PURE(Word32Clz, 1, 0, 1), - PURE(Word64And, 2, 0, 1), PURE(Word64Or, 2, 0, 1), PURE(Word64Xor, 2, 0, 1), - PURE(Word64Shl, 2, 0, 1), PURE(Word64Shr, 2, 0, 1), - PURE(Word64Sar, 2, 0, 1), PURE(Word64Ror, 2, 0, 1), - PURE(Word64Equal, 2, 0, 1), PURE(Int32Add, 2, 0, 1), - PURE(Int32AddWithOverflow, 2, 0, 2), PURE(Int32Sub, 2, 0, 1), - PURE(Int32SubWithOverflow, 2, 0, 2), PURE(Int32Mul, 2, 0, 1), - PURE(Int32MulHigh, 2, 0, 1), PURE(Int32Div, 2, 1, 1), - PURE(Uint32Div, 2, 1, 1), PURE(Int32Mod, 2, 1, 1), PURE(Uint32Mod, 2, 1, 1), - PURE(Int32LessThan, 2, 0, 1), PURE(Int32LessThanOrEqual, 2, 0, 1), - PURE(Uint32LessThan, 2, 0, 1), PURE(Uint32LessThanOrEqual, 2, 0, 1), - PURE(Int64Add, 2, 0, 1), PURE(Int64Sub, 2, 0, 1), PURE(Int64Mul, 2, 0, 1), - PURE(Int64Div, 2, 0, 1), PURE(Uint64Div, 2, 0, 1), PURE(Int64Mod, 2, 0, 1), - PURE(Uint64Mod, 2, 0, 1), PURE(Int64LessThan, 2, 0, 1), - PURE(Int64LessThanOrEqual, 2, 0, 1), PURE(Uint64LessThan, 2, 0, 1), - PURE(ChangeFloat32ToFloat64, 1, 0, 1), PURE(ChangeFloat64ToInt32, 1, 0, 1), - PURE(ChangeFloat64ToUint32, 1, 0, 1), PURE(ChangeInt32ToInt64, 1, 0, 1), - PURE(ChangeUint32ToFloat64, 1, 0, 1), PURE(ChangeUint32ToUint64, 1, 0, 1), - PURE(TruncateFloat64ToFloat32, 1, 0, 1), - PURE(TruncateFloat64ToInt32, 1, 0, 1), PURE(TruncateInt64ToInt32, 1, 0, 1), - PURE(Float32Add, 2, 0, 1), PURE(Float32Sub, 2, 0, 1), - PURE(Float32Mul, 2, 0, 1), PURE(Float32Div, 2, 0, 1), - PURE(Float32Abs, 1, 0, 1), PURE(Float32Sqrt, 1, 0, 1), - PURE(Float32Equal, 2, 0, 1), PURE(Float32LessThan, 2, 0, 1), - PURE(Float32LessThanOrEqual, 2, 0, 1), PURE(Float32Max, 2, 0, 1), - PURE(Float32Min, 2, 0, 1), PURE(Float64Add, 2, 0, 1), - PURE(Float64Sub, 2, 0, 1), PURE(Float64Mul, 2, 0, 1), - PURE(Float64Div, 2, 0, 1), PURE(Float64Mod, 2, 0, 1), - PURE(Float64Abs, 1, 0, 1), PURE(Float64Sqrt, 1, 0, 1), - PURE(Float64Equal, 2, 0, 1), PURE(Float64LessThan, 2, 0, 1), - PURE(Float64LessThanOrEqual, 2, 0, 1), PURE(Float64Max, 2, 0, 1), - PURE(Float64Min, 2, 0, 1), PURE(LoadStackPointer, 0, 0, 1), - PURE(Float64RoundDown, 1, 0, 1), PURE(Float64RoundTruncate, 1, 0, 1), - PURE(Float64RoundTiesAway, 1, 0, 1), PURE(Float64ExtractLowWord32, 1, 0, 1), - PURE(Float64ExtractHighWord32, 1, 0, 1), - PURE(Float64InsertLowWord32, 2, 0, 1), - PURE(Float64InsertHighWord32, 2, 0, 1) + PURE(Word32And, 2, 0, 1), // -- + PURE(Word32Or, 2, 0, 1), // -- + PURE(Word32Xor, 2, 0, 1), // -- + PURE(Word32Shl, 2, 0, 1), // -- + PURE(Word32Shr, 2, 0, 1), // -- + PURE(Word32Sar, 2, 0, 1), // -- + PURE(Word32Ror, 2, 0, 1), // -- + PURE(Word32Equal, 2, 0, 1), // -- + PURE(Word32Clz, 1, 0, 1), // -- + PURE(Word64And, 2, 0, 1), // -- + PURE(Word64Or, 2, 0, 1), // -- + PURE(Word64Xor, 2, 0, 1), // -- + PURE(Word64Shl, 2, 0, 1), // -- + PURE(Word64Shr, 2, 0, 1), // -- + PURE(Word64Sar, 2, 0, 1), // -- + PURE(Word64Ror, 2, 0, 1), // -- + PURE(Word64Equal, 2, 0, 1), // -- + PURE(Int32Add, 2, 0, 1), // -- + PURE(Int32AddWithOverflow, 2, 0, 2), // -- + PURE(Int32Sub, 2, 0, 1), // -- + PURE(Int32SubWithOverflow, 2, 0, 2), // -- + PURE(Int32Mul, 2, 0, 1), // -- + PURE(Int32MulHigh, 2, 0, 1), // -- + PURE(Int32Div, 2, 1, 1), // -- + PURE(Uint32Div, 2, 1, 1), // -- + PURE(Int32Mod, 2, 1, 1), // -- + PURE(Uint32Mod, 2, 1, 1), // -- + PURE(Int32LessThan, 2, 0, 1), // -- + PURE(Int32LessThanOrEqual, 2, 0, 1), // -- + PURE(Uint32LessThan, 2, 0, 1), // -- + PURE(Uint32LessThanOrEqual, 2, 0, 1), // -- + PURE(Int64Add, 2, 0, 1), // -- + PURE(Int64Sub, 2, 0, 1), // -- + PURE(Int64Mul, 2, 0, 1), // -- + PURE(Int64Div, 2, 1, 1), // -- + PURE(Uint64Div, 2, 1, 1), // -- + PURE(Int64Mod, 2, 1, 1), // -- + PURE(Uint64Mod, 2, 1, 1), // -- + PURE(Int64LessThan, 2, 0, 1), // -- + PURE(Int64LessThanOrEqual, 2, 0, 1), // -- + PURE(Uint64LessThan, 2, 0, 1), // -- + PURE(Uint64LessThanOrEqual, 2, 0, 1), // -- + PURE(ChangeFloat32ToFloat64, 1, 0, 1), // -- + PURE(ChangeFloat64ToInt32, 1, 0, 1), // -- + PURE(ChangeFloat64ToUint32, 1, 0, 1), // -- + PURE(ChangeInt32ToInt64, 1, 0, 1), // -- + PURE(ChangeUint32ToFloat64, 1, 0, 1), // -- + PURE(ChangeUint32ToUint64, 1, 0, 1), // -- + PURE(TruncateFloat64ToFloat32, 1, 0, 1), // -- + PURE(TruncateInt64ToInt32, 1, 0, 1), // -- + PURE(Float32Abs, 1, 0, 1), // -- + PURE(Float32Add, 2, 0, 1), // -- + PURE(Float32Sub, 2, 0, 1), // -- + PURE(Float32Mul, 2, 0, 1), // -- + PURE(Float32Div, 2, 0, 1), // -- + PURE(Float32Sqrt, 1, 0, 1), // -- + PURE(Float32Equal, 2, 0, 1), // -- + PURE(Float32LessThan, 2, 0, 1), // -- + PURE(Float32LessThanOrEqual, 2, 0, 1), // -- + PURE(Float64Abs, 1, 0, 1), // -- + PURE(Float64Add, 2, 0, 1), // -- + PURE(Float64Sub, 2, 0, 1), // -- + PURE(Float64Mul, 2, 0, 1), // -- + PURE(Float64Div, 2, 0, 1), // -- + PURE(Float64Mod, 2, 0, 1), // -- + PURE(Float64Sqrt, 1, 0, 1), // -- + PURE(Float64Equal, 2, 0, 1), // -- + PURE(Float64LessThan, 2, 0, 1), // -- + PURE(Float64LessThanOrEqual, 2, 0, 1), // -- + PURE(LoadStackPointer, 0, 0, 1), // -- + PURE(Float64ExtractLowWord32, 1, 0, 1), // -- + PURE(Float64ExtractHighWord32, 1, 0, 1), // -- + PURE(Float64InsertLowWord32, 2, 0, 1), // -- + PURE(Float64InsertHighWord32, 2, 0, 1), // -- #undef PURE }; - -typedef MachineOperatorTestWithParam<PureOperator> MachinePureOperatorTest; - } // namespace +class MachinePureOperatorTest : public TestWithZone { + protected: + MachineType word_type() { return kMachPtr; } +}; -TEST_P(MachinePureOperatorTest, InstancesAreGloballyShared) { - const PureOperator& pop = GetParam(); - MachineOperatorBuilder machine1(zone(), type()); - MachineOperatorBuilder machine2(zone(), type()); - EXPECT_EQ((machine1.*pop.constructor)(), (machine2.*pop.constructor)()); + +TEST_F(MachinePureOperatorTest, PureOperators) { + TRACED_FOREACH(MachineType, machine_rep1, kMachineReps) { + MachineOperatorBuilder machine1(zone(), machine_rep1); + TRACED_FOREACH(MachineType, machine_rep2, kMachineReps) { + MachineOperatorBuilder machine2(zone(), machine_rep2); + TRACED_FOREACH(PureOperator, pop, kPureOperators) { + const Operator* op1 = (machine1.*pop.constructor)(); + const Operator* op2 = (machine2.*pop.constructor)(); + EXPECT_EQ(op1, op2); + EXPECT_EQ(pop.value_input_count, op1->ValueInputCount()); + EXPECT_EQ(pop.control_input_count, op1->ControlInputCount()); + EXPECT_EQ(pop.value_output_count, op1->ValueOutputCount()); + } + } + } } -TEST_P(MachinePureOperatorTest, NumberOfInputsAndOutputs) { - MachineOperatorBuilder machine(zone(), type()); - const PureOperator& pop = GetParam(); - const Operator* op = (machine.*pop.constructor)(); +// Optional operators. - EXPECT_EQ(pop.value_input_count, op->ValueInputCount()); - EXPECT_EQ(0, op->EffectInputCount()); - EXPECT_EQ(pop.control_input_count, op->ControlInputCount()); - EXPECT_EQ(pop.value_input_count + pop.control_input_count, - OperatorProperties::GetTotalInputCount(op)); +namespace { - EXPECT_EQ(pop.value_output_count, op->ValueOutputCount()); - EXPECT_EQ(0, op->EffectOutputCount()); - EXPECT_EQ(0, op->ControlOutputCount()); -} +struct OptionalOperatorEntry { + const OptionalOperator (MachineOperatorBuilder::*constructor)(); + MachineOperatorBuilder::Flag enabling_flag; + char const* const constructor_name; + int value_input_count; + int control_input_count; + int value_output_count; +}; -TEST_P(MachinePureOperatorTest, MarkedAsPure) { - MachineOperatorBuilder machine(zone(), type()); - const PureOperator& pop = GetParam(); - const Operator* op = (machine.*pop.constructor)(); - EXPECT_TRUE(op->HasProperty(Operator::kPure)); +std::ostream& operator<<(std::ostream& os, OptionalOperatorEntry const& pop) { + return os << pop.constructor_name; } +const OptionalOperatorEntry kOptionalOperators[] = { +#define OPTIONAL_ENTRY(Name, value_input_count, control_input_count, \ + value_output_count) \ + { \ + &MachineOperatorBuilder::Name, MachineOperatorBuilder::k##Name, #Name, \ + value_input_count, control_input_count, value_output_count \ + } + OPTIONAL_ENTRY(Float32Max, 2, 0, 1), // -- + OPTIONAL_ENTRY(Float32Min, 2, 0, 1), // -- + OPTIONAL_ENTRY(Float64Max, 2, 0, 1), // -- + OPTIONAL_ENTRY(Float64Min, 2, 0, 1), // -- + OPTIONAL_ENTRY(Float64RoundDown, 1, 0, 1), // -- + OPTIONAL_ENTRY(Float64RoundTruncate, 1, 0, 1), // -- + OPTIONAL_ENTRY(Float64RoundTiesAway, 1, 0, 1), // -- +#undef OPTIONAL_ENTRY +}; +} // namespace -TEST_P(MachinePureOperatorTest, OpcodeIsCorrect) { - MachineOperatorBuilder machine(zone(), type()); - const PureOperator& pop = GetParam(); - const Operator* op = (machine.*pop.constructor)(); - EXPECT_EQ(pop.opcode, op->opcode()); -} +class MachineOptionalOperatorTest : public TestWithZone { + protected: + MachineType word_type() { return kMachPtr; } +}; -INSTANTIATE_TEST_CASE_P( - MachineOperatorTest, MachinePureOperatorTest, - ::testing::Combine(::testing::ValuesIn(kMachineReps), - ::testing::ValuesIn(kPureOperators))); -#endif // GTEST_HAS_COMBINE +TEST_F(MachineOptionalOperatorTest, OptionalOperators) { + TRACED_FOREACH(OptionalOperatorEntry, pop, kOptionalOperators) { + TRACED_FOREACH(MachineType, machine_rep1, kMachineReps) { + MachineOperatorBuilder machine1(zone(), machine_rep1, pop.enabling_flag); + TRACED_FOREACH(MachineType, machine_rep2, kMachineReps) { + MachineOperatorBuilder machine2(zone(), machine_rep2, + pop.enabling_flag); + const Operator* op1 = (machine1.*pop.constructor)().op(); + const Operator* op2 = (machine2.*pop.constructor)().op(); + EXPECT_EQ(op1, op2); + EXPECT_EQ(pop.value_input_count, op1->ValueInputCount()); + EXPECT_EQ(pop.control_input_count, op1->ControlInputCount()); + EXPECT_EQ(pop.value_output_count, op1->ValueOutputCount()); + + MachineOperatorBuilder machine3(zone(), word_type()); + EXPECT_TRUE((machine1.*pop.constructor)().IsSupported()); + EXPECT_FALSE((machine3.*pop.constructor)().IsSupported()); + } + } + } +} // ----------------------------------------------------------------------------- diff --git a/deps/v8/test/unittests/compiler/node-properties-unittest.cc b/deps/v8/test/unittests/compiler/node-properties-unittest.cc index 2bec4faf4d..463948d43f 100644 --- a/deps/v8/test/unittests/compiler/node-properties-unittest.cc +++ b/deps/v8/test/unittests/compiler/node-properties-unittest.cc @@ -10,78 +10,72 @@ using testing::AnyOf; using testing::ElementsAre; using testing::IsNull; -using testing::UnorderedElementsAre; namespace v8 { namespace internal { namespace compiler { -typedef TestWithZone NodePropertiesTest; - +class NodePropertiesTest : public TestWithZone { + public: + Node* NewMockNode(const Operator* op) { + return Node::New(zone(), 0, op, 0, nullptr, false); + } + Node* NewMockNode(const Operator* op, Node* n1) { + Node* nodes[] = {n1}; + return Node::New(zone(), 0, op, arraysize(nodes), nodes, false); + } + Node* NewMockNode(const Operator* op, Node* n1, Node* n2) { + Node* nodes[] = {n1, n2}; + return Node::New(zone(), 0, op, arraysize(nodes), nodes, false); + } +}; namespace { const Operator kMockOperator(IrOpcode::kDead, Operator::kNoProperties, - "MockOperator", 0, 0, 0, 1, 0, 0); -const Operator kMockOpEffect(IrOpcode::kDead, Operator::kNoProperties, - "MockOpEffect", 0, 1, 0, 1, 1, 0); -const Operator kMockOpControl(IrOpcode::kDead, Operator::kNoProperties, - "MockOpControl", 0, 0, 1, 1, 0, 1); + "MockOperator", 0, 0, 0, 1, 1, 2); const Operator kMockCallOperator(IrOpcode::kCall, Operator::kNoProperties, "MockCallOperator", 0, 0, 0, 0, 0, 2); -} // namespace - - -TEST_F(NodePropertiesTest, ReplaceWithValue_ValueUse) { - CommonOperatorBuilder common(zone()); - Node* node = Node::New(zone(), 0, &kMockOperator, 0, nullptr, false); - Node* use_value = Node::New(zone(), 0, common.Return(), 1, &node, false); - Node* replacement = Node::New(zone(), 0, &kMockOperator, 0, nullptr, false); - NodeProperties::ReplaceWithValue(node, replacement); - EXPECT_EQ(replacement, use_value->InputAt(0)); - EXPECT_EQ(0, node->UseCount()); - EXPECT_EQ(1, replacement->UseCount()); - EXPECT_THAT(replacement->uses(), ElementsAre(use_value)); -} - +const IfExceptionHint kNoHint = IfExceptionHint::kLocallyCaught; -TEST_F(NodePropertiesTest, ReplaceWithValue_EffectUse) { - CommonOperatorBuilder common(zone()); - Node* start = Node::New(zone(), 0, common.Start(1), 0, nullptr, false); - Node* node = Node::New(zone(), 0, &kMockOpEffect, 1, &start, false); - Node* use_effect = Node::New(zone(), 0, common.EffectPhi(1), 1, &node, false); - Node* replacement = Node::New(zone(), 0, &kMockOperator, 0, nullptr, false); - NodeProperties::ReplaceWithValue(node, replacement); - EXPECT_EQ(start, use_effect->InputAt(0)); - EXPECT_EQ(0, node->UseCount()); - EXPECT_EQ(2, start->UseCount()); - EXPECT_EQ(0, replacement->UseCount()); - EXPECT_THAT(start->uses(), UnorderedElementsAre(use_effect, node)); -} +} // namespace -TEST_F(NodePropertiesTest, ReplaceWithValue_ControlUse) { +TEST_F(NodePropertiesTest, ReplaceUses) { CommonOperatorBuilder common(zone()); - Node* start = Node::New(zone(), 0, common.Start(1), 0, nullptr, false); - Node* node = Node::New(zone(), 0, &kMockOpControl, 1, &start, false); - Node* success = Node::New(zone(), 0, common.IfSuccess(), 1, &node, false); - Node* use_control = Node::New(zone(), 0, common.Merge(1), 1, &success, false); - Node* replacement = Node::New(zone(), 0, &kMockOperator, 0, nullptr, false); - NodeProperties::ReplaceWithValue(node, replacement); - EXPECT_EQ(start, use_control->InputAt(0)); + Node* node = NewMockNode(&kMockOperator); + Node* effect = NewMockNode(&kMockOperator); + Node* use_value = NewMockNode(common.Return(), node); + Node* use_effect = NewMockNode(common.EffectPhi(1), node); + Node* use_success = NewMockNode(common.IfSuccess(), node); + Node* use_exception = NewMockNode(common.IfException(kNoHint), effect, node); + Node* r_value = NewMockNode(&kMockOperator); + Node* r_effect = NewMockNode(&kMockOperator); + Node* r_success = NewMockNode(&kMockOperator); + Node* r_exception = NewMockNode(&kMockOperator); + NodeProperties::ReplaceUses(node, r_value, r_effect, r_success, r_exception); + EXPECT_EQ(r_value, use_value->InputAt(0)); + EXPECT_EQ(r_effect, use_effect->InputAt(0)); + EXPECT_EQ(r_success, use_success->InputAt(0)); + EXPECT_EQ(r_exception, use_exception->InputAt(1)); EXPECT_EQ(0, node->UseCount()); - EXPECT_EQ(2, start->UseCount()); - EXPECT_EQ(0, replacement->UseCount()); - EXPECT_THAT(start->uses(), UnorderedElementsAre(use_control, node)); + EXPECT_EQ(1, r_value->UseCount()); + EXPECT_EQ(1, r_effect->UseCount()); + EXPECT_EQ(1, r_success->UseCount()); + EXPECT_EQ(1, r_exception->UseCount()); + EXPECT_THAT(r_value->uses(), ElementsAre(use_value)); + EXPECT_THAT(r_effect->uses(), ElementsAre(use_effect)); + EXPECT_THAT(r_success->uses(), ElementsAre(use_success)); + EXPECT_THAT(r_exception->uses(), ElementsAre(use_exception)); } TEST_F(NodePropertiesTest, FindProjection) { CommonOperatorBuilder common(zone()); - Node* start = Node::New(zone(), 0, common.Start(1), 0, nullptr, false); - Node* proj0 = Node::New(zone(), 1, common.Projection(0), 1, &start, false); - Node* proj1 = Node::New(zone(), 2, common.Projection(1), 1, &start, false); + Node* start = NewMockNode(common.Start(1)); + Node* proj0 = NewMockNode(common.Projection(0), start); + Node* proj1 = NewMockNode(common.Projection(1), start); EXPECT_EQ(proj0, NodeProperties::FindProjection(start, 0)); EXPECT_EQ(proj1, NodeProperties::FindProjection(start, 1)); EXPECT_THAT(NodeProperties::FindProjection(start, 2), IsNull()); @@ -92,9 +86,9 @@ TEST_F(NodePropertiesTest, FindProjection) { TEST_F(NodePropertiesTest, CollectControlProjections_Branch) { Node* result[2]; CommonOperatorBuilder common(zone()); - Node* branch = Node::New(zone(), 1, common.Branch(), 0, nullptr, false); - Node* if_false = Node::New(zone(), 2, common.IfFalse(), 1, &branch, false); - Node* if_true = Node::New(zone(), 3, common.IfTrue(), 1, &branch, false); + Node* branch = NewMockNode(common.Branch()); + Node* if_false = NewMockNode(common.IfFalse(), branch); + Node* if_true = NewMockNode(common.IfTrue(), branch); NodeProperties::CollectControlProjections(branch, result, arraysize(result)); EXPECT_EQ(if_true, result[0]); EXPECT_EQ(if_false, result[1]); @@ -104,9 +98,9 @@ TEST_F(NodePropertiesTest, CollectControlProjections_Branch) { TEST_F(NodePropertiesTest, CollectControlProjections_Call) { Node* result[2]; CommonOperatorBuilder common(zone()); - Node* call = Node::New(zone(), 1, &kMockCallOperator, 0, nullptr, false); - Node* if_ex = Node::New(zone(), 2, common.IfException(), 1, &call, false); - Node* if_ok = Node::New(zone(), 3, common.IfSuccess(), 1, &call, false); + Node* call = NewMockNode(&kMockCallOperator); + Node* if_ex = NewMockNode(common.IfException(kNoHint), call, call); + Node* if_ok = NewMockNode(common.IfSuccess(), call); NodeProperties::CollectControlProjections(call, result, arraysize(result)); EXPECT_EQ(if_ok, result[0]); EXPECT_EQ(if_ex, result[1]); @@ -116,10 +110,10 @@ TEST_F(NodePropertiesTest, CollectControlProjections_Call) { TEST_F(NodePropertiesTest, CollectControlProjections_Switch) { Node* result[3]; CommonOperatorBuilder common(zone()); - Node* sw = Node::New(zone(), 1, common.Switch(3), 0, nullptr, false); - Node* if_default = Node::New(zone(), 2, common.IfDefault(), 1, &sw, false); - Node* if_value1 = Node::New(zone(), 3, common.IfValue(1), 1, &sw, false); - Node* if_value2 = Node::New(zone(), 4, common.IfValue(2), 1, &sw, false); + Node* sw = NewMockNode(common.Switch(3)); + Node* if_default = NewMockNode(common.IfDefault(), sw); + Node* if_value1 = NewMockNode(common.IfValue(1), sw); + Node* if_value2 = NewMockNode(common.IfValue(2), sw); NodeProperties::CollectControlProjections(sw, result, arraysize(result)); EXPECT_THAT(result[0], AnyOf(if_value1, if_value2)); EXPECT_THAT(result[1], AnyOf(if_value1, if_value2)); diff --git a/deps/v8/test/unittests/compiler/node-test-utils.cc b/deps/v8/test/unittests/compiler/node-test-utils.cc index e6201ec67f..520ce0159e 100644 --- a/deps/v8/test/unittests/compiler/node-test-utils.cc +++ b/deps/v8/test/unittests/compiler/node-test-utils.cc @@ -7,6 +7,7 @@ #include <vector> #include "src/assembler.h" +#include "src/compiler/js-operator.h" #include "src/compiler/node-properties.h" #include "src/compiler/simplified-operator.h" #include "src/unique.h" @@ -748,6 +749,32 @@ class IsTailCallMatcher final : public NodeMatcher { }; +class IsReferenceEqualMatcher final : public NodeMatcher { + public: + IsReferenceEqualMatcher(const Matcher<Type*>& type_matcher, + const Matcher<Node*>& lhs_matcher, + const Matcher<Node*>& rhs_matcher) + : NodeMatcher(IrOpcode::kReferenceEqual), + type_matcher_(type_matcher), + lhs_matcher_(lhs_matcher), + rhs_matcher_(rhs_matcher) {} + + bool MatchAndExplain(Node* node, MatchResultListener* listener) const final { + return (NodeMatcher::MatchAndExplain(node, listener) && + // TODO(bmeurer): The type parameter is currently ignored. + PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "lhs", + lhs_matcher_, listener) && + PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), "rhs", + rhs_matcher_, listener)); + } + + private: + const Matcher<Type*> type_matcher_; + const Matcher<Node*> lhs_matcher_; + const Matcher<Node*> rhs_matcher_; +}; + + class IsAllocateMatcher final : public NodeMatcher { public: IsAllocateMatcher(const Matcher<Node*>& size_matcher, @@ -1160,24 +1187,32 @@ class IsLoadMatcher final : public NodeMatcher { }; -class IsToNumberMatcher final : public NodeMatcher { +class IsStoreMatcher final : public NodeMatcher { public: - IsToNumberMatcher(const Matcher<Node*>& base_matcher, - const Matcher<Node*>& context_matcher, - const Matcher<Node*>& effect_matcher, - const Matcher<Node*>& control_matcher) - : NodeMatcher(IrOpcode::kJSToNumber), + IsStoreMatcher(const Matcher<StoreRepresentation>& rep_matcher, + const Matcher<Node*>& base_matcher, + const Matcher<Node*>& index_matcher, + const Matcher<Node*>& value_matcher, + const Matcher<Node*>& effect_matcher, + const Matcher<Node*>& control_matcher) + : NodeMatcher(IrOpcode::kStore), + rep_matcher_(rep_matcher), base_matcher_(base_matcher), - context_matcher_(context_matcher), + index_matcher_(index_matcher), + value_matcher_(value_matcher), effect_matcher_(effect_matcher), control_matcher_(control_matcher) {} void DescribeTo(std::ostream* os) const final { NodeMatcher::DescribeTo(os); - *os << " whose base ("; + *os << " whose rep ("; + rep_matcher_.DescribeTo(os); + *os << "), base ("; base_matcher_.DescribeTo(os); - *os << "), context ("; - context_matcher_.DescribeTo(os); + *os << "), index ("; + index_matcher_.DescribeTo(os); + *os << "), value ("; + value_matcher_.DescribeTo(os); *os << "), effect ("; effect_matcher_.DescribeTo(os); *os << ") and control ("; @@ -1187,10 +1222,14 @@ class IsToNumberMatcher final : public NodeMatcher { bool MatchAndExplain(Node* node, MatchResultListener* listener) const final { return (NodeMatcher::MatchAndExplain(node, listener) && + PrintMatchAndExplain(OpParameter<StoreRepresentation>(node), "rep", + rep_matcher_, listener) && PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base", base_matcher_, listener) && - PrintMatchAndExplain(NodeProperties::GetContextInput(node), - "context", context_matcher_, listener) && + PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), + "index", index_matcher_, listener) && + PrintMatchAndExplain(NodeProperties::GetValueInput(node, 2), + "value", value_matcher_, listener) && PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect", effect_matcher_, listener) && PrintMatchAndExplain(NodeProperties::GetControlInput(node), @@ -1198,39 +1237,33 @@ class IsToNumberMatcher final : public NodeMatcher { } private: + const Matcher<StoreRepresentation> rep_matcher_; const Matcher<Node*> base_matcher_; - const Matcher<Node*> context_matcher_; + const Matcher<Node*> index_matcher_; + const Matcher<Node*> value_matcher_; const Matcher<Node*> effect_matcher_; const Matcher<Node*> control_matcher_; }; -class IsStoreMatcher final : public NodeMatcher { +class IsToNumberMatcher final : public NodeMatcher { public: - IsStoreMatcher(const Matcher<StoreRepresentation>& rep_matcher, - const Matcher<Node*>& base_matcher, - const Matcher<Node*>& index_matcher, - const Matcher<Node*>& value_matcher, - const Matcher<Node*>& effect_matcher, - const Matcher<Node*>& control_matcher) - : NodeMatcher(IrOpcode::kStore), - rep_matcher_(rep_matcher), + IsToNumberMatcher(const Matcher<Node*>& base_matcher, + const Matcher<Node*>& context_matcher, + const Matcher<Node*>& effect_matcher, + const Matcher<Node*>& control_matcher) + : NodeMatcher(IrOpcode::kJSToNumber), base_matcher_(base_matcher), - index_matcher_(index_matcher), - value_matcher_(value_matcher), + context_matcher_(context_matcher), effect_matcher_(effect_matcher), control_matcher_(control_matcher) {} void DescribeTo(std::ostream* os) const final { NodeMatcher::DescribeTo(os); - *os << " whose rep ("; - rep_matcher_.DescribeTo(os); - *os << "), base ("; + *os << " whose base ("; base_matcher_.DescribeTo(os); - *os << "), index ("; - index_matcher_.DescribeTo(os); - *os << "), value ("; - value_matcher_.DescribeTo(os); + *os << "), context ("; + context_matcher_.DescribeTo(os); *os << "), effect ("; effect_matcher_.DescribeTo(os); *os << ") and control ("; @@ -1240,14 +1273,10 @@ class IsStoreMatcher final : public NodeMatcher { bool MatchAndExplain(Node* node, MatchResultListener* listener) const final { return (NodeMatcher::MatchAndExplain(node, listener) && - PrintMatchAndExplain(OpParameter<StoreRepresentation>(node), "rep", - rep_matcher_, listener) && PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base", base_matcher_, listener) && - PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), - "index", index_matcher_, listener) && - PrintMatchAndExplain(NodeProperties::GetValueInput(node, 2), - "value", value_matcher_, listener) && + PrintMatchAndExplain(NodeProperties::GetContextInput(node), + "context", context_matcher_, listener) && PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect", effect_matcher_, listener) && PrintMatchAndExplain(NodeProperties::GetControlInput(node), @@ -1255,15 +1284,44 @@ class IsStoreMatcher final : public NodeMatcher { } private: - const Matcher<StoreRepresentation> rep_matcher_; const Matcher<Node*> base_matcher_; - const Matcher<Node*> index_matcher_; - const Matcher<Node*> value_matcher_; + const Matcher<Node*> context_matcher_; const Matcher<Node*> effect_matcher_; const Matcher<Node*> control_matcher_; }; +class IsLoadContextMatcher final : public NodeMatcher { + public: + IsLoadContextMatcher(const Matcher<ContextAccess>& access_matcher, + const Matcher<Node*>& context_matcher) + : NodeMatcher(IrOpcode::kJSLoadContext), + access_matcher_(access_matcher), + context_matcher_(context_matcher) {} + + void DescribeTo(std::ostream* os) const final { + NodeMatcher::DescribeTo(os); + *os << " whose access ("; + access_matcher_.DescribeTo(os); + *os << ") and context ("; + context_matcher_.DescribeTo(os); + *os << ")"; + } + + bool MatchAndExplain(Node* node, MatchResultListener* listener) const final { + return (NodeMatcher::MatchAndExplain(node, listener) && + PrintMatchAndExplain(OpParameter<ContextAccess>(node), "access", + access_matcher_, listener) && + PrintMatchAndExplain(NodeProperties::GetContextInput(node), + "context", context_matcher_, listener)); + } + + private: + const Matcher<ContextAccess> access_matcher_; + const Matcher<Node*> context_matcher_; +}; + + class IsBinopMatcher final : public NodeMatcher { public: IsBinopMatcher(IrOpcode::Value opcode, const Matcher<Node*>& lhs_matcher, @@ -1320,8 +1378,28 @@ class IsUnopMatcher final : public NodeMatcher { } // namespace -Matcher<Node*> IsEnd(const Matcher<Node*>& control_matcher) { - return MakeMatcher(new IsControl1Matcher(IrOpcode::kEnd, control_matcher)); +Matcher<Node*> IsDead() { + return MakeMatcher(new NodeMatcher(IrOpcode::kDead)); +} + + +Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher) { + return MakeMatcher(new IsControl1Matcher(IrOpcode::kEnd, control0_matcher)); +} + + +Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher, + const Matcher<Node*>& control1_matcher) { + return MakeMatcher(new IsControl2Matcher(IrOpcode::kEnd, control0_matcher, + control1_matcher)); +} + + +Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher, + const Matcher<Node*>& control1_matcher, + const Matcher<Node*>& control2_matcher) { + return MakeMatcher(new IsControl3Matcher(IrOpcode::kEnd, control0_matcher, + control1_matcher, control2_matcher)); } @@ -1600,6 +1678,14 @@ Matcher<Node*> IsTailCall( } +Matcher<Node*> IsReferenceEqual(const Matcher<Type*>& type_matcher, + const Matcher<Node*>& lhs_matcher, + const Matcher<Node*>& rhs_matcher) { + return MakeMatcher( + new IsReferenceEqualMatcher(type_matcher, lhs_matcher, rhs_matcher)); +} + + Matcher<Node*> IsAllocate(const Matcher<Node*>& size_matcher, const Matcher<Node*>& effect_matcher, const Matcher<Node*>& control_matcher) { @@ -1686,15 +1772,6 @@ Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher, } -Matcher<Node*> IsToNumber(const Matcher<Node*>& base_matcher, - const Matcher<Node*>& context_matcher, - const Matcher<Node*>& effect_matcher, - const Matcher<Node*>& control_matcher) { - return MakeMatcher(new IsToNumberMatcher(base_matcher, context_matcher, - effect_matcher, control_matcher)); -} - - Matcher<Node*> IsStore(const Matcher<StoreRepresentation>& rep_matcher, const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher, @@ -1707,6 +1784,21 @@ Matcher<Node*> IsStore(const Matcher<StoreRepresentation>& rep_matcher, } +Matcher<Node*> IsToNumber(const Matcher<Node*>& base_matcher, + const Matcher<Node*>& context_matcher, + const Matcher<Node*>& effect_matcher, + const Matcher<Node*>& control_matcher) { + return MakeMatcher(new IsToNumberMatcher(base_matcher, context_matcher, + effect_matcher, control_matcher)); +} + + +Matcher<Node*> IsLoadContext(const Matcher<ContextAccess>& access_matcher, + const Matcher<Node*>& context_matcher) { + return MakeMatcher(new IsLoadContextMatcher(access_matcher, context_matcher)); +} + + #define IS_BINOP_MATCHER(Name) \ Matcher<Node*> Is##Name(const Matcher<Node*>& lhs_matcher, \ const Matcher<Node*>& rhs_matcher) { \ @@ -1717,6 +1809,9 @@ IS_BINOP_MATCHER(NumberEqual) IS_BINOP_MATCHER(NumberLessThan) IS_BINOP_MATCHER(NumberSubtract) IS_BINOP_MATCHER(NumberMultiply) +IS_BINOP_MATCHER(NumberShiftLeft) +IS_BINOP_MATCHER(NumberShiftRight) +IS_BINOP_MATCHER(NumberShiftRightLogical) IS_BINOP_MATCHER(Word32And) IS_BINOP_MATCHER(Word32Sar) IS_BINOP_MATCHER(Word32Shl) diff --git a/deps/v8/test/unittests/compiler/node-test-utils.h b/deps/v8/test/unittests/compiler/node-test-utils.h index 9c4646b2f0..a64d9f009a 100644 --- a/deps/v8/test/unittests/compiler/node-test-utils.h +++ b/deps/v8/test/unittests/compiler/node-test-utils.h @@ -17,12 +17,17 @@ class ExternalReference; class HeapObject; template <class T> class Unique; +template <class> +class TypeImpl; +struct ZoneTypeConfig; +typedef TypeImpl<ZoneTypeConfig> Type; namespace compiler { // Forward declarations. class BufferAccess; class CallDescriptor; +class ContextAccess; struct ElementAccess; struct FieldAccess; class Node; @@ -31,7 +36,13 @@ class Node; using ::testing::Matcher; -Matcher<Node*> IsEnd(const Matcher<Node*>& control_matcher); +Matcher<Node*> IsDead(); +Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher); +Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher, + const Matcher<Node*>& control1_matcher); +Matcher<Node*> IsEnd(const Matcher<Node*>& control0_matcher, + const Matcher<Node*>& control1_matcher, + const Matcher<Node*>& control2_matcher); Matcher<Node*> IsBranch(const Matcher<Node*>& value_matcher, const Matcher<Node*>& control_matcher); Matcher<Node*> IsMerge(const Matcher<Node*>& control0_matcher, @@ -125,6 +136,9 @@ Matcher<Node*> IsTailCall( const Matcher<Node*>& control_matcher); Matcher<Node*> IsBooleanNot(const Matcher<Node*>& value_matcher); +Matcher<Node*> IsReferenceEqual(const Matcher<Type*>& type_matcher, + const Matcher<Node*>& lhs_matcher, + const Matcher<Node*>& rhs_matcher); Matcher<Node*> IsNumberEqual(const Matcher<Node*>& lhs_matcher, const Matcher<Node*>& rhs_matcher); Matcher<Node*> IsNumberLessThan(const Matcher<Node*>& lhs_matcher, @@ -133,6 +147,12 @@ Matcher<Node*> IsNumberSubtract(const Matcher<Node*>& lhs_matcher, const Matcher<Node*>& rhs_matcher); Matcher<Node*> IsNumberMultiply(const Matcher<Node*>& lhs_matcher, const Matcher<Node*>& rhs_matcher); +Matcher<Node*> IsNumberShiftLeft(const Matcher<Node*>& lhs_matcher, + const Matcher<Node*>& rhs_matcher); +Matcher<Node*> IsNumberShiftRight(const Matcher<Node*>& lhs_matcher, + const Matcher<Node*>& rhs_matcher); +Matcher<Node*> IsNumberShiftRightLogical(const Matcher<Node*>& lhs_matcher, + const Matcher<Node*>& rhs_matcher); Matcher<Node*> IsAllocate(const Matcher<Node*>& size_matcher, const Matcher<Node*>& effect_matcher, const Matcher<Node*>& control_matcher); @@ -255,6 +275,8 @@ Matcher<Node*> IsToNumber(const Matcher<Node*>& base_matcher, const Matcher<Node*>& context_matcher, const Matcher<Node*>& effect_matcher, const Matcher<Node*>& control_matcher); +Matcher<Node*> IsLoadContext(const Matcher<ContextAccess>& access_matcher, + const Matcher<Node*>& context_matcher); Matcher<Node*> IsNumberToInt32(const Matcher<Node*>& input_matcher); Matcher<Node*> IsNumberToUint32(const Matcher<Node*>& input_matcher); diff --git a/deps/v8/test/unittests/compiler/node-unittest.cc b/deps/v8/test/unittests/compiler/node-unittest.cc index 6b61bd5c1c..5341f69716 100644 --- a/deps/v8/test/unittests/compiler/node-unittest.cc +++ b/deps/v8/test/unittests/compiler/node-unittest.cc @@ -32,7 +32,7 @@ const Operator kOp2(kOpcode2, Operator::kNoProperties, "Op2", 2, 0, 0, 1, 0, 0); TEST_F(NodeTest, New) { Node* const node = Node::New(zone(), 1, &kOp0, 0, nullptr, false); - EXPECT_EQ(1, node->id()); + EXPECT_EQ(1U, node->id()); EXPECT_EQ(0, node->UseCount()); EXPECT_TRUE(node->uses().empty()); EXPECT_EQ(0, node->InputCount()); @@ -166,6 +166,96 @@ TEST_F(NodeTest, AppendInput) { EXPECT_THAT(node->inputs(), ElementsAre(n0, n1, n0, n0, n1)); } + +TEST_F(NodeTest, TrimThenAppend) { + Node* n0 = Node::New(zone(), 0, &kOp0, 0, nullptr, false); + Node* n1 = Node::New(zone(), 1, &kOp0, 0, nullptr, false); + Node* n2 = Node::New(zone(), 2, &kOp0, 0, nullptr, false); + Node* n3 = Node::New(zone(), 3, &kOp0, 0, nullptr, false); + Node* n4 = Node::New(zone(), 4, &kOp0, 0, nullptr, false); + Node* n5 = Node::New(zone(), 5, &kOp0, 0, nullptr, false); + Node* n6 = Node::New(zone(), 6, &kOp0, 0, nullptr, false); + Node* n7 = Node::New(zone(), 7, &kOp0, 0, nullptr, false); + Node* n8 = Node::New(zone(), 8, &kOp0, 0, nullptr, false); + Node* n9 = Node::New(zone(), 9, &kOp0, 0, nullptr, false); + Node* node = Node::New(zone(), 12345, &kOp0, 0, nullptr, true); + + EXPECT_TRUE(node->inputs().empty()); + + node->AppendInput(zone(), n0); + EXPECT_FALSE(node->inputs().empty()); + EXPECT_THAT(node->inputs(), ElementsAre(n0)); + + node->TrimInputCount(0); + EXPECT_TRUE(node->inputs().empty()); + + node->AppendInput(zone(), n1); + EXPECT_FALSE(node->inputs().empty()); + EXPECT_THAT(node->inputs(), ElementsAre(n1)); + + node->AppendInput(zone(), n2); + EXPECT_FALSE(node->inputs().empty()); + EXPECT_THAT(node->inputs(), ElementsAre(n1, n2)); + + node->TrimInputCount(1); + EXPECT_FALSE(node->inputs().empty()); + EXPECT_THAT(node->inputs(), ElementsAre(n1)); + + node->AppendInput(zone(), n3); + EXPECT_FALSE(node->inputs().empty()); + EXPECT_THAT(node->inputs(), ElementsAre(n1, n3)); + + node->AppendInput(zone(), n4); + EXPECT_FALSE(node->inputs().empty()); + EXPECT_THAT(node->inputs(), ElementsAre(n1, n3, n4)); + + node->AppendInput(zone(), n5); + EXPECT_FALSE(node->inputs().empty()); + EXPECT_THAT(node->inputs(), ElementsAre(n1, n3, n4, n5)); + + node->AppendInput(zone(), n6); + EXPECT_FALSE(node->inputs().empty()); + EXPECT_THAT(node->inputs(), ElementsAre(n1, n3, n4, n5, n6)); + + node->AppendInput(zone(), n7); + EXPECT_FALSE(node->inputs().empty()); + EXPECT_THAT(node->inputs(), ElementsAre(n1, n3, n4, n5, n6, n7)); + + node->TrimInputCount(4); + EXPECT_THAT(node->inputs(), ElementsAre(n1, n3, n4, n5)); + + node->AppendInput(zone(), n8); + EXPECT_FALSE(node->inputs().empty()); + EXPECT_THAT(node->inputs(), ElementsAre(n1, n3, n4, n5, n8)); + + node->AppendInput(zone(), n9); + EXPECT_FALSE(node->inputs().empty()); + EXPECT_THAT(node->inputs(), ElementsAre(n1, n3, n4, n5, n8, n9)); +} + + +TEST_F(NodeTest, BigNodes) { + static const int kMaxSize = 512; + Node* inputs[kMaxSize]; + + Node* n0 = Node::New(zone(), 0, &kOp0, 0, nullptr, false); + Node* n1 = Node::New(zone(), 1, &kOp1, 1, &n0, false); + + for (int i = 0; i < kMaxSize; i++) { + inputs[i] = i & 1 ? n0 : n1; + } + + for (int size = 13; size <= kMaxSize; size += 9) { + Node* node = Node::New(zone(), 12345, &kOp0, size, inputs, false); + EXPECT_EQ(size, node->InputCount()); + + for (int i = 0; i < size; i++) { + EXPECT_EQ(inputs[i], node->InputAt(i)); + } + } +} + + } // namespace compiler } // namespace internal } // namespace v8 diff --git a/deps/v8/test/unittests/compiler/scheduler-unittest.cc b/deps/v8/test/unittests/compiler/scheduler-unittest.cc index 4de15492b2..45c636b27a 100644 --- a/deps/v8/test/unittests/compiler/scheduler-unittest.cc +++ b/deps/v8/test/unittests/compiler/scheduler-unittest.cc @@ -631,7 +631,7 @@ TEST_F(SchedulerRPOTest, LoopMultibackedge) { TEST_F(SchedulerTest, BuildScheduleEmpty) { graph()->SetStart(graph()->NewNode(common()->Start(0))); - graph()->SetEnd(graph()->NewNode(common()->End(), graph()->start())); + graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start())); USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags)); } @@ -643,22 +643,23 @@ TEST_F(SchedulerTest, BuildScheduleOneParameter) { Node* ret = graph()->NewNode(common()->Return(), p1, graph()->start(), graph()->start()); - graph()->SetEnd(graph()->NewNode(common()->End(), ret)); + graph()->SetEnd(graph()->NewNode(common()->End(1), ret)); USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags)); } TEST_F(SchedulerTest, BuildScheduleIfSplit) { - graph()->SetStart(graph()->NewNode(common()->Start(3))); + graph()->SetStart(graph()->NewNode(common()->Start(5))); Node* p1 = graph()->NewNode(common()->Parameter(0), graph()->start()); Node* p2 = graph()->NewNode(common()->Parameter(1), graph()->start()); Node* p3 = graph()->NewNode(common()->Parameter(2), graph()->start()); Node* p4 = graph()->NewNode(common()->Parameter(3), graph()->start()); Node* p5 = graph()->NewNode(common()->Parameter(4), graph()->start()); - Node* cmp = graph()->NewNode(js()->LessThanOrEqual(LanguageMode::SLOPPY), p1, - p2, p3, graph()->start(), graph()->start()); + Node* cmp = + graph()->NewNode(js()->LessThanOrEqual(LanguageMode::SLOPPY), p1, p2, p3, + p4, p5, graph()->start(), graph()->start()); Node* branch = graph()->NewNode(common()->Branch(), cmp, graph()->start()); Node* true_branch = graph()->NewNode(common()->IfTrue(), branch); Node* false_branch = graph()->NewNode(common()->IfFalse(), branch); @@ -667,1341 +668,12 @@ TEST_F(SchedulerTest, BuildScheduleIfSplit) { graph()->NewNode(common()->Return(), p4, graph()->start(), true_branch); Node* ret2 = graph()->NewNode(common()->Return(), p5, graph()->start(), false_branch); - Node* merge = graph()->NewNode(common()->Merge(2), ret1, ret2); - graph()->SetEnd(graph()->NewNode(common()->End(), merge)); + graph()->SetEnd(graph()->NewNode(common()->End(2), ret1, ret2)); ComputeAndVerifySchedule(13); } -TEST_F(SchedulerTest, BuildScheduleIfSplitWithEffects) { - const Operator* op; - Unique<HeapObject> unique_constant = - Unique<HeapObject>::CreateImmovable(factory()->undefined_value()); - - // 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()->Dead()); - op = common()->End(); - Node* n39 = graph()->NewNode(op, nil); - USE(n39); - op = common()->Merge(2); - Node* n37 = graph()->NewNode(op, nil, nil); - USE(n37); - op = common()->Return(); - Node* n29 = graph()->NewNode(op, nil, nil, nil); - USE(n29); - op = common()->Return(); - Node* n36 = graph()->NewNode(op, nil, nil, nil); - USE(n36); - op = js()->Add(LanguageMode::SLOPPY); - Node* n27 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n27); - op = common()->IfSuccess(); - Node* n28 = graph()->NewNode(op, nil); - USE(n28); - op = js()->Subtract(LanguageMode::SLOPPY); - Node* n34 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n34); - op = common()->IfSuccess(); - Node* n35 = graph()->NewNode(op, nil); - USE(n35); - op = js()->Subtract(LanguageMode::SLOPPY); - Node* n25 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n25); - op = common()->Parameter(4); - Node* n5 = graph()->NewNode(op, nil); - USE(n5); - op = common()->Parameter(5); - Node* n7 = graph()->NewNode(op, nil); - USE(n7); - op = common()->FrameState(JS_FRAME, BailoutId(-1), - OutputFrameStateCombine::Ignore()); - Node* n13 = graph()->NewNode(op, nil, nil, nil, nil, nil); - USE(n13); - op = common()->IfSuccess(); - Node* n26 = graph()->NewNode(op, nil); - USE(n26); - op = js()->Multiply(LanguageMode::SLOPPY); - Node* n32 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n32); - op = common()->Parameter(1); - Node* n2 = graph()->NewNode(op, nil); - USE(n2); - op = common()->IfSuccess(); - Node* n33 = graph()->NewNode(op, nil); - USE(n33); - op = js()->Subtract(LanguageMode::SLOPPY); - Node* n23 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n23); - op = common()->IfSuccess(); - Node* n24 = graph()->NewNode(op, nil); - USE(n24); - op = common()->Start(4); - Node* n0 = graph()->NewNode(op); - USE(n0); - op = common()->StateValues(0); - Node* n11 = graph()->NewNode(op); - USE(n11); - op = common()->NumberConstant(0); - Node* n12 = graph()->NewNode(op); - USE(n12); - op = common()->HeapConstant(unique_constant); - Node* n6 = graph()->NewNode(op); - USE(n6); - op = common()->Parameter(3); - Node* n4 = graph()->NewNode(op, nil); - USE(n4); - op = js()->LessThan(LanguageMode::SLOPPY); - Node* n15 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil); - USE(n15); - op = common()->IfFalse(); - Node* n31 = graph()->NewNode(op, nil); - USE(n31); - op = js()->Add(LanguageMode::SLOPPY); - Node* n19 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n19); - op = js()->Multiply(LanguageMode::SLOPPY); - Node* n21 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n21); - op = common()->IfSuccess(); - Node* n22 = graph()->NewNode(op, nil); - USE(n22); - op = common()->Parameter(2); - Node* n3 = graph()->NewNode(op, nil); - USE(n3); - op = js()->StackCheck(); - Node* n9 = graph()->NewNode(op, nil, nil, nil, nil); - USE(n9); - op = common()->IfSuccess(); - Node* n10 = graph()->NewNode(op, nil); - USE(n10); - op = common()->Branch(); - Node* n17 = graph()->NewNode(op, nil, nil); - USE(n17); - op = common()->IfTrue(); - Node* n18 = graph()->NewNode(op, nil); - USE(n18); - op = common()->IfSuccess(); - Node* n20 = graph()->NewNode(op, nil); - USE(n20); - op = common()->IfSuccess(); - Node* n16 = graph()->NewNode(op, nil); - USE(n16); - n39->ReplaceInput(0, n37); - n37->ReplaceInput(0, n29); - n37->ReplaceInput(1, n36); - n29->ReplaceInput(0, n27); - n29->ReplaceInput(1, n27); - n29->ReplaceInput(2, n28); - n36->ReplaceInput(0, n34); - n36->ReplaceInput(1, n34); - n36->ReplaceInput(2, n35); - n27->ReplaceInput(0, n25); - n27->ReplaceInput(1, n5); - n27->ReplaceInput(2, n7); - n27->ReplaceInput(3, n13); - n27->ReplaceInput(4, n13); - n27->ReplaceInput(5, n25); - n27->ReplaceInput(6, n26); - n28->ReplaceInput(0, n27); - n34->ReplaceInput(0, n32); - n34->ReplaceInput(1, n2); - n34->ReplaceInput(2, n7); - n34->ReplaceInput(3, n13); - n34->ReplaceInput(4, n13); - n34->ReplaceInput(5, n32); - n34->ReplaceInput(6, n33); - n35->ReplaceInput(0, n34); - n25->ReplaceInput(0, n23); - n25->ReplaceInput(1, n2); - n25->ReplaceInput(2, n7); - n25->ReplaceInput(3, n13); - n25->ReplaceInput(4, n13); - n25->ReplaceInput(5, n23); - n25->ReplaceInput(6, n24); - n5->ReplaceInput(0, n0); - n7->ReplaceInput(0, n0); - n13->ReplaceInput(0, n11); - n13->ReplaceInput(1, n11); - n13->ReplaceInput(2, n11); - n13->ReplaceInput(3, n12); - n13->ReplaceInput(4, n6); - n26->ReplaceInput(0, n25); - n32->ReplaceInput(0, n4); - n32->ReplaceInput(1, n4); - n32->ReplaceInput(2, n7); - n32->ReplaceInput(3, n13); - n32->ReplaceInput(4, n13); - n32->ReplaceInput(5, n15); - n32->ReplaceInput(6, n31); - n2->ReplaceInput(0, n0); - n33->ReplaceInput(0, n32); - n23->ReplaceInput(0, n19); - n23->ReplaceInput(1, n21); - n23->ReplaceInput(2, n7); - n23->ReplaceInput(3, n13); - n23->ReplaceInput(4, n13); - n23->ReplaceInput(5, n21); - n23->ReplaceInput(6, n22); - n24->ReplaceInput(0, n23); - n4->ReplaceInput(0, n0); - n15->ReplaceInput(0, n2); - n15->ReplaceInput(1, n3); - n15->ReplaceInput(2, n7); - n15->ReplaceInput(3, n13); - n15->ReplaceInput(4, n9); - n15->ReplaceInput(5, n10); - n31->ReplaceInput(0, n17); - n19->ReplaceInput(0, n2); - n19->ReplaceInput(1, n3); - n19->ReplaceInput(2, n7); - n19->ReplaceInput(3, n13); - n19->ReplaceInput(4, n13); - n19->ReplaceInput(5, n15); - n19->ReplaceInput(6, n18); - n21->ReplaceInput(0, n4); - n21->ReplaceInput(1, n4); - n21->ReplaceInput(2, n7); - n21->ReplaceInput(3, n13); - n21->ReplaceInput(4, n13); - n21->ReplaceInput(5, n19); - n21->ReplaceInput(6, n20); - n22->ReplaceInput(0, n21); - n3->ReplaceInput(0, n0); - n9->ReplaceInput(0, n7); - n9->ReplaceInput(1, n13); - n9->ReplaceInput(2, n0); - n9->ReplaceInput(3, n0); - n10->ReplaceInput(0, n9); - n17->ReplaceInput(0, n15); - n17->ReplaceInput(1, n16); - n18->ReplaceInput(0, n17); - n20->ReplaceInput(0, n19); - n16->ReplaceInput(0, n15); - - graph()->SetStart(n0); - graph()->SetEnd(n39); - - ComputeAndVerifySchedule(34); -} - - -TEST_F(SchedulerTest, BuildScheduleSimpleLoop) { - const Operator* op; - Unique<HeapObject> unique_constant = - Unique<HeapObject>::CreateImmovable(factory()->undefined_value()); - - // Manually transcripted code for: - // function turbo_fan_test(a, b) { - // while (a < b) { - // a++; - // } - // return a; - // } - Node* nil = graph()->NewNode(common()->Dead()); - op = common()->End(); - Node* n34 = graph()->NewNode(op, nil); - USE(n34); - op = common()->Return(); - Node* n32 = graph()->NewNode(op, nil, nil, nil); - USE(n32); - op = common()->Phi(kMachAnyTagged, 2); - Node* n13 = graph()->NewNode(op, nil, nil, nil); - USE(n13); - op = js()->LessThan(LanguageMode::SLOPPY); - Node* n16 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil); - USE(n16); - op = common()->IfFalse(); - Node* n22 = graph()->NewNode(op, nil); - USE(n22); - op = common()->Parameter(1); - Node* n2 = graph()->NewNode(op, nil); - USE(n2); - op = js()->Add(LanguageMode::SLOPPY); - Node* n29 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n29); - op = common()->Loop(2); - Node* n12 = graph()->NewNode(op, nil, nil); - USE(n12); - op = common()->Parameter(2); - Node* n3 = graph()->NewNode(op, nil); - USE(n3); - op = common()->Parameter(3); - Node* n5 = graph()->NewNode(op, nil); - USE(n5); - op = common()->FrameState(JS_FRAME, BailoutId(-1), - OutputFrameStateCombine::Ignore()); - Node* n11 = graph()->NewNode(op, nil, nil, nil, nil, nil); - USE(n11); - op = common()->EffectPhi(2); - Node* n14 = graph()->NewNode(op, nil, nil, nil); - USE(n14); - op = common()->Branch(); - Node* n19 = graph()->NewNode(op, nil, nil); - USE(n19); - op = common()->Start(2); - Node* n0 = graph()->NewNode(op); - USE(n0); - op = js()->ToNumber(); - Node* n26 = graph()->NewNode(op, nil, nil, nil, nil, nil); - USE(n26); - op = common()->NumberConstant(1); - Node* n28 = graph()->NewNode(op); - USE(n28); - op = common()->IfSuccess(); - Node* n27 = graph()->NewNode(op, nil); - USE(n27); - op = common()->IfSuccess(); - Node* n8 = graph()->NewNode(op, nil); - USE(n8); - op = common()->IfSuccess(); - Node* n30 = graph()->NewNode(op, nil); - USE(n30); - op = common()->StateValues(0); - Node* n9 = graph()->NewNode(op); - USE(n9); - op = common()->NumberConstant(0); - Node* n10 = graph()->NewNode(op); - USE(n10); - op = common()->HeapConstant(unique_constant); - Node* n4 = graph()->NewNode(op); - USE(n4); - op = js()->StackCheck(); - Node* n7 = graph()->NewNode(op, nil, nil, nil, nil); - USE(n7); - op = js()->ToBoolean(); - Node* n18 = graph()->NewNode(op, nil, nil); - USE(n18); - op = common()->IfSuccess(); - Node* n17 = graph()->NewNode(op, nil); - USE(n17); - op = js()->StackCheck(); - Node* n24 = graph()->NewNode(op, nil, nil, nil, nil); - USE(n24); - op = common()->IfSuccess(); - Node* n25 = graph()->NewNode(op, nil); - USE(n25); - op = common()->IfTrue(); - Node* n20 = graph()->NewNode(op, nil); - USE(n20); - n34->ReplaceInput(0, n32); - n32->ReplaceInput(0, n13); - n32->ReplaceInput(1, n16); - n32->ReplaceInput(2, n22); - n13->ReplaceInput(0, n2); - n13->ReplaceInput(1, n29); - n13->ReplaceInput(2, n12); - n16->ReplaceInput(0, n13); - n16->ReplaceInput(1, n3); - n16->ReplaceInput(2, n5); - n16->ReplaceInput(3, n11); - n16->ReplaceInput(4, n14); - n16->ReplaceInput(5, n12); - n22->ReplaceInput(0, n19); - n2->ReplaceInput(0, n0); - n29->ReplaceInput(0, n26); - n29->ReplaceInput(1, n28); - n29->ReplaceInput(2, n5); - n29->ReplaceInput(3, n11); - n29->ReplaceInput(4, n11); - n29->ReplaceInput(5, n26); - n29->ReplaceInput(6, n27); - n12->ReplaceInput(0, n8); - n12->ReplaceInput(1, n30); - n3->ReplaceInput(0, n0); - n5->ReplaceInput(0, n0); - n11->ReplaceInput(0, n9); - n11->ReplaceInput(1, n9); - n11->ReplaceInput(2, n9); - n11->ReplaceInput(3, n10); - n11->ReplaceInput(4, n4); - n14->ReplaceInput(0, n7); - n14->ReplaceInput(1, n29); - n14->ReplaceInput(2, n12); - n19->ReplaceInput(0, n18); - n19->ReplaceInput(1, n17); - n26->ReplaceInput(0, n13); - n26->ReplaceInput(1, n5); - n26->ReplaceInput(2, n11); - n26->ReplaceInput(3, n24); - n26->ReplaceInput(4, n25); - n27->ReplaceInput(0, n26); - n8->ReplaceInput(0, n7); - n30->ReplaceInput(0, n29); - n7->ReplaceInput(0, n5); - n7->ReplaceInput(1, n11); - n7->ReplaceInput(2, n0); - n7->ReplaceInput(3, n0); - n18->ReplaceInput(0, n16); - n18->ReplaceInput(1, n5); - n17->ReplaceInput(0, n16); - n24->ReplaceInput(0, n5); - n24->ReplaceInput(1, n11); - n24->ReplaceInput(2, n16); - n24->ReplaceInput(3, n20); - n25->ReplaceInput(0, n24); - n20->ReplaceInput(0, n19); - - graph()->SetStart(n0); - graph()->SetEnd(n34); - - ComputeAndVerifySchedule(30); -} - - -TEST_F(SchedulerTest, BuildScheduleComplexLoops) { - const Operator* op; - Unique<HeapObject> unique_constant = - Unique<HeapObject>::CreateImmovable(factory()->undefined_value()); - - // 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()->Dead()); - op = common()->End(); - Node* n71 = graph()->NewNode(op, nil); - USE(n71); - op = common()->Return(); - Node* n69 = graph()->NewNode(op, nil, nil, nil); - USE(n69); - op = common()->Phi(kMachAnyTagged, 2); - Node* n53 = graph()->NewNode(op, nil, nil, nil); - USE(n53); - op = js()->LessThan(LanguageMode::SLOPPY); - Node* n55 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil); - USE(n55); - op = common()->IfFalse(); - Node* n61 = graph()->NewNode(op, nil); - USE(n61); - op = common()->Phi(kMachAnyTagged, 2); - Node* n14 = graph()->NewNode(op, nil, nil, nil); - USE(n14); - op = js()->Add(LanguageMode::SLOPPY); - Node* n66 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n66); - op = common()->Loop(2); - Node* n52 = graph()->NewNode(op, nil, nil); - USE(n52); - op = common()->Parameter(2); - Node* n3 = graph()->NewNode(op, nil); - USE(n3); - op = common()->Parameter(4); - Node* n6 = graph()->NewNode(op, nil); - USE(n6); - op = common()->FrameState(JS_FRAME, BailoutId(-1), - OutputFrameStateCombine::Ignore()); - Node* n12 = graph()->NewNode(op, nil, nil, nil, nil, nil); - USE(n12); - op = common()->EffectPhi(2); - Node* n54 = graph()->NewNode(op, nil, nil, nil); - USE(n54); - op = common()->Branch(); - Node* n58 = graph()->NewNode(op, nil, nil); - USE(n58); - op = common()->Parameter(1); - Node* n2 = graph()->NewNode(op, nil); - USE(n2); - op = js()->Add(LanguageMode::SLOPPY); - Node* n31 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n31); - op = common()->Loop(2); - Node* n13 = graph()->NewNode(op, nil, nil); - USE(n13); - op = common()->NumberConstant(2); - Node* n65 = graph()->NewNode(op); - USE(n65); - op = js()->StackCheck(); - Node* n63 = graph()->NewNode(op, nil, nil, nil, nil); - USE(n63); - op = common()->IfSuccess(); - Node* n64 = graph()->NewNode(op, nil); - USE(n64); - op = common()->IfFalse(); - Node* n24 = graph()->NewNode(op, nil); - USE(n24); - op = common()->IfSuccess(); - Node* n67 = graph()->NewNode(op, nil); - USE(n67); - op = common()->Start(3); - Node* n0 = graph()->NewNode(op); - USE(n0); - op = common()->StateValues(0); - Node* n10 = graph()->NewNode(op); - USE(n10); - op = common()->NumberConstant(0); - Node* n11 = graph()->NewNode(op); - USE(n11); - op = common()->HeapConstant(unique_constant); - Node* n5 = graph()->NewNode(op); - USE(n5); - op = js()->LessThan(LanguageMode::SLOPPY); - Node* n18 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil); - USE(n18); - op = js()->ToBoolean(); - Node* n57 = graph()->NewNode(op, nil, nil); - USE(n57); - op = common()->IfSuccess(); - Node* n56 = graph()->NewNode(op, nil); - USE(n56); - op = js()->ToNumber(); - Node* n28 = graph()->NewNode(op, nil, nil, nil, nil, nil); - USE(n28); - op = common()->NumberConstant(1); - Node* n30 = graph()->NewNode(op); - USE(n30); - op = common()->IfSuccess(); - Node* n29 = graph()->NewNode(op, nil); - USE(n29); - op = common()->IfSuccess(); - Node* n9 = graph()->NewNode(op, nil); - USE(n9); - op = common()->IfFalse(); - Node* n42 = graph()->NewNode(op, nil); - USE(n42); - op = common()->IfTrue(); - Node* n59 = graph()->NewNode(op, nil); - USE(n59); - op = common()->Branch(); - Node* n21 = graph()->NewNode(op, nil, nil); - USE(n21); - op = common()->EffectPhi(2); - Node* n16 = graph()->NewNode(op, nil, nil, nil); - USE(n16); - op = js()->StackCheck(); - Node* n26 = graph()->NewNode(op, nil, nil, nil, nil); - USE(n26); - op = common()->IfSuccess(); - Node* n27 = graph()->NewNode(op, nil); - USE(n27); - op = js()->StackCheck(); - Node* n8 = graph()->NewNode(op, nil, nil, nil, nil); - USE(n8); - op = common()->Branch(); - Node* n39 = graph()->NewNode(op, nil, nil); - USE(n39); - op = js()->ToBoolean(); - Node* n20 = graph()->NewNode(op, nil, nil); - USE(n20); - op = common()->IfSuccess(); - Node* n19 = graph()->NewNode(op, nil); - USE(n19); - op = js()->LessThan(LanguageMode::SLOPPY); - Node* n36 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil); - USE(n36); - op = common()->IfTrue(); - Node* n22 = graph()->NewNode(op, nil); - USE(n22); - op = js()->ToBoolean(); - Node* n38 = graph()->NewNode(op, nil, nil); - USE(n38); - op = common()->IfSuccess(); - Node* n37 = graph()->NewNode(op, nil); - USE(n37); - op = common()->Phi(kMachAnyTagged, 2); - Node* n34 = graph()->NewNode(op, nil, nil, nil); - USE(n34); - op = common()->EffectPhi(2); - Node* n35 = graph()->NewNode(op, nil, nil, nil); - USE(n35); - op = common()->Loop(2); - Node* n33 = graph()->NewNode(op, nil, nil); - USE(n33); - op = common()->Phi(kMachAnyTagged, 2); - Node* n15 = graph()->NewNode(op, nil, nil, nil); - USE(n15); - op = js()->Add(LanguageMode::SLOPPY); - Node* n48 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n48); - op = common()->IfSuccess(); - Node* n32 = graph()->NewNode(op, nil); - USE(n32); - op = common()->IfSuccess(); - Node* n49 = graph()->NewNode(op, nil); - USE(n49); - op = common()->Parameter(3); - Node* n4 = graph()->NewNode(op, nil); - USE(n4); - op = js()->ToNumber(); - Node* n46 = graph()->NewNode(op, nil, nil, nil, nil, nil); - USE(n46); - op = common()->IfSuccess(); - Node* n47 = graph()->NewNode(op, nil); - USE(n47); - op = js()->StackCheck(); - Node* n44 = graph()->NewNode(op, nil, nil, nil, nil); - USE(n44); - op = common()->IfSuccess(); - Node* n45 = graph()->NewNode(op, nil); - USE(n45); - op = common()->IfTrue(); - Node* n40 = graph()->NewNode(op, nil); - USE(n40); - n71->ReplaceInput(0, n69); - n69->ReplaceInput(0, n53); - n69->ReplaceInput(1, n55); - n69->ReplaceInput(2, n61); - n53->ReplaceInput(0, n14); - n53->ReplaceInput(1, n66); - n53->ReplaceInput(2, n52); - n55->ReplaceInput(0, n53); - n55->ReplaceInput(1, n3); - n55->ReplaceInput(2, n6); - n55->ReplaceInput(3, n12); - n55->ReplaceInput(4, n54); - n55->ReplaceInput(5, n52); - n61->ReplaceInput(0, n58); - n14->ReplaceInput(0, n2); - n14->ReplaceInput(1, n31); - n14->ReplaceInput(2, n13); - n66->ReplaceInput(0, n53); - n66->ReplaceInput(1, n65); - n66->ReplaceInput(2, n6); - n66->ReplaceInput(3, n12); - n66->ReplaceInput(4, n12); - n66->ReplaceInput(5, n63); - n66->ReplaceInput(6, n64); - n52->ReplaceInput(0, n24); - n52->ReplaceInput(1, n67); - n3->ReplaceInput(0, n0); - n6->ReplaceInput(0, n0); - n12->ReplaceInput(0, n10); - n12->ReplaceInput(1, n10); - n12->ReplaceInput(2, n10); - n12->ReplaceInput(3, n11); - n12->ReplaceInput(4, n5); - n54->ReplaceInput(0, n18); - n54->ReplaceInput(1, n66); - n54->ReplaceInput(2, n52); - n58->ReplaceInput(0, n57); - n58->ReplaceInput(1, n56); - n2->ReplaceInput(0, n0); - n31->ReplaceInput(0, n28); - n31->ReplaceInput(1, n30); - n31->ReplaceInput(2, n6); - n31->ReplaceInput(3, n12); - n31->ReplaceInput(4, n12); - n31->ReplaceInput(5, n28); - n31->ReplaceInput(6, n29); - n13->ReplaceInput(0, n9); - n13->ReplaceInput(1, n42); - n63->ReplaceInput(0, n6); - n63->ReplaceInput(1, n12); - n63->ReplaceInput(2, n55); - n63->ReplaceInput(3, n59); - n64->ReplaceInput(0, n63); - n24->ReplaceInput(0, n21); - n67->ReplaceInput(0, n66); - n18->ReplaceInput(0, n14); - n18->ReplaceInput(1, n3); - n18->ReplaceInput(2, n6); - n18->ReplaceInput(3, n12); - n18->ReplaceInput(4, n16); - n18->ReplaceInput(5, n13); - n57->ReplaceInput(0, n55); - n57->ReplaceInput(1, n6); - n56->ReplaceInput(0, n55); - n28->ReplaceInput(0, n14); - n28->ReplaceInput(1, n6); - n28->ReplaceInput(2, n12); - n28->ReplaceInput(3, n26); - n28->ReplaceInput(4, n27); - n29->ReplaceInput(0, n28); - n9->ReplaceInput(0, n8); - n42->ReplaceInput(0, n39); - n59->ReplaceInput(0, n58); - n21->ReplaceInput(0, n20); - n21->ReplaceInput(1, n19); - n16->ReplaceInput(0, n8); - n16->ReplaceInput(1, n36); - n16->ReplaceInput(2, n13); - n26->ReplaceInput(0, n6); - n26->ReplaceInput(1, n12); - n26->ReplaceInput(2, n18); - n26->ReplaceInput(3, n22); - n27->ReplaceInput(0, n26); - n8->ReplaceInput(0, n6); - n8->ReplaceInput(1, n12); - n8->ReplaceInput(2, n0); - n8->ReplaceInput(3, n0); - n39->ReplaceInput(0, n38); - n39->ReplaceInput(1, n37); - n20->ReplaceInput(0, n18); - n20->ReplaceInput(1, n6); - n19->ReplaceInput(0, n18); - n36->ReplaceInput(0, n34); - n36->ReplaceInput(1, n3); - n36->ReplaceInput(2, n6); - n36->ReplaceInput(3, n12); - n36->ReplaceInput(4, n35); - n36->ReplaceInput(5, n33); - n22->ReplaceInput(0, n21); - n38->ReplaceInput(0, n36); - n38->ReplaceInput(1, n6); - n37->ReplaceInput(0, n36); - n34->ReplaceInput(0, n15); - n34->ReplaceInput(1, n48); - n34->ReplaceInput(2, n33); - n35->ReplaceInput(0, n31); - n35->ReplaceInput(1, n48); - n35->ReplaceInput(2, n33); - n33->ReplaceInput(0, n32); - n33->ReplaceInput(1, n49); - n15->ReplaceInput(0, n4); - n15->ReplaceInput(1, n34); - n15->ReplaceInput(2, n13); - n48->ReplaceInput(0, n46); - n48->ReplaceInput(1, n30); - n48->ReplaceInput(2, n6); - n48->ReplaceInput(3, n12); - n48->ReplaceInput(4, n12); - n48->ReplaceInput(5, n46); - n48->ReplaceInput(6, n47); - n32->ReplaceInput(0, n31); - n49->ReplaceInput(0, n48); - n4->ReplaceInput(0, n0); - n46->ReplaceInput(0, n34); - n46->ReplaceInput(1, n6); - n46->ReplaceInput(2, n12); - n46->ReplaceInput(3, n44); - n46->ReplaceInput(4, n45); - n47->ReplaceInput(0, n46); - n44->ReplaceInput(0, n6); - n44->ReplaceInput(1, n12); - n44->ReplaceInput(2, n36); - n44->ReplaceInput(3, n40); - n45->ReplaceInput(0, n44); - n40->ReplaceInput(0, n39); - - graph()->SetStart(n0); - graph()->SetEnd(n71); - - ComputeAndVerifySchedule(65); -} - - -TEST_F(SchedulerTest, BuildScheduleBreakAndContinue) { - const Operator* op; - Unique<HeapObject> unique_constant = - Unique<HeapObject>::CreateImmovable(factory()->undefined_value()); - - // 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()->Dead()); - op = common()->End(); - Node* n86 = graph()->NewNode(op, nil); - USE(n86); - op = common()->Return(); - Node* n84 = graph()->NewNode(op, nil, nil, nil); - USE(n84); - op = js()->Add(LanguageMode::SLOPPY); - Node* n82 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n82); - op = common()->IfSuccess(); - Node* n83 = graph()->NewNode(op, nil); - USE(n83); - op = common()->Phi(kMachAnyTagged, 2); - Node* n15 = graph()->NewNode(op, nil, nil, nil); - USE(n15); - op = common()->Phi(kMachAnyTagged, 2); - Node* n17 = graph()->NewNode(op, nil, nil, nil); - USE(n17); - op = common()->Parameter(4); - Node* n6 = graph()->NewNode(op, nil); - USE(n6); - op = common()->FrameState(JS_FRAME, BailoutId(-1), - OutputFrameStateCombine::Ignore()); - Node* n12 = graph()->NewNode(op, nil, nil, nil, nil, nil); - USE(n12); - op = js()->LessThan(LanguageMode::SLOPPY); - Node* n19 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil); - USE(n19); - op = common()->IfFalse(); - Node* n25 = graph()->NewNode(op, nil); - USE(n25); - op = common()->Parameter(1); - Node* n2 = graph()->NewNode(op, nil); - USE(n2); - op = common()->Phi(kMachAnyTagged, 2); - Node* n35 = graph()->NewNode(op, nil, nil, nil); - USE(n35); - op = common()->Loop(2); - Node* n14 = graph()->NewNode(op, nil, nil); - USE(n14); - op = common()->NumberConstant(0); - Node* n11 = graph()->NewNode(op); - USE(n11); - op = common()->Phi(kMachAnyTagged, 2); - Node* n81 = graph()->NewNode(op, nil, nil, nil); - USE(n81); - op = common()->Start(3); - Node* n0 = graph()->NewNode(op); - USE(n0); - op = common()->StateValues(0); - Node* n10 = graph()->NewNode(op); - USE(n10); - op = common()->HeapConstant(unique_constant); - Node* n5 = graph()->NewNode(op); - USE(n5); - op = common()->Parameter(2); - Node* n3 = graph()->NewNode(op, nil); - USE(n3); - op = common()->EffectPhi(2); - Node* n18 = graph()->NewNode(op, nil, nil, nil); - USE(n18); - op = common()->Branch(); - Node* n22 = graph()->NewNode(op, nil, nil); - USE(n22); - op = js()->Add(LanguageMode::SLOPPY); - Node* n32 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n32); - op = js()->Add(LanguageMode::SLOPPY); - Node* n64 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n64); - op = common()->Loop(2); - Node* n34 = graph()->NewNode(op, nil, nil); - USE(n34); - op = common()->IfSuccess(); - Node* n9 = graph()->NewNode(op, nil); - USE(n9); - op = common()->Merge(2); - Node* n72 = graph()->NewNode(op, nil, nil); - USE(n72); - op = js()->Add(LanguageMode::SLOPPY); - Node* n78 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n78); - op = js()->StackCheck(); - Node* n8 = graph()->NewNode(op, nil, nil, nil, nil); - USE(n8); - op = common()->EffectPhi(2); - Node* n80 = graph()->NewNode(op, nil, nil, nil); - USE(n80); - op = js()->ToBoolean(); - Node* n21 = graph()->NewNode(op, nil, nil); - USE(n21); - op = common()->IfSuccess(); - Node* n20 = graph()->NewNode(op, nil); - USE(n20); - op = js()->ToNumber(); - Node* n29 = graph()->NewNode(op, nil, nil, nil, nil, nil); - USE(n29); - op = common()->NumberConstant(1); - Node* n31 = graph()->NewNode(op); - USE(n31); - op = common()->IfSuccess(); - Node* n30 = graph()->NewNode(op, nil); - USE(n30); - op = js()->ToNumber(); - Node* n62 = graph()->NewNode(op, nil, nil, nil, nil, nil); - USE(n62); - op = common()->IfSuccess(); - Node* n63 = graph()->NewNode(op, nil); - USE(n63); - op = common()->IfSuccess(); - Node* n33 = graph()->NewNode(op, nil); - USE(n33); - op = common()->IfSuccess(); - Node* n65 = graph()->NewNode(op, nil); - USE(n65); - op = common()->IfTrue(); - Node* n71 = graph()->NewNode(op, nil); - USE(n71); - op = common()->IfSuccess(); - Node* n79 = graph()->NewNode(op, nil); - USE(n79); - op = js()->ToNumber(); - Node* n76 = graph()->NewNode(op, nil, nil, nil, nil, nil); - USE(n76); - op = common()->IfSuccess(); - Node* n77 = graph()->NewNode(op, nil); - USE(n77); - op = js()->Equal(); - Node* n67 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil); - USE(n67); - op = js()->StackCheck(); - Node* n27 = graph()->NewNode(op, nil, nil, nil, nil); - USE(n27); - op = common()->IfSuccess(); - Node* n28 = graph()->NewNode(op, nil); - USE(n28); - op = js()->Equal(); - Node* n52 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil); - USE(n52); - op = common()->IfFalse(); - Node* n60 = graph()->NewNode(op, nil); - USE(n60); - op = common()->Branch(); - Node* n70 = graph()->NewNode(op, nil, nil); - USE(n70); - op = common()->IfFalse(); - Node* n74 = graph()->NewNode(op, nil); - USE(n74); - op = common()->EffectPhi(2); - Node* n57 = graph()->NewNode(op, nil, nil, nil); - USE(n57); - op = common()->Merge(2); - Node* n45 = graph()->NewNode(op, nil, nil); - USE(n45); - op = common()->IfTrue(); - Node* n23 = graph()->NewNode(op, nil); - USE(n23); - op = js()->Add(LanguageMode::SLOPPY); - Node* n50 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n50); - op = common()->IfSuccess(); - Node* n51 = graph()->NewNode(op, nil); - USE(n51); - op = common()->Branch(); - Node* n55 = graph()->NewNode(op, nil, nil); - USE(n55); - op = js()->ToBoolean(); - Node* n69 = graph()->NewNode(op, nil, nil); - USE(n69); - op = common()->IfSuccess(); - Node* n68 = graph()->NewNode(op, nil); - USE(n68); - op = js()->LessThan(LanguageMode::SLOPPY); - Node* n38 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil); - USE(n38); - op = common()->IfFalse(); - Node* n44 = graph()->NewNode(op, nil); - USE(n44); - op = common()->IfTrue(); - Node* n56 = graph()->NewNode(op, nil); - USE(n56); - op = js()->ToNumber(); - Node* n48 = graph()->NewNode(op, nil, nil, nil, nil, nil); - USE(n48); - op = common()->IfSuccess(); - Node* n49 = graph()->NewNode(op, nil); - USE(n49); - op = js()->ToBoolean(); - Node* n54 = graph()->NewNode(op, nil, nil); - USE(n54); - op = common()->IfSuccess(); - Node* n53 = graph()->NewNode(op, nil); - USE(n53); - op = common()->Phi(kMachAnyTagged, 2); - Node* n36 = graph()->NewNode(op, nil, nil, nil); - USE(n36); - op = common()->EffectPhi(2); - Node* n37 = graph()->NewNode(op, nil, nil, nil); - USE(n37); - op = common()->Branch(); - Node* n41 = graph()->NewNode(op, nil, nil); - USE(n41); - op = js()->StackCheck(); - Node* n46 = graph()->NewNode(op, nil, nil, nil, nil); - USE(n46); - op = common()->IfSuccess(); - Node* n47 = graph()->NewNode(op, nil); - USE(n47); - op = common()->Phi(kMachAnyTagged, 2); - Node* n16 = graph()->NewNode(op, nil, nil, nil); - USE(n16); - op = js()->ToBoolean(); - Node* n40 = graph()->NewNode(op, nil, nil); - USE(n40); - op = common()->IfSuccess(); - Node* n39 = graph()->NewNode(op, nil); - USE(n39); - op = common()->IfTrue(); - Node* n42 = graph()->NewNode(op, nil); - USE(n42); - op = common()->Parameter(3); - Node* n4 = graph()->NewNode(op, nil); - USE(n4); - op = common()->Phi(kMachAnyTagged, 2); - Node* n58 = graph()->NewNode(op, nil, nil, nil); - USE(n58); - n86->ReplaceInput(0, n84); - n84->ReplaceInput(0, n82); - n84->ReplaceInput(1, n82); - n84->ReplaceInput(2, n83); - n82->ReplaceInput(0, n15); - n82->ReplaceInput(1, n17); - n82->ReplaceInput(2, n6); - n82->ReplaceInput(3, n12); - n82->ReplaceInput(4, n12); - n82->ReplaceInput(5, n19); - n82->ReplaceInput(6, n25); - n83->ReplaceInput(0, n82); - n15->ReplaceInput(0, n2); - n15->ReplaceInput(1, n35); - n15->ReplaceInput(2, n14); - n17->ReplaceInput(0, n11); - n17->ReplaceInput(1, n81); - n17->ReplaceInput(2, n14); - n6->ReplaceInput(0, n0); - n12->ReplaceInput(0, n10); - n12->ReplaceInput(1, n10); - n12->ReplaceInput(2, n10); - n12->ReplaceInput(3, n11); - n12->ReplaceInput(4, n5); - n19->ReplaceInput(0, n15); - n19->ReplaceInput(1, n3); - n19->ReplaceInput(2, n6); - n19->ReplaceInput(3, n12); - n19->ReplaceInput(4, n18); - n19->ReplaceInput(5, n14); - n25->ReplaceInput(0, n22); - n2->ReplaceInput(0, n0); - n35->ReplaceInput(0, n32); - n35->ReplaceInput(1, n64); - n35->ReplaceInput(2, n34); - n14->ReplaceInput(0, n9); - n14->ReplaceInput(1, n72); - n81->ReplaceInput(0, n17); - n81->ReplaceInput(1, n78); - n81->ReplaceInput(2, n72); - n3->ReplaceInput(0, n0); - n18->ReplaceInput(0, n8); - n18->ReplaceInput(1, n80); - n18->ReplaceInput(2, n14); - n22->ReplaceInput(0, n21); - n22->ReplaceInput(1, n20); - n32->ReplaceInput(0, n29); - n32->ReplaceInput(1, n31); - n32->ReplaceInput(2, n6); - n32->ReplaceInput(3, n12); - n32->ReplaceInput(4, n12); - n32->ReplaceInput(5, n29); - n32->ReplaceInput(6, n30); - n64->ReplaceInput(0, n62); - n64->ReplaceInput(1, n31); - n64->ReplaceInput(2, n6); - n64->ReplaceInput(3, n12); - n64->ReplaceInput(4, n12); - n64->ReplaceInput(5, n62); - n64->ReplaceInput(6, n63); - n34->ReplaceInput(0, n33); - n34->ReplaceInput(1, n65); - n9->ReplaceInput(0, n8); - n72->ReplaceInput(0, n71); - n72->ReplaceInput(1, n79); - n78->ReplaceInput(0, n76); - n78->ReplaceInput(1, n31); - n78->ReplaceInput(2, n6); - n78->ReplaceInput(3, n12); - n78->ReplaceInput(4, n12); - n78->ReplaceInput(5, n76); - n78->ReplaceInput(6, n77); - n8->ReplaceInput(0, n6); - n8->ReplaceInput(1, n12); - n8->ReplaceInput(2, n0); - n8->ReplaceInput(3, n0); - n80->ReplaceInput(0, n67); - n80->ReplaceInput(1, n78); - n80->ReplaceInput(2, n72); - n21->ReplaceInput(0, n19); - n21->ReplaceInput(1, n6); - n20->ReplaceInput(0, n19); - n29->ReplaceInput(0, n15); - n29->ReplaceInput(1, n6); - n29->ReplaceInput(2, n12); - n29->ReplaceInput(3, n27); - n29->ReplaceInput(4, n28); - n30->ReplaceInput(0, n29); - n62->ReplaceInput(0, n35); - n62->ReplaceInput(1, n6); - n62->ReplaceInput(2, n12); - n62->ReplaceInput(3, n52); - n62->ReplaceInput(4, n60); - n63->ReplaceInput(0, n62); - n33->ReplaceInput(0, n32); - n65->ReplaceInput(0, n64); - n71->ReplaceInput(0, n70); - n79->ReplaceInput(0, n78); - n76->ReplaceInput(0, n17); - n76->ReplaceInput(1, n6); - n76->ReplaceInput(2, n12); - n76->ReplaceInput(3, n67); - n76->ReplaceInput(4, n74); - n77->ReplaceInput(0, n76); - n67->ReplaceInput(0, n35); - n67->ReplaceInput(1, n31); - n67->ReplaceInput(2, n6); - n67->ReplaceInput(3, n12); - n67->ReplaceInput(4, n57); - n67->ReplaceInput(5, n45); - n27->ReplaceInput(0, n6); - n27->ReplaceInput(1, n12); - n27->ReplaceInput(2, n19); - n27->ReplaceInput(3, n23); - n28->ReplaceInput(0, n27); - n52->ReplaceInput(0, n17); - n52->ReplaceInput(1, n11); - n52->ReplaceInput(2, n6); - n52->ReplaceInput(3, n12); - n52->ReplaceInput(4, n50); - n52->ReplaceInput(5, n51); - n60->ReplaceInput(0, n55); - n70->ReplaceInput(0, n69); - n70->ReplaceInput(1, n68); - n74->ReplaceInput(0, n70); - n57->ReplaceInput(0, n38); - n57->ReplaceInput(1, n52); - n57->ReplaceInput(2, n45); - n45->ReplaceInput(0, n44); - n45->ReplaceInput(1, n56); - n23->ReplaceInput(0, n22); - n50->ReplaceInput(0, n48); - n50->ReplaceInput(1, n31); - n50->ReplaceInput(2, n6); - n50->ReplaceInput(3, n12); - n50->ReplaceInput(4, n12); - n50->ReplaceInput(5, n48); - n50->ReplaceInput(6, n49); - n51->ReplaceInput(0, n50); - n55->ReplaceInput(0, n54); - n55->ReplaceInput(1, n53); - n69->ReplaceInput(0, n67); - n69->ReplaceInput(1, n6); - n68->ReplaceInput(0, n67); - n38->ReplaceInput(0, n36); - n38->ReplaceInput(1, n3); - n38->ReplaceInput(2, n6); - n38->ReplaceInput(3, n12); - n38->ReplaceInput(4, n37); - n38->ReplaceInput(5, n34); - n44->ReplaceInput(0, n41); - n56->ReplaceInput(0, n55); - n48->ReplaceInput(0, n36); - n48->ReplaceInput(1, n6); - n48->ReplaceInput(2, n12); - n48->ReplaceInput(3, n46); - n48->ReplaceInput(4, n47); - n49->ReplaceInput(0, n48); - n54->ReplaceInput(0, n52); - n54->ReplaceInput(1, n6); - n53->ReplaceInput(0, n52); - n36->ReplaceInput(0, n16); - n36->ReplaceInput(1, n50); - n36->ReplaceInput(2, n34); - n37->ReplaceInput(0, n32); - n37->ReplaceInput(1, n64); - n37->ReplaceInput(2, n34); - n41->ReplaceInput(0, n40); - n41->ReplaceInput(1, n39); - n46->ReplaceInput(0, n6); - n46->ReplaceInput(1, n12); - n46->ReplaceInput(2, n38); - n46->ReplaceInput(3, n42); - n47->ReplaceInput(0, n46); - n16->ReplaceInput(0, n4); - n16->ReplaceInput(1, n58); - n16->ReplaceInput(2, n14); - n40->ReplaceInput(0, n38); - n40->ReplaceInput(1, n6); - n39->ReplaceInput(0, n38); - n42->ReplaceInput(0, n41); - n4->ReplaceInput(0, n0); - n58->ReplaceInput(0, n36); - n58->ReplaceInput(1, n50); - n58->ReplaceInput(2, n45); - - graph()->SetStart(n0); - graph()->SetEnd(n86); - - ComputeAndVerifySchedule(83); -} - - -TEST_F(SchedulerTest, BuildScheduleSimpleLoopWithCodeMotion) { - const Operator* op; - Unique<HeapObject> unique_constant = - Unique<HeapObject>::CreateImmovable(factory()->undefined_value()); - - // Manually transcripted code for: - // function turbo_fan_test(a, b, c) { - // while (a < b) { - // a += b + c; - // } - // return a; - // } - Node* nil = graph()->NewNode(common()->Dead()); - op = common()->End(); - Node* n34 = graph()->NewNode(op, nil); - USE(n34); - op = common()->Return(); - Node* n32 = graph()->NewNode(op, nil, nil, nil); - USE(n32); - op = common()->Phi(kMachAnyTagged, 2); - Node* n14 = graph()->NewNode(op, nil, nil, nil); - USE(n14); - op = js()->LessThan(LanguageMode::SLOPPY); - Node* n17 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil); - USE(n17); - op = common()->IfFalse(); - Node* n23 = graph()->NewNode(op, nil); - USE(n23); - op = common()->Parameter(1); - Node* n2 = graph()->NewNode(op, nil); - USE(n2); - op = js()->Add(LanguageMode::SLOPPY); - Node* n29 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n29); - op = common()->Loop(2); - Node* n13 = graph()->NewNode(op, nil, nil); - USE(n13); - op = common()->Parameter(2); - Node* n3 = graph()->NewNode(op, nil); - USE(n3); - op = common()->Parameter(4); - Node* n6 = graph()->NewNode(op, nil); - USE(n6); - op = common()->FrameState(JS_FRAME, BailoutId(-1), - OutputFrameStateCombine::Ignore()); - Node* n12 = graph()->NewNode(op, nil, nil, nil, nil, nil); - USE(n12); - op = common()->EffectPhi(2); - Node* n15 = graph()->NewNode(op, nil, nil, nil); - USE(n15); - op = common()->Branch(); - Node* n20 = graph()->NewNode(op, nil, nil); - USE(n20); - op = common()->Start(3); - Node* n0 = graph()->NewNode(op); - USE(n0); - op = js()->Add(LanguageMode::SLOPPY); - Node* n27 = graph()->NewNode(op, nil, nil, nil, nil, nil, nil, nil); - USE(n27); - op = common()->IfSuccess(); - Node* n28 = graph()->NewNode(op, nil); - USE(n28); - op = common()->IfSuccess(); - Node* n9 = graph()->NewNode(op, nil); - USE(n9); - op = common()->IfSuccess(); - Node* n30 = graph()->NewNode(op, nil); - USE(n30); - op = common()->StateValues(0); - Node* n10 = graph()->NewNode(op); - USE(n10); - op = common()->NumberConstant(0); - Node* n11 = graph()->NewNode(op); - USE(n11); - op = common()->HeapConstant(unique_constant); - Node* n5 = graph()->NewNode(op); - USE(n5); - op = js()->StackCheck(); - Node* n8 = graph()->NewNode(op, nil, nil, nil, nil); - USE(n8); - op = js()->ToBoolean(); - Node* n19 = graph()->NewNode(op, nil, nil); - USE(n19); - op = common()->IfSuccess(); - Node* n18 = graph()->NewNode(op, nil); - USE(n18); - op = common()->Parameter(3); - Node* n4 = graph()->NewNode(op, nil); - USE(n4); - op = js()->StackCheck(); - Node* n25 = graph()->NewNode(op, nil, nil, nil, nil); - USE(n25); - op = common()->IfSuccess(); - Node* n26 = graph()->NewNode(op, nil); - USE(n26); - op = common()->IfTrue(); - Node* n21 = graph()->NewNode(op, nil); - USE(n21); - n34->ReplaceInput(0, n32); - n32->ReplaceInput(0, n14); - n32->ReplaceInput(1, n17); - n32->ReplaceInput(2, n23); - n14->ReplaceInput(0, n2); - n14->ReplaceInput(1, n29); - n14->ReplaceInput(2, n13); - n17->ReplaceInput(0, n14); - n17->ReplaceInput(1, n3); - n17->ReplaceInput(2, n6); - n17->ReplaceInput(3, n12); - n17->ReplaceInput(4, n15); - n17->ReplaceInput(5, n13); - n23->ReplaceInput(0, n20); - n2->ReplaceInput(0, n0); - n29->ReplaceInput(0, n14); - n29->ReplaceInput(1, n27); - n29->ReplaceInput(2, n6); - n29->ReplaceInput(3, n12); - n29->ReplaceInput(4, n12); - n29->ReplaceInput(5, n27); - n29->ReplaceInput(6, n28); - n13->ReplaceInput(0, n9); - n13->ReplaceInput(1, n30); - n3->ReplaceInput(0, n0); - n6->ReplaceInput(0, n0); - n12->ReplaceInput(0, n10); - n12->ReplaceInput(1, n10); - n12->ReplaceInput(2, n10); - n12->ReplaceInput(3, n11); - n12->ReplaceInput(4, n5); - n15->ReplaceInput(0, n8); - n15->ReplaceInput(1, n29); - n15->ReplaceInput(2, n13); - n20->ReplaceInput(0, n19); - n20->ReplaceInput(1, n18); - n27->ReplaceInput(0, n3); - n27->ReplaceInput(1, n4); - n27->ReplaceInput(2, n6); - n27->ReplaceInput(3, n12); - n27->ReplaceInput(4, n12); - n27->ReplaceInput(5, n25); - n27->ReplaceInput(6, n26); - n28->ReplaceInput(0, n27); - n9->ReplaceInput(0, n8); - n30->ReplaceInput(0, n29); - n8->ReplaceInput(0, n6); - n8->ReplaceInput(1, n12); - n8->ReplaceInput(2, n0); - n8->ReplaceInput(3, n0); - n19->ReplaceInput(0, n17); - n19->ReplaceInput(1, n6); - n18->ReplaceInput(0, n17); - n4->ReplaceInput(0, n0); - n25->ReplaceInput(0, n6); - n25->ReplaceInput(1, n12); - n25->ReplaceInput(2, n17); - n25->ReplaceInput(3, n21); - n26->ReplaceInput(0, n25); - n21->ReplaceInput(0, n20); - - graph()->SetStart(n0); - graph()->SetEnd(n34); - - ComputeAndVerifySchedule(30); -} - - namespace { Node* CreateDiamond(Graph* graph, CommonOperatorBuilder* common, Node* cond) { @@ -2025,7 +697,7 @@ TARGET_TEST_F(SchedulerTest, FloatingDiamond1) { Node* p0 = graph()->NewNode(common()->Parameter(0), start); Node* d1 = CreateDiamond(graph(), common(), p0); Node* ret = graph()->NewNode(common()->Return(), d1, start, start); - Node* end = graph()->NewNode(common()->End(), ret, start); + Node* end = graph()->NewNode(common()->End(1), ret); graph()->SetEnd(end); @@ -2043,7 +715,7 @@ TARGET_TEST_F(SchedulerTest, FloatingDiamond2) { Node* d2 = CreateDiamond(graph(), common(), p1); Node* add = graph()->NewNode(&kIntAdd, d1, d2); Node* ret = graph()->NewNode(common()->Return(), add, start, start); - Node* end = graph()->NewNode(common()->End(), ret, start); + Node* end = graph()->NewNode(common()->End(1), ret); graph()->SetEnd(end); @@ -2062,7 +734,7 @@ TARGET_TEST_F(SchedulerTest, FloatingDiamond3) { Node* add = graph()->NewNode(&kIntAdd, d1, d2); Node* d3 = CreateDiamond(graph(), common(), add); Node* ret = graph()->NewNode(common()->Return(), d3, start, start); - Node* end = graph()->NewNode(common()->End(), ret, start); + Node* end = graph()->NewNode(common()->End(1), ret); graph()->SetEnd(end); @@ -2099,7 +771,7 @@ TARGET_TEST_F(SchedulerTest, NestedFloatingDiamonds) { Node* ephi1 = graph()->NewNode(common()->EffectPhi(2), start, map, m); Node* ret = graph()->NewNode(common()->Return(), phi, ephi1, start); - Node* end = graph()->NewNode(common()->End(), ret, start); + Node* end = graph()->NewNode(common()->End(1), ret); graph()->SetEnd(end); @@ -2143,7 +815,7 @@ TARGET_TEST_F(SchedulerTest, NestedFloatingDiamondWithChain) { Node* add = graph()->NewNode(&kIntAdd, phiA2, phiB2); Node* ret = graph()->NewNode(common()->Return(), add, start, start); - Node* end = graph()->NewNode(common()->End(), ret, start); + Node* end = graph()->NewNode(common()->End(1), ret); graph()->SetEnd(end); @@ -2177,7 +849,7 @@ TARGET_TEST_F(SchedulerTest, NestedFloatingDiamondWithLoop) { Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), fv, ind, m); Node* ret = graph()->NewNode(common()->Return(), phi, start, start); - Node* end = graph()->NewNode(common()->End(), ret, start); + Node* end = graph()->NewNode(common()->End(1), ret); graph()->SetEnd(end); @@ -2210,7 +882,7 @@ TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond1) { ind->ReplaceInput(1, phi1); // close induction variable. Node* ret = graph()->NewNode(common()->Return(), ind, start, f); - Node* end = graph()->NewNode(common()->End(), ret, f); + Node* end = graph()->NewNode(common()->End(2), ret, f); graph()->SetEnd(end); @@ -2244,7 +916,7 @@ TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond2) { ind->ReplaceInput(1, add); // close induction variable. Node* ret = graph()->NewNode(common()->Return(), ind, start, f); - Node* end = graph()->NewNode(common()->End(), ret, f); + Node* end = graph()->NewNode(common()->End(2), ret, f); graph()->SetEnd(end); @@ -2290,7 +962,7 @@ TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond3) { ind->ReplaceInput(1, add); // close induction variable. Node* ret = graph()->NewNode(common()->Return(), ind, start, f); - Node* end = graph()->NewNode(common()->End(), ret, f); + Node* end = graph()->NewNode(common()->End(2), ret, f); graph()->SetEnd(end); @@ -2324,7 +996,7 @@ TARGET_TEST_F(SchedulerTest, PhisPushedDownToDifferentBranches) { graph()->NewNode(common()->Phi(kMachAnyTagged, 2), phi, phi2, m2); Node* ret = graph()->NewNode(common()->Return(), phi3, start, start); - Node* end = graph()->NewNode(common()->End(), ret, start); + Node* end = graph()->NewNode(common()->End(1), ret); graph()->SetEnd(end); @@ -2345,7 +1017,7 @@ TARGET_TEST_F(SchedulerTest, BranchHintTrue) { Node* m = graph()->NewNode(common()->Merge(2), t, f); Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), tv, fv, m); Node* ret = graph()->NewNode(common()->Return(), phi, start, start); - Node* end = graph()->NewNode(common()->End(), ret, start); + Node* end = graph()->NewNode(common()->End(1), ret); graph()->SetEnd(end); @@ -2369,7 +1041,7 @@ TARGET_TEST_F(SchedulerTest, BranchHintFalse) { Node* m = graph()->NewNode(common()->Merge(2), t, f); Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), tv, fv, m); Node* ret = graph()->NewNode(common()->Return(), phi, start, start); - Node* end = graph()->NewNode(common()->End(), ret, start); + Node* end = graph()->NewNode(common()->End(1), ret); graph()->SetEnd(end); @@ -2387,15 +1059,17 @@ TARGET_TEST_F(SchedulerTest, CallException) { Node* p0 = graph()->NewNode(common()->Parameter(0), start); Node* c1 = graph()->NewNode(&kMockCall, start); Node* ok1 = graph()->NewNode(common()->IfSuccess(), c1); - Node* ex1 = graph()->NewNode(common()->IfException(), c1); + Node* ex1 = graph()->NewNode( + common()->IfException(IfExceptionHint::kLocallyUncaught), c1, c1); Node* c2 = graph()->NewNode(&kMockCall, ok1); Node* ok2 = graph()->NewNode(common()->IfSuccess(), c2); - Node* ex2 = graph()->NewNode(common()->IfException(), c2); + Node* ex2 = graph()->NewNode( + common()->IfException(IfExceptionHint::kLocallyUncaught), c2, c2); Node* hdl = graph()->NewNode(common()->Merge(2), ex1, ex2); Node* m = graph()->NewNode(common()->Merge(2), ok2, hdl); Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), c2, p0, m); Node* ret = graph()->NewNode(common()->Return(), phi, start, m); - Node* end = graph()->NewNode(common()->End(), ret); + Node* end = graph()->NewNode(common()->End(1), ret); graph()->SetEnd(end); @@ -2414,7 +1088,7 @@ TARGET_TEST_F(SchedulerTest, TailCall) { Node* p0 = graph()->NewNode(common()->Parameter(0), start); Node* call = graph()->NewNode(&kMockTailCall, p0, start, start); - Node* end = graph()->NewNode(common()->End(), call); + Node* end = graph()->NewNode(common()->End(1), call); graph()->SetEnd(end); @@ -2437,7 +1111,7 @@ TARGET_TEST_F(SchedulerTest, Switch) { Node* m = graph()->NewNode(common()->Merge(3), c0, c1, d); Node* phi = graph()->NewNode(common()->Phi(kMachInt32, 3), v0, v1, vd, m); Node* ret = graph()->NewNode(common()->Return(), phi, start, m); - Node* end = graph()->NewNode(common()->End(), ret); + Node* end = graph()->NewNode(common()->End(1), ret); graph()->SetEnd(end); @@ -2460,7 +1134,7 @@ TARGET_TEST_F(SchedulerTest, FloatingSwitch) { Node* m = graph()->NewNode(common()->Merge(3), c0, c1, d); Node* phi = graph()->NewNode(common()->Phi(kMachInt32, 3), v0, v1, vd, m); Node* ret = graph()->NewNode(common()->Return(), phi, start, start); - Node* end = graph()->NewNode(common()->End(), ret); + Node* end = graph()->NewNode(common()->End(1), ret); graph()->SetEnd(end); @@ -2480,7 +1154,7 @@ TARGET_TEST_F(SchedulerTest, Terminate) { Node* terminate = graph()->NewNode(common()->Terminate(), effect, loop); effect->ReplaceInput(1, terminate); - Node* end = graph()->NewNode(common()->End(), terminate); + Node* end = graph()->NewNode(common()->End(1), terminate); graph()->SetEnd(end); diff --git a/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc b/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc index a5dad5a415..07728913b1 100644 --- a/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc +++ b/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc @@ -54,7 +54,6 @@ const PureOperator kPureOperators[] = { PURE(StringEqual, Operator::kCommutative, 2), PURE(StringLessThan, Operator::kNoProperties, 2), PURE(StringLessThanOrEqual, Operator::kNoProperties, 2), - PURE(StringAdd, Operator::kNoProperties, 2), PURE(ChangeTaggedToInt32, Operator::kNoProperties, 1), PURE(ChangeTaggedToUint32, Operator::kNoProperties, 1), PURE(ChangeTaggedToFloat64, Operator::kNoProperties, 1), diff --git a/deps/v8/test/unittests/compiler/tail-call-optimization-unittest.cc b/deps/v8/test/unittests/compiler/tail-call-optimization-unittest.cc index 5ac1f8e796..449299bb1d 100644 --- a/deps/v8/test/unittests/compiler/tail-call-optimization-unittest.cc +++ b/deps/v8/test/unittests/compiler/tail-call-optimization-unittest.cc @@ -33,7 +33,7 @@ TEST_F(TailCallOptimizationTest, CallCodeObject0) { CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0), new (zone()) MachineSignature(1, 1, kMachineSignature), new (zone()) LocationSignature(1, 1, kLocationSignature), 0, - Operator::kNoProperties, 0, CallDescriptor::kNoFlags); + Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags); Node* p0 = Parameter(0); Node* p1 = Parameter(1); Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, @@ -53,15 +53,16 @@ TEST_F(TailCallOptimizationTest, CallCodeObject1) { CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0), new (zone()) MachineSignature(1, 1, kMachineSignature), new (zone()) LocationSignature(1, 1, kLocationSignature), 0, - Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls); + Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls); Node* p0 = Parameter(0); Node* p1 = Parameter(1); Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, graph()->start(), graph()->start()); Node* if_success = graph()->NewNode(common()->IfSuccess(), call); - Node* if_exception = graph()->NewNode(common()->IfException(), call); + Node* if_exception = graph()->NewNode( + common()->IfException(IfExceptionHint::kLocallyUncaught), call, call); Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); - Node* end = graph()->NewNode(common()->End(), if_exception); + Node* end = graph()->NewNode(common()->End(1), if_exception); graph()->SetEnd(end); Reduction r = Reduce(ret); ASSERT_FALSE(r.Changed()); @@ -76,7 +77,7 @@ TEST_F(TailCallOptimizationTest, CallCodeObject2) { CallDescriptor::kCallCodeObject, kMachAnyTagged, LinkageLocation(0), new (zone()) MachineSignature(1, 1, kMachineSignature), new (zone()) LocationSignature(1, 1, kLocationSignature), 0, - Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls); + Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls); Node* p0 = Parameter(0); Node* p1 = Parameter(1); Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, @@ -98,7 +99,7 @@ TEST_F(TailCallOptimizationTest, CallJSFunction0) { CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0), new (zone()) MachineSignature(1, 1, kMachineSignature), new (zone()) LocationSignature(1, 1, kLocationSignature), 0, - Operator::kNoProperties, 0, CallDescriptor::kNoFlags); + Operator::kNoProperties, 0, 0, CallDescriptor::kNoFlags); Node* p0 = Parameter(0); Node* p1 = Parameter(1); Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, @@ -118,15 +119,16 @@ TEST_F(TailCallOptimizationTest, CallJSFunction1) { CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0), new (zone()) MachineSignature(1, 1, kMachineSignature), new (zone()) LocationSignature(1, 1, kLocationSignature), 0, - Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls); + Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls); Node* p0 = Parameter(0); Node* p1 = Parameter(1); Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, graph()->start(), graph()->start()); Node* if_success = graph()->NewNode(common()->IfSuccess(), call); - Node* if_exception = graph()->NewNode(common()->IfException(), call); + Node* if_exception = graph()->NewNode( + common()->IfException(IfExceptionHint::kLocallyUncaught), call, call); Node* ret = graph()->NewNode(common()->Return(), call, call, if_success); - Node* end = graph()->NewNode(common()->End(), if_exception); + Node* end = graph()->NewNode(common()->End(1), if_exception); graph()->SetEnd(end); Reduction r = Reduce(ret); ASSERT_FALSE(r.Changed()); @@ -141,7 +143,7 @@ TEST_F(TailCallOptimizationTest, CallJSFunction2) { CallDescriptor::kCallJSFunction, kMachAnyTagged, LinkageLocation(0), new (zone()) MachineSignature(1, 1, kMachineSignature), new (zone()) LocationSignature(1, 1, kLocationSignature), 0, - Operator::kNoProperties, 0, CallDescriptor::kSupportsTailCalls); + Operator::kNoProperties, 0, 0, CallDescriptor::kSupportsTailCalls); Node* p0 = Parameter(0); Node* p1 = Parameter(1); Node* call = graph()->NewNode(common()->Call(kCallDescriptor), p0, p1, diff --git a/deps/v8/test/unittests/counters-unittest.cc b/deps/v8/test/unittests/counters-unittest.cc index dd60a0d9c1..822a5c552e 100644 --- a/deps/v8/test/unittests/counters-unittest.cc +++ b/deps/v8/test/unittests/counters-unittest.cc @@ -49,7 +49,7 @@ TEST_F(AggregatedMemoryHistogramTest, OneSample1) { FLAG_histogram_interval = 10; AddSample(10, 1000); AddSample(20, 1000); - EXPECT_EQ(1, samples()->size()); + EXPECT_EQ(1U, samples()->size()); EXPECT_EQ(1000, (*samples())[0]); } @@ -58,7 +58,7 @@ TEST_F(AggregatedMemoryHistogramTest, OneSample2) { FLAG_histogram_interval = 10; AddSample(10, 500); AddSample(20, 1000); - EXPECT_EQ(1, samples()->size()); + EXPECT_EQ(1U, samples()->size()); EXPECT_EQ(750, (*samples())[0]); } @@ -69,7 +69,7 @@ TEST_F(AggregatedMemoryHistogramTest, OneSample3) { AddSample(15, 500); AddSample(15, 1000); AddSample(20, 1000); - EXPECT_EQ(1, samples()->size()); + EXPECT_EQ(1U, samples()->size()); EXPECT_EQ(750, (*samples())[0]); } @@ -79,7 +79,7 @@ TEST_F(AggregatedMemoryHistogramTest, OneSample4) { AddSample(10, 500); AddSample(15, 750); AddSample(20, 1000); - EXPECT_EQ(1, samples()->size()); + EXPECT_EQ(1U, samples()->size()); EXPECT_EQ(750, (*samples())[0]); } @@ -88,7 +88,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples1) { FLAG_histogram_interval = 10; AddSample(10, 1000); AddSample(30, 1000); - EXPECT_EQ(2, samples()->size()); + EXPECT_EQ(2U, samples()->size()); EXPECT_EQ(1000, (*samples())[0]); EXPECT_EQ(1000, (*samples())[1]); } @@ -99,7 +99,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples2) { AddSample(10, 1000); AddSample(20, 1000); AddSample(30, 1000); - EXPECT_EQ(2, samples()->size()); + EXPECT_EQ(2U, samples()->size()); EXPECT_EQ(1000, (*samples())[0]); EXPECT_EQ(1000, (*samples())[1]); } @@ -111,7 +111,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples3) { AddSample(20, 1000); AddSample(20, 500); AddSample(30, 500); - EXPECT_EQ(2, samples()->size()); + EXPECT_EQ(2U, samples()->size()); EXPECT_EQ(1000, (*samples())[0]); EXPECT_EQ(500, (*samples())[1]); } @@ -121,7 +121,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples4) { FLAG_histogram_interval = 10; AddSample(10, 1000); AddSample(30, 0); - EXPECT_EQ(2, samples()->size()); + EXPECT_EQ(2U, samples()->size()); EXPECT_EQ(750, (*samples())[0]); EXPECT_EQ(250, (*samples())[1]); } @@ -131,7 +131,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples5) { FLAG_histogram_interval = 10; AddSample(10, 0); AddSample(30, 1000); - EXPECT_EQ(2, samples()->size()); + EXPECT_EQ(2U, samples()->size()); EXPECT_EQ(250, (*samples())[0]); EXPECT_EQ(750, (*samples())[1]); } @@ -142,7 +142,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples6) { AddSample(10, 0); AddSample(15, 1000); AddSample(30, 1000); - EXPECT_EQ(2, samples()->size()); + EXPECT_EQ(2U, samples()->size()); EXPECT_EQ((500 + 1000) / 2, (*samples())[0]); EXPECT_EQ(1000, (*samples())[1]); } @@ -154,7 +154,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples7) { AddSample(15, 1000); AddSample(25, 0); AddSample(30, 1000); - EXPECT_EQ(2, samples()->size()); + EXPECT_EQ(2U, samples()->size()); EXPECT_EQ((500 + 750) / 2, (*samples())[0]); EXPECT_EQ((250 + 500) / 2, (*samples())[1]); } @@ -166,7 +166,7 @@ TEST_F(AggregatedMemoryHistogramTest, TwoSamples8) { AddSample(15, 0); AddSample(25, 1000); AddSample(30, 0); - EXPECT_EQ(2, samples()->size()); + EXPECT_EQ(2U, samples()->size()); EXPECT_EQ((500 + 250) / 2, (*samples())[0]); EXPECT_EQ((750 + 500) / 2, (*samples())[1]); } @@ -177,7 +177,7 @@ TEST_F(AggregatedMemoryHistogramTest, ManySamples1) { const int kMaxSamples = 1000; AddSample(0, 0); AddSample(10 * kMaxSamples, 10 * kMaxSamples); - EXPECT_EQ(kMaxSamples, samples()->size()); + EXPECT_EQ(static_cast<unsigned>(kMaxSamples), samples()->size()); for (int i = 0; i < kMaxSamples; i++) { EXPECT_EQ(i * 10 + 5, (*samples())[i]); } @@ -189,7 +189,7 @@ TEST_F(AggregatedMemoryHistogramTest, ManySamples2) { const int kMaxSamples = 1000; AddSample(0, 0); AddSample(10 * (2 * kMaxSamples), 10 * (2 * kMaxSamples)); - EXPECT_EQ(kMaxSamples, samples()->size()); + EXPECT_EQ(static_cast<unsigned>(kMaxSamples), samples()->size()); for (int i = 0; i < kMaxSamples; i++) { EXPECT_EQ(i * 10 + 5, (*samples())[i]); } diff --git a/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc b/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc index 54d3bd52bb..c75fde492e 100644 --- a/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc +++ b/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc @@ -25,7 +25,6 @@ class GCIdleTimeHandlerTest : public ::testing::Test { result.contexts_disposal_rate = GCIdleTimeHandler::kHighContextDisposalRate; result.size_of_objects = kSizeOfObjects; result.incremental_marking_stopped = false; - result.can_start_incremental_marking = true; result.sweeping_in_progress = false; result.sweeping_completed = false; result.mark_compact_speed_in_bytes_per_ms = kMarkCompactSpeed; @@ -38,56 +37,6 @@ class GCIdleTimeHandlerTest : public ::testing::Test { return result; } - void TransitionToReduceMemoryMode( - const GCIdleTimeHandler::HeapState& heap_state) { - handler()->NotifyScavenge(); - EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); - double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; - int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle; - bool incremental = !heap_state.incremental_marking_stopped || - heap_state.can_start_incremental_marking; - for (int i = 0; i < limit; i++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - if (incremental) { - EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); - } else { - EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type); - } - } - handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); - } - - void TransitionToDoneMode(const GCIdleTimeHandler::HeapState& heap_state, - double idle_time_ms, - GCIdleTimeActionType expected) { - EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); - int limit = GCIdleTimeHandler::kMaxIdleMarkCompacts; - for (int i = 0; i < limit; i++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(expected, action.type); - EXPECT_TRUE(action.reduce_memory); - handler()->NotifyMarkCompact(); - handler()->NotifyIdleMarkCompact(); - } - handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(GCIdleTimeHandler::kDone, handler()->mode()); - } - - void TransitionToReduceLatencyMode( - const GCIdleTimeHandler::HeapState& heap_state) { - EXPECT_EQ(GCIdleTimeHandler::kDone, handler()->mode()); - int limit = GCIdleTimeHandler::kMarkCompactsBeforeMutatorIsActive; - double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; - for (int i = 0; i < limit; i++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DONE, action.type); - handler()->NotifyMarkCompact(); - } - handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); - } - static const size_t kSizeOfObjects = 100 * MB; static const size_t kMarkCompactSpeed = 200 * KB; static const size_t kMarkingSpeed = 200 * KB; @@ -219,6 +168,18 @@ TEST_F(GCIdleTimeHandlerTest, DoScavengeHighScavengeSpeed) { } +TEST_F(GCIdleTimeHandlerTest, DoNotScavengeSmallNewSpaceSize) { + GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); + heap_state.used_new_space_size = (MB / 2) - 1; + heap_state.scavenge_speed_in_bytes_per_ms = kNewSpaceCapacity; + int idle_time_ms = 16; + EXPECT_FALSE(GCIdleTimeHandler::ShouldDoScavenge( + idle_time_ms, heap_state.new_space_capacity, + heap_state.used_new_space_size, heap_state.scavenge_speed_in_bytes_per_ms, + heap_state.new_space_allocation_throughput_in_bytes_per_ms)); +} + + TEST_F(GCIdleTimeHandlerTest, ShouldDoMarkCompact) { size_t idle_time_ms = GCIdleTimeHandler::kMaxScheduledIdleTime; EXPECT_TRUE(GCIdleTimeHandler::ShouldDoMarkCompact(idle_time_ms, 0, 0)); @@ -251,11 +212,8 @@ TEST_F(GCIdleTimeHandlerTest, ContextDisposeLowRate) { heap_state.contexts_disposed = 1; heap_state.incremental_marking_stopped = true; double idle_time_ms = 0; - for (int mode = 0; mode < 1; mode++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_NOTHING, action.type); - TransitionToReduceMemoryMode(heap_state); - } + GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); + EXPECT_EQ(DO_NOTHING, action.type); } @@ -266,11 +224,8 @@ TEST_F(GCIdleTimeHandlerTest, ContextDisposeHighRate) { GCIdleTimeHandler::kHighContextDisposalRate - 1; heap_state.incremental_marking_stopped = true; double idle_time_ms = 0; - for (int mode = 0; mode < 1; mode++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_FULL_GC, action.type); - TransitionToReduceMemoryMode(heap_state); - } + GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); + EXPECT_EQ(DO_FULL_GC, action.type); } @@ -280,42 +235,34 @@ TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeZeroIdleTime) { heap_state.contexts_disposal_rate = 1.0; heap_state.incremental_marking_stopped = true; double idle_time_ms = 0; - for (int mode = 0; mode < 1; mode++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_FULL_GC, action.type); - TransitionToReduceMemoryMode(heap_state); - } + GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); + EXPECT_EQ(DO_FULL_GC, action.type); } TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime1) { GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); heap_state.contexts_disposed = 1; - heap_state.contexts_disposal_rate = 1.0; - heap_state.incremental_marking_stopped = true; + heap_state.contexts_disposal_rate = + GCIdleTimeHandler::kHighContextDisposalRate; size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; double idle_time_ms = static_cast<double>(heap_state.size_of_objects / speed - 1); - for (int mode = 0; mode < 1; mode++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); - TransitionToReduceMemoryMode(heap_state); - } + GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); + EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); } TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime2) { GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); heap_state.contexts_disposed = 1; - heap_state.contexts_disposal_rate = 1.0; + heap_state.contexts_disposal_rate = + GCIdleTimeHandler::kHighContextDisposalRate; size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; double idle_time_ms = static_cast<double>(heap_state.size_of_objects / speed - 1); - for (int mode = 0; mode < 1; mode++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); - TransitionToReduceMemoryMode(heap_state); - } + GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); + EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); } @@ -323,197 +270,106 @@ TEST_F(GCIdleTimeHandlerTest, IncrementalMarking1) { GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); size_t speed = heap_state.incremental_marking_speed_in_bytes_per_ms; double idle_time_ms = 10; - for (int mode = 0; mode < 1; mode++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); - EXPECT_GT(speed * static_cast<size_t>(idle_time_ms), - static_cast<size_t>(action.parameter)); - EXPECT_LT(0, action.parameter); - TransitionToReduceMemoryMode(heap_state); - } + GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); + EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); + EXPECT_GT(speed * static_cast<size_t>(idle_time_ms), + static_cast<size_t>(action.parameter)); + EXPECT_LT(0, action.parameter); } TEST_F(GCIdleTimeHandlerTest, IncrementalMarking2) { GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); - heap_state.incremental_marking_stopped = true; size_t speed = heap_state.incremental_marking_speed_in_bytes_per_ms; double idle_time_ms = 10; - for (int mode = 0; mode < 1; mode++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); - EXPECT_GT(speed * static_cast<size_t>(idle_time_ms), - static_cast<size_t>(action.parameter)); - EXPECT_LT(0, action.parameter); - TransitionToReduceMemoryMode(heap_state); - } + GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); + EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); + EXPECT_GT(speed * static_cast<size_t>(idle_time_ms), + static_cast<size_t>(action.parameter)); + EXPECT_LT(0, action.parameter); } TEST_F(GCIdleTimeHandlerTest, NotEnoughTime) { GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; double idle_time_ms = static_cast<double>(heap_state.size_of_objects / speed - 1); GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_NOTHING, action.type); - TransitionToReduceMemoryMode(heap_state); - action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); + EXPECT_EQ(DONE, action.type); } TEST_F(GCIdleTimeHandlerTest, FinalizeSweeping) { GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; - for (int mode = 0; mode < 1; mode++) { - heap_state.sweeping_in_progress = true; - heap_state.sweeping_completed = true; - double idle_time_ms = 10.0; - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_FINALIZE_SWEEPING, action.type); - heap_state.sweeping_in_progress = false; - heap_state.sweeping_completed = false; - TransitionToReduceMemoryMode(heap_state); - } + heap_state.sweeping_in_progress = true; + heap_state.sweeping_completed = true; + double idle_time_ms = 10.0; + GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); + EXPECT_EQ(DO_FINALIZE_SWEEPING, action.type); } TEST_F(GCIdleTimeHandlerTest, CannotFinalizeSweeping) { GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; - for (int mode = 0; mode < 1; mode++) { - heap_state.sweeping_in_progress = true; - heap_state.sweeping_completed = false; - double idle_time_ms = 10.0; - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_NOTHING, action.type); - heap_state.sweeping_in_progress = false; - heap_state.sweeping_completed = false; - TransitionToReduceMemoryMode(heap_state); - } + heap_state.sweeping_in_progress = true; + heap_state.sweeping_completed = false; + double idle_time_ms = 10.0; + GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); + EXPECT_EQ(DO_NOTHING, action.type); } TEST_F(GCIdleTimeHandlerTest, Scavenge) { GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); int idle_time_ms = 10; - for (int mode = 0; mode < 1; mode++) { - heap_state.used_new_space_size = - heap_state.new_space_capacity - - (kNewSpaceAllocationThroughput * idle_time_ms); - GCIdleTimeAction action = - handler()->Compute(static_cast<double>(idle_time_ms), heap_state); - EXPECT_EQ(DO_SCAVENGE, action.type); - heap_state.used_new_space_size = 0; - TransitionToReduceMemoryMode(heap_state); - } + heap_state.used_new_space_size = + heap_state.new_space_capacity - + (kNewSpaceAllocationThroughput * idle_time_ms); + GCIdleTimeAction action = + handler()->Compute(static_cast<double>(idle_time_ms), heap_state); + EXPECT_EQ(DO_SCAVENGE, action.type); + heap_state.used_new_space_size = 0; } TEST_F(GCIdleTimeHandlerTest, ScavengeAndDone) { GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); int idle_time_ms = 10; - heap_state.can_start_incremental_marking = false; - heap_state.incremental_marking_stopped = true; - for (int mode = 0; mode < 1; mode++) { - heap_state.used_new_space_size = - heap_state.new_space_capacity - - (kNewSpaceAllocationThroughput * idle_time_ms); - GCIdleTimeAction action = - handler()->Compute(static_cast<double>(idle_time_ms), heap_state); - EXPECT_EQ(DO_SCAVENGE, action.type); - heap_state.used_new_space_size = 0; - action = handler()->Compute(static_cast<double>(idle_time_ms), heap_state); - EXPECT_EQ(DO_NOTHING, action.type); - TransitionToReduceMemoryMode(heap_state); - } -} - - -TEST_F(GCIdleTimeHandlerTest, StopEventually1) { - GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; - double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; - bool stopped = false; - for (int i = 0; i < kMaxNotifications && !stopped; i++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - if (action.type == DO_INCREMENTAL_MARKING || action.type == DO_FULL_GC) { - handler()->NotifyMarkCompact(); - handler()->NotifyIdleMarkCompact(); - } - if (action.type == DONE) stopped = true; - } - EXPECT_TRUE(stopped); -} - - -TEST_F(GCIdleTimeHandlerTest, StopEventually2) { - GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); - heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; - size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; - double idle_time_ms = - static_cast<double>(heap_state.size_of_objects / speed + 1); - TransitionToReduceMemoryMode(heap_state); - TransitionToDoneMode(heap_state, idle_time_ms, DO_FULL_GC); - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); + heap_state.used_new_space_size = + heap_state.new_space_capacity - + (kNewSpaceAllocationThroughput * idle_time_ms); + GCIdleTimeAction action = + handler()->Compute(static_cast<double>(idle_time_ms), heap_state); + EXPECT_EQ(DO_SCAVENGE, action.type); + heap_state.used_new_space_size = 0; + action = handler()->Compute(static_cast<double>(idle_time_ms), heap_state); EXPECT_EQ(DONE, action.type); } -TEST_F(GCIdleTimeHandlerTest, StopEventually3) { +TEST_F(GCIdleTimeHandlerTest, DoNotStartIncrementalMarking) { GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; - double idle_time_ms = 10; - TransitionToReduceMemoryMode(heap_state); - TransitionToDoneMode(heap_state, idle_time_ms, DO_INCREMENTAL_MARKING); - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DONE, action.type); -} - - -TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop1) { - GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); - heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; - size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms; - double idle_time_ms = - static_cast<double>(heap_state.size_of_objects / speed + 1); - TransitionToReduceMemoryMode(heap_state); - TransitionToDoneMode(heap_state, idle_time_ms, DO_FULL_GC); + double idle_time_ms = 10.0; GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); EXPECT_EQ(DONE, action.type); - TransitionToReduceLatencyMode(heap_state); - heap_state.can_start_incremental_marking = true; - action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); - EXPECT_FALSE(action.reduce_memory); - EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); } -TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop2) { +TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop) { GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; - double idle_time_ms = 10; - TransitionToReduceMemoryMode(heap_state); - TransitionToDoneMode(heap_state, idle_time_ms, DO_INCREMENTAL_MARKING); + double idle_time_ms = 10.0; GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); EXPECT_EQ(DONE, action.type); - TransitionToReduceLatencyMode(heap_state); - heap_state.can_start_incremental_marking = true; + heap_state.incremental_marking_stopped = false; action = handler()->Compute(idle_time_ms, heap_state); EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); - EXPECT_FALSE(action.reduce_memory); - EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); } @@ -529,7 +385,6 @@ TEST_F(GCIdleTimeHandlerTest, ZeroIdleTimeNothingToDo) { TEST_F(GCIdleTimeHandlerTest, SmallIdleTimeNothingToDo) { GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; for (int i = 0; i < kMaxNotifications; i++) { GCIdleTimeAction action = handler()->Compute(10, heap_state); EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type); @@ -537,105 +392,16 @@ TEST_F(GCIdleTimeHandlerTest, SmallIdleTimeNothingToDo) { } -TEST_F(GCIdleTimeHandlerTest, StayInReduceLatencyModeBecauseOfScavenges) { - GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); - heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; - double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; - int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle; - for (int i = 0; i < kMaxNotifications; i++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type); - if ((i + 1) % limit == 0) handler()->NotifyScavenge(); - EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); - } -} - - -TEST_F(GCIdleTimeHandlerTest, StayInReduceLatencyModeBecauseOfMarkCompacts) { - GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); - heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; - double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; - int limit = GCIdleTimeHandler::kLongIdleNotificationsBeforeMutatorIsIdle; - for (int i = 0; i < kMaxNotifications; i++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_TRUE(DO_NOTHING == action.type || DONE == action.type); - if ((i + 1) % limit == 0) handler()->NotifyMarkCompact(); - EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); - } -} - - -TEST_F(GCIdleTimeHandlerTest, ReduceMemoryToReduceLatency) { - GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); - heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; - double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; - int limit = GCIdleTimeHandler::kMaxIdleMarkCompacts; - for (int idle_gc = 0; idle_gc < limit; idle_gc++) { - TransitionToReduceMemoryMode(heap_state); - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); - EXPECT_TRUE(action.reduce_memory); - EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); - for (int i = 0; i < idle_gc; i++) { - action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); - EXPECT_TRUE(action.reduce_memory); - // ReduceMemory mode should tolerate one mutator GC per idle GC. - handler()->NotifyScavenge(); - // Notify idle GC. - handler()->NotifyMarkCompact(); - handler()->NotifyIdleMarkCompact(); - } - // Transition to ReduceLatency mode after doing |idle_gc| idle GCs. - handler()->NotifyScavenge(); - action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_NOTHING, action.type); - EXPECT_FALSE(action.reduce_memory); - EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); - } -} - - -TEST_F(GCIdleTimeHandlerTest, ReduceMemoryToDone) { - GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); - heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; - double idle_time_ms = GCIdleTimeHandler::kMinLongIdleTime; - int limit = GCIdleTimeHandler::kMaxIdleMarkCompacts; - TransitionToReduceMemoryMode(heap_state); - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); - EXPECT_TRUE(action.reduce_memory); - for (int i = 0; i < limit; i++) { - action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); - EXPECT_TRUE(action.reduce_memory); - EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); - // ReduceMemory mode should tolerate one mutator GC per idle GC. - handler()->NotifyScavenge(); - // Notify idle GC. - handler()->NotifyMarkCompact(); - handler()->NotifyIdleMarkCompact(); - } - action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DONE, action.type); -} - - TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnSweeping) { // Regression test for crbug.com/489323. GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); // Simulate sweeping being in-progress but not complete. heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; heap_state.sweeping_in_progress = true; heap_state.sweeping_completed = false; double idle_time_ms = 10.0; - for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerMode; i++) { + for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimes; i++) { GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); EXPECT_EQ(DO_NOTHING, action.type); } @@ -651,34 +417,11 @@ TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnIncrementalMarking) { // Simulate incremental marking stopped and not eligible to start. heap_state.incremental_marking_stopped = true; - heap_state.can_start_incremental_marking = false; double idle_time_ms = 10.0; - for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimesPerMode; i++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_NOTHING, action.type); - } - // We should return DONE after not making progress for some time. + // We should return DONE if we cannot start incremental marking. GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); EXPECT_EQ(DONE, action.type); } - -TEST_F(GCIdleTimeHandlerTest, BackgroundReduceLatencyToReduceMemory) { - GCIdleTimeHandler::HeapState heap_state = DefaultHeapState(); - heap_state.incremental_marking_stopped = false; - heap_state.can_start_incremental_marking = true; - double idle_time_ms = GCIdleTimeHandler::kMinBackgroundIdleTime; - handler()->NotifyScavenge(); - EXPECT_EQ(GCIdleTimeHandler::kReduceLatency, handler()->mode()); - int limit = - GCIdleTimeHandler::kBackgroundIdleNotificationsBeforeMutatorIsIdle; - for (int i = 0; i < limit; i++) { - GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type); - } - handler()->Compute(idle_time_ms, heap_state); - EXPECT_EQ(GCIdleTimeHandler::kReduceMemory, handler()->mode()); -} - } // namespace internal } // namespace v8 diff --git a/deps/v8/test/unittests/heap/heap-unittest.cc b/deps/v8/test/unittests/heap/heap-unittest.cc new file mode 100644 index 0000000000..9492faf9f3 --- /dev/null +++ b/deps/v8/test/unittests/heap/heap-unittest.cc @@ -0,0 +1,48 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <cmath> +#include <limits> + +#include "src/objects.h" +#include "src/objects-inl.h" + +#include "src/handles.h" +#include "src/handles-inl.h" + +#include "src/heap/heap.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace v8 { +namespace internal { + +double Round(double x) { + // Round to three digits. + return floor(x * 1000 + 0.5) / 1000; +} + + +void CheckEqualRounded(double expected, double actual) { + expected = Round(expected); + actual = Round(actual); + EXPECT_DOUBLE_EQ(expected, actual); +} + + +TEST(Heap, HeapGrowingFactor) { + CheckEqualRounded(Heap::kMaxHeapGrowingFactor, + Heap::HeapGrowingFactor(34, 1)); + CheckEqualRounded(3.553, Heap::HeapGrowingFactor(45, 1)); + CheckEqualRounded(2.830, Heap::HeapGrowingFactor(50, 1)); + CheckEqualRounded(1.478, Heap::HeapGrowingFactor(100, 1)); + CheckEqualRounded(1.193, Heap::HeapGrowingFactor(200, 1)); + CheckEqualRounded(1.121, Heap::HeapGrowingFactor(300, 1)); + CheckEqualRounded(Heap::HeapGrowingFactor(300, 1), + Heap::HeapGrowingFactor(600, 2)); + CheckEqualRounded(Heap::kMinHeapGrowingFactor, + Heap::HeapGrowingFactor(400, 1)); +} + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/unittests/heap/memory-reducer-unittest.cc b/deps/v8/test/unittests/heap/memory-reducer-unittest.cc new file mode 100644 index 0000000000..3301d13b7e --- /dev/null +++ b/deps/v8/test/unittests/heap/memory-reducer-unittest.cc @@ -0,0 +1,331 @@ +// 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/flags.h" +#include "src/heap/memory-reducer.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace v8 { +namespace internal { + +MemoryReducer::State DoneState() { + return MemoryReducer::State(MemoryReducer::kDone, 0, 0.0, 1.0); +} + + +MemoryReducer::State WaitState(int started_gcs, double next_gc_start_ms) { + return MemoryReducer::State(MemoryReducer::kWait, started_gcs, + next_gc_start_ms, 1.0); +} + + +MemoryReducer::State RunState(int started_gcs, double next_gc_start_ms) { + return MemoryReducer::State(MemoryReducer::kRun, started_gcs, + next_gc_start_ms, 1.0); +} + + +MemoryReducer::Event MarkCompactEvent(double time_ms, + bool next_gc_likely_to_collect_more) { + MemoryReducer::Event event; + event.type = MemoryReducer::kMarkCompact; + event.time_ms = time_ms; + event.next_gc_likely_to_collect_more = next_gc_likely_to_collect_more; + return event; +} + + +MemoryReducer::Event MarkCompactEventGarbageLeft(double time_ms) { + return MarkCompactEvent(time_ms, true); +} + + +MemoryReducer::Event MarkCompactEventNoGarbageLeft(double time_ms) { + return MarkCompactEvent(time_ms, false); +} + + +MemoryReducer::Event TimerEvent(double time_ms, bool low_allocation_rate, + bool can_start_incremental_gc) { + MemoryReducer::Event event; + event.type = MemoryReducer::kTimer; + event.time_ms = time_ms; + event.low_allocation_rate = low_allocation_rate; + event.can_start_incremental_gc = can_start_incremental_gc; + return event; +} + + +MemoryReducer::Event TimerEventLowAllocationRate(double time_ms) { + return TimerEvent(time_ms, true, true); +} + + +MemoryReducer::Event TimerEventHighAllocationRate(double time_ms) { + return TimerEvent(time_ms, false, true); +} + + +MemoryReducer::Event TimerEventPendingGC(double time_ms) { + return TimerEvent(time_ms, true, false); +} + + +MemoryReducer::Event ContextDisposedEvent(double time_ms) { + MemoryReducer::Event event; + event.type = MemoryReducer::kContextDisposed; + event.time_ms = time_ms; + return event; +} + + +MemoryReducer::Event BackgroundIdleNotificationEvent( + double time_ms, bool can_start_incremental_gc = true) { + MemoryReducer::Event event; + event.type = MemoryReducer::kBackgroundIdleNotification; + event.time_ms = time_ms; + event.can_start_incremental_gc = can_start_incremental_gc; + return event; +} + + +TEST(MemoryReducer, FromDoneToDone) { + MemoryReducer::State state0(DoneState()), state1(DoneState()); + + state1 = MemoryReducer::Step(state0, TimerEventLowAllocationRate(0)); + EXPECT_EQ(MemoryReducer::kDone, state1.action); + + state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(0)); + EXPECT_EQ(MemoryReducer::kDone, state1.action); + + state1 = MemoryReducer::Step(state0, TimerEventPendingGC(0)); + EXPECT_EQ(MemoryReducer::kDone, state1.action); + + state1 = MemoryReducer::Step(state0, BackgroundIdleNotificationEvent(0)); + EXPECT_EQ(MemoryReducer::kDone, state1.action); +} + + +TEST(MemoryReducer, FromDoneToWait) { + if (!FLAG_incremental_marking) return; + + MemoryReducer::State state0(DoneState()), state1(DoneState()); + + state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(MemoryReducer::kLongDelayMs + 2, state1.next_gc_start_ms); + EXPECT_EQ(0, state1.started_gcs); + EXPECT_EQ(2, state1.last_gc_time_ms); + + state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(MemoryReducer::kLongDelayMs + 2, state1.next_gc_start_ms); + EXPECT_EQ(0, state1.started_gcs); + EXPECT_EQ(2, state1.last_gc_time_ms); + + state1 = MemoryReducer::Step(state0, ContextDisposedEvent(0)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); + EXPECT_EQ(0, state1.started_gcs); + EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); +} + + +TEST(MemoryReducer, FromWaitToWait) { + if (!FLAG_incremental_marking) return; + + MemoryReducer::State state0(WaitState(2, 1000.0)), state1(DoneState()); + + state1 = MemoryReducer::Step(state0, ContextDisposedEvent(2000)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + + state1 = MemoryReducer::Step( + state0, TimerEventLowAllocationRate(state0.next_gc_start_ms - 1)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + + state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(2000)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + + state1 = MemoryReducer::Step(state0, TimerEventPendingGC(2000)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + + state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + EXPECT_EQ(2000, state1.last_gc_time_ms); + + state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + EXPECT_EQ(2000, state1.last_gc_time_ms); + + state1 = MemoryReducer::Step(state0, BackgroundIdleNotificationEvent(2000)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs + 1, state1.started_gcs); + + state1 = + MemoryReducer::Step(state0, BackgroundIdleNotificationEvent(2000, false)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + + state0.last_gc_time_ms = 0; + state1 = MemoryReducer::Step( + state0, + TimerEventHighAllocationRate(MemoryReducer::kWatchdogDelayMs + 1)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(MemoryReducer::kWatchdogDelayMs + 1 + MemoryReducer::kLongDelayMs, + state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); + + state0.last_gc_time_ms = 1; + state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(2000)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); + + state0.started_gcs = MemoryReducer::kMaxNumberOfGCs; + state1 = MemoryReducer::Step(state0, BackgroundIdleNotificationEvent(2000)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); +} + + +TEST(MemoryReducer, FromWaitToRun) { + if (!FLAG_incremental_marking) return; + + MemoryReducer::State state0(WaitState(0, 1000.0)), state1(DoneState()); + + state1 = MemoryReducer::Step( + state0, TimerEventLowAllocationRate(state0.next_gc_start_ms + 1)); + EXPECT_EQ(MemoryReducer::kRun, state1.action); + EXPECT_EQ(0, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs + 1, state1.started_gcs); + + state1 = MemoryReducer::Step( + state0, + TimerEventHighAllocationRate(MemoryReducer::kWatchdogDelayMs + 2)); + EXPECT_EQ(MemoryReducer::kRun, state1.action); + EXPECT_EQ(0, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs + 1, state1.started_gcs); + EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); +} + + +TEST(MemoryReducer, FromWaitToDone) { + if (!FLAG_incremental_marking) return; + + MemoryReducer::State state0(WaitState(2, 0.0)), state1(DoneState()); + + state0.started_gcs = MemoryReducer::kMaxNumberOfGCs; + + state1 = MemoryReducer::Step(state0, TimerEventLowAllocationRate(2000)); + EXPECT_EQ(MemoryReducer::kDone, state1.action); + EXPECT_EQ(0, state1.next_gc_start_ms); + EXPECT_EQ(MemoryReducer::kMaxNumberOfGCs, state1.started_gcs); + EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); + + state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(2000)); + EXPECT_EQ(MemoryReducer::kDone, state1.action); + EXPECT_EQ(0, state1.next_gc_start_ms); + EXPECT_EQ(MemoryReducer::kMaxNumberOfGCs, state1.started_gcs); + EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); + + state1 = MemoryReducer::Step(state0, TimerEventPendingGC(2000)); + EXPECT_EQ(MemoryReducer::kDone, state1.action); + EXPECT_EQ(0, state1.next_gc_start_ms); + EXPECT_EQ(MemoryReducer::kMaxNumberOfGCs, state1.started_gcs); + EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); +} + + +TEST(MemoryReducer, FromRunToRun) { + if (!FLAG_incremental_marking) return; + + MemoryReducer::State state0(RunState(1, 0.0)), state1(DoneState()); + + state1 = MemoryReducer::Step(state0, TimerEventLowAllocationRate(2000)); + EXPECT_EQ(MemoryReducer::kRun, state1.action); + EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); + + state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(2000)); + EXPECT_EQ(MemoryReducer::kRun, state1.action); + EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); + + state1 = MemoryReducer::Step(state0, TimerEventPendingGC(2000)); + EXPECT_EQ(MemoryReducer::kRun, state1.action); + EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); + + state1 = MemoryReducer::Step(state0, ContextDisposedEvent(2000)); + EXPECT_EQ(MemoryReducer::kRun, state1.action); + EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); +} + + +TEST(MemoryReducer, FromRunToDone) { + if (!FLAG_incremental_marking) return; + + MemoryReducer::State state0(RunState(2, 0.0)), state1(DoneState()); + + state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000)); + EXPECT_EQ(MemoryReducer::kDone, state1.action); + EXPECT_EQ(0, state1.next_gc_start_ms); + EXPECT_EQ(MemoryReducer::kMaxNumberOfGCs, state1.started_gcs); + EXPECT_EQ(2000, state1.last_gc_time_ms); + + state0.started_gcs = MemoryReducer::kMaxNumberOfGCs; + + state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000)); + EXPECT_EQ(MemoryReducer::kDone, state1.action); + EXPECT_EQ(0, state1.next_gc_start_ms); + EXPECT_EQ(2000, state1.last_gc_time_ms); +} + + +TEST(MemoryReducer, FromRunToWait) { + if (!FLAG_incremental_marking) return; + + MemoryReducer::State state0(RunState(2, 0.0)), state1(DoneState()); + + state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(2000 + MemoryReducer::kShortDelayMs, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + EXPECT_EQ(2000, state1.last_gc_time_ms); + + state0.started_gcs = 1; + + state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000)); + EXPECT_EQ(MemoryReducer::kWait, state1.action); + EXPECT_EQ(2000 + MemoryReducer::kShortDelayMs, state1.next_gc_start_ms); + EXPECT_EQ(state0.started_gcs, state1.started_gcs); + EXPECT_EQ(2000, state1.last_gc_time_ms); +} + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/unittests/libplatform/default-platform-unittest.cc b/deps/v8/test/unittests/libplatform/default-platform-unittest.cc index d2c160e558..814b27bc51 100644 --- a/deps/v8/test/unittests/libplatform/default-platform-unittest.cc +++ b/deps/v8/test/unittests/libplatform/default-platform-unittest.cc @@ -19,6 +19,17 @@ struct MockTask : public Task { MOCK_METHOD0(Die, void()); }; + +class DefaultPlatformWithMockTime : public DefaultPlatform { + public: + DefaultPlatformWithMockTime() : time_(0) {} + double MonotonicallyIncreasingTime() override { return time_; } + void IncreaseTime(double seconds) { time_ += seconds; } + + private: + double time_; +}; + } // namespace @@ -39,5 +50,82 @@ TEST(DefaultPlatformTest, PumpMessageLoop) { EXPECT_FALSE(platform.PumpMessageLoop(isolate)); } + +TEST(DefaultPlatformTest, PumpMessageLoopDelayed) { + InSequence s; + + int dummy; + Isolate* isolate = reinterpret_cast<Isolate*>(&dummy); + + DefaultPlatformWithMockTime platform; + EXPECT_FALSE(platform.PumpMessageLoop(isolate)); + + StrictMock<MockTask>* task1 = new StrictMock<MockTask>; + StrictMock<MockTask>* task2 = new StrictMock<MockTask>; + platform.CallDelayedOnForegroundThread(isolate, task2, 100); + platform.CallDelayedOnForegroundThread(isolate, task1, 10); + + EXPECT_FALSE(platform.PumpMessageLoop(isolate)); + + platform.IncreaseTime(11); + EXPECT_CALL(*task1, Run()); + EXPECT_CALL(*task1, Die()); + EXPECT_TRUE(platform.PumpMessageLoop(isolate)); + + EXPECT_FALSE(platform.PumpMessageLoop(isolate)); + + platform.IncreaseTime(90); + EXPECT_CALL(*task2, Run()); + EXPECT_CALL(*task2, Die()); + EXPECT_TRUE(platform.PumpMessageLoop(isolate)); +} + + +TEST(DefaultPlatformTest, PumpMessageLoopNoStarvation) { + InSequence s; + + int dummy; + Isolate* isolate = reinterpret_cast<Isolate*>(&dummy); + + DefaultPlatformWithMockTime platform; + EXPECT_FALSE(platform.PumpMessageLoop(isolate)); + + StrictMock<MockTask>* task1 = new StrictMock<MockTask>; + StrictMock<MockTask>* task2 = new StrictMock<MockTask>; + StrictMock<MockTask>* task3 = new StrictMock<MockTask>; + platform.CallOnForegroundThread(isolate, task1); + platform.CallDelayedOnForegroundThread(isolate, task2, 10); + platform.IncreaseTime(11); + + EXPECT_CALL(*task1, Run()); + EXPECT_CALL(*task1, Die()); + EXPECT_TRUE(platform.PumpMessageLoop(isolate)); + + platform.CallOnForegroundThread(isolate, task3); + + EXPECT_CALL(*task2, Run()); + EXPECT_CALL(*task2, Die()); + EXPECT_TRUE(platform.PumpMessageLoop(isolate)); + EXPECT_CALL(*task3, Run()); + EXPECT_CALL(*task3, Die()); + EXPECT_TRUE(platform.PumpMessageLoop(isolate)); +} + + +TEST(DefaultPlatformTest, PendingDelayedTasksAreDestroyedOnShutdown) { + InSequence s; + + int dummy; + Isolate* isolate = reinterpret_cast<Isolate*>(&dummy); + + { + DefaultPlatformWithMockTime platform; + StrictMock<MockTask>* task = new StrictMock<MockTask>; + platform.CallDelayedOnForegroundThread(isolate, task, 10); + EXPECT_CALL(*task, Die()); + } +} + + } // namespace platform } // namespace v8 diff --git a/deps/v8/test/unittests/unittests.gyp b/deps/v8/test/unittests/unittests.gyp index 7a298a9074..00658b3fda 100644 --- a/deps/v8/test/unittests/unittests.gyp +++ b/deps/v8/test/unittests/unittests.gyp @@ -44,10 +44,11 @@ 'compiler/compiler-test-utils.h', 'compiler/control-equivalence-unittest.cc', 'compiler/control-flow-optimizer-unittest.cc', - 'compiler/control-reducer-unittest.cc', + 'compiler/dead-code-elimination-unittest.cc', 'compiler/diamond-unittest.cc', 'compiler/graph-reducer-unittest.cc', 'compiler/graph-reducer-unittest.h', + 'compiler/graph-trimmer-unittest.cc', 'compiler/graph-unittest.cc', 'compiler/graph-unittest.h', 'compiler/instruction-selector-unittest.cc', @@ -88,6 +89,8 @@ 'libplatform/task-queue-unittest.cc', 'libplatform/worker-thread-unittest.cc', 'heap/gc-idle-time-handler-unittest.cc', + 'heap/memory-reducer-unittest.cc', + 'heap/heap-unittest.cc', 'run-all-unittests.cc', 'test-utils.h', 'test-utils.cc', diff --git a/deps/v8/test/webkit/class-syntax-extends-expected.txt b/deps/v8/test/webkit/class-syntax-extends-expected.txt index b3b4c8ee60..1eede9c60b 100644 --- a/deps/v8/test/webkit/class-syntax-extends-expected.txt +++ b/deps/v8/test/webkit/class-syntax-extends-expected.txt @@ -58,12 +58,12 @@ PASS new (class extends undefined { constructor () { this } }) threw exception T PASS new (class extends undefined { constructor () { super(); } }) threw exception TypeError: Class extends value undefined is not a function or null. PASS x = {}; new (class extends undefined { constructor () { return x; } }) threw exception TypeError: Class extends value undefined is not a function or null. PASS y = 12; new (class extends undefined { constructor () { return y; } }) threw exception TypeError: Class extends value undefined is not a function or null. -FAIL class x {}; new (class extends null { constructor () { return new x; } }) instanceof x should be true. Threw exception TypeError: x is not a function +PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x is true PASS new (class extends null { constructor () { this; } }) threw exception ReferenceError: this is not defined. PASS new (class extends null { constructor () { super(); } }) threw exception TypeError: function () {} is not a constructor. PASS x = {}; new (class extends null { constructor () { return x } }) is x PASS y = 12; new (class extends null { constructor () { return y; } }) threw exception TypeError: Derived constructors may only return object or undefined. -FAIL class x {}; new (class extends null { constructor () { return new x; } }) instanceof x should be true. Threw exception TypeError: x is not a function +PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x is true PASS x = null; Object.getPrototypeOf((class extends x { }).prototype) is null PASS Object.prototype.isPrototypeOf(class { }) is true PASS Function.prototype.isPrototypeOf(class { }) is true diff --git a/deps/v8/test/webkit/cyclic-prototypes-expected.txt b/deps/v8/test/webkit/cyclic-prototypes-expected.txt index 7ac87b04ca..34bdb04a73 100644 --- a/deps/v8/test/webkit/cyclic-prototypes-expected.txt +++ b/deps/v8/test/webkit/cyclic-prototypes-expected.txt @@ -26,7 +26,7 @@ This test makes sure we don't hang when setting cyclic prototype values: http:// On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS o1.__proto__ = o3; threw exception Error: Cyclic __proto__ value. +PASS o1.__proto__ = o3; threw exception TypeError: Cyclic __proto__ value. PASS ({}).hasOwnProperty.call(o1, '__proto__') is false PASS ({}).hasOwnProperty.call(o1, '__proto__') is true PASS Object.getPrototypeOf(o1) is null diff --git a/deps/v8/test/webkit/fast/js/Object-getOwnPropertyNames-expected.txt b/deps/v8/test/webkit/fast/js/Object-getOwnPropertyNames-expected.txt index 1948700fca..7731a98671 100644 --- a/deps/v8/test/webkit/fast/js/Object-getOwnPropertyNames-expected.txt +++ b/deps/v8/test/webkit/fast/js/Object-getOwnPropertyNames-expected.txt @@ -44,12 +44,12 @@ PASS getSortedOwnPropertyNames(decodeURI) is ['length', 'name'] PASS getSortedOwnPropertyNames(decodeURIComponent) is ['length', 'name'] PASS getSortedOwnPropertyNames(encodeURI) is ['length', 'name'] PASS getSortedOwnPropertyNames(encodeURIComponent) is ['length', 'name'] -PASS getSortedOwnPropertyNames(Object) is ['arguments', 'caller', 'create', 'defineProperties', 'defineProperty', 'deliverChangeRecords', 'freeze', 'getNotifier', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', 'getOwnPropertySymbols', 'getPrototypeOf', 'is', 'isExtensible', 'isFrozen', 'isSealed', 'keys', 'length', 'name', 'observe', 'preventExtensions', 'prototype', 'seal', 'setPrototypeOf', 'unobserve'] +PASS getSortedOwnPropertyNames(Object) is ['arguments', 'assign', 'caller', 'create', 'defineProperties', 'defineProperty', 'deliverChangeRecords', 'freeze', 'getNotifier', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', 'getOwnPropertySymbols', 'getPrototypeOf', 'is', 'isExtensible', 'isFrozen', 'isSealed', 'keys', 'length', 'name', 'observe', 'preventExtensions', 'prototype', 'seal', 'setPrototypeOf', 'unobserve'] PASS getSortedOwnPropertyNames(Object.prototype) is ['__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', '__proto__', 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf'] PASS getSortedOwnPropertyNames(Function) is ['arguments', 'caller', 'length', 'name', 'prototype'] PASS getSortedOwnPropertyNames(Function.prototype) is ['apply', 'arguments', 'bind', 'call', 'caller', 'constructor', 'length', 'name', 'toString'] -PASS getSortedOwnPropertyNames(Array) is ['arguments', 'caller', 'isArray', 'length', 'name', 'observe', 'prototype', 'unobserve'] -PASS getSortedOwnPropertyNames(Array.prototype) is ['concat', 'constructor', 'entries', 'every', 'filter', 'forEach', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift'] +PASS getSortedOwnPropertyNames(Array) is ['arguments', 'caller', 'from', 'isArray', 'length', 'name', 'observe', 'of', 'prototype', 'unobserve'] +PASS getSortedOwnPropertyNames(Array.prototype) is ['concat', 'constructor', 'copyWithin', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift'] PASS getSortedOwnPropertyNames(String) is ['arguments', 'caller', 'fromCharCode', 'fromCodePoint', 'length', 'name', 'prototype', 'raw'] PASS getSortedOwnPropertyNames(String.prototype) is ['anchor', 'big', 'blink', 'bold', 'charAt', 'charCodeAt', 'codePointAt', 'concat', 'constructor', 'endsWith', 'fixed', 'fontcolor', 'fontsize', 'includes', 'indexOf', 'italics', 'lastIndexOf', 'length', 'link', 'localeCompare', 'match', 'normalize', 'repeat', 'replace', 'search', 'slice', 'small', 'split', 'startsWith', 'strike', 'sub', 'substr', 'substring', 'sup', 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toString', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', 'valueOf'] PASS getSortedOwnPropertyNames(Boolean) is ['arguments', 'caller', 'length', 'name', 'prototype'] diff --git a/deps/v8/test/webkit/fast/js/Object-getOwnPropertyNames.js b/deps/v8/test/webkit/fast/js/Object-getOwnPropertyNames.js index 20e509ba96..e34562f5ba 100644 --- a/deps/v8/test/webkit/fast/js/Object-getOwnPropertyNames.js +++ b/deps/v8/test/webkit/fast/js/Object-getOwnPropertyNames.js @@ -71,12 +71,12 @@ var expectedPropertyNamesSet = { "encodeURI": "['length', 'name']", "encodeURIComponent": "['length', 'name']", // Built-in ECMA objects - "Object": "['arguments', 'caller', 'create', 'defineProperties', 'defineProperty', 'deliverChangeRecords', 'freeze', 'getNotifier', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', 'getOwnPropertySymbols', 'getPrototypeOf', 'is', 'isExtensible', 'isFrozen', 'isSealed', 'keys', 'length', 'name', 'observe', 'preventExtensions', 'prototype', 'seal', 'setPrototypeOf', 'unobserve']", + "Object": "['arguments', 'assign', 'caller', 'create', 'defineProperties', 'defineProperty', 'deliverChangeRecords', 'freeze', 'getNotifier', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', 'getOwnPropertySymbols', 'getPrototypeOf', 'is', 'isExtensible', 'isFrozen', 'isSealed', 'keys', 'length', 'name', 'observe', 'preventExtensions', 'prototype', 'seal', 'setPrototypeOf', 'unobserve']", "Object.prototype": "['__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', '__proto__', 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf']", "Function": "['arguments', 'caller', 'length', 'name', 'prototype']", "Function.prototype": "['apply', 'arguments', 'bind', 'call', 'caller', 'constructor', 'length', 'name', 'toString']", - "Array": "['arguments', 'caller', 'isArray', 'length', 'name', 'observe', 'prototype', 'unobserve']", - "Array.prototype": "['concat', 'constructor', 'entries', 'every', 'filter', 'forEach', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift']", + "Array": "['arguments', 'caller', 'from', 'isArray', 'length', 'name', 'observe', 'of', 'prototype', 'unobserve']", + "Array.prototype": "['concat', 'constructor', 'copyWithin', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift']", "String": "['arguments', 'caller', 'fromCharCode', 'fromCodePoint', 'length', 'name', 'prototype', 'raw']", "String.prototype": "['anchor', 'big', 'blink', 'bold', 'charAt', 'charCodeAt', 'codePointAt', 'concat', 'constructor', 'endsWith', 'fixed', 'fontcolor', 'fontsize', 'includes', 'indexOf', 'italics', 'lastIndexOf', 'length', 'link', 'localeCompare', 'match', 'normalize', 'repeat', 'replace', 'search', 'slice', 'small', 'split', 'startsWith', 'strike', 'sub', 'substr', 'substring', 'sup', 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toString', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', 'valueOf']", "Boolean": "['arguments', 'caller', 'length', 'name', 'prototype']", diff --git a/deps/v8/test/webkit/fast/js/arguments-expected.txt b/deps/v8/test/webkit/fast/js/arguments-expected.txt index f5bbb72936..4f0150033d 100644 --- a/deps/v8/test/webkit/fast/js/arguments-expected.txt +++ b/deps/v8/test/webkit/fast/js/arguments-expected.txt @@ -157,7 +157,7 @@ PASS access_after_delete_extra_5(1, 2, 3, 4, 5) is 5 PASS argumentsParam(true) is true PASS argumentsFunctionConstructorParam(true) is true PASS argumentsVarUndefined() is '[object Arguments]' -FAIL argumentsConstUndefined() should be [object Arguments]. Threw exception TypeError: Identifier 'arguments' has already been declared +FAIL argumentsConstUndefined() should be [object Arguments]. Threw exception SyntaxError: Identifier 'arguments' has already been declared PASS argumentCalleeInException() is argumentCalleeInException PASS shadowedArgumentsApply([true]) is true PASS shadowedArgumentsLength([]) is 0 diff --git a/deps/v8/test/webkit/fast/js/primitive-property-access-edge-cases-expected.txt b/deps/v8/test/webkit/fast/js/primitive-property-access-edge-cases-expected.txt index cc273dfba0..df66f4eba4 100644 --- a/deps/v8/test/webkit/fast/js/primitive-property-access-edge-cases-expected.txt +++ b/deps/v8/test/webkit/fast/js/primitive-property-access-edge-cases-expected.txt @@ -56,9 +56,9 @@ PASS checkNumericGet(true, Boolean) is true FAIL checkNumericSet(1, Number) should be true. Was false. FAIL checkNumericSet('hello', String) should be true. Was false. FAIL checkNumericSet(true, Boolean) should be true. Was false. -FAIL checkNumericGetStrict(1, Number) should be true. Was false. -FAIL checkNumericGetStrict('hello', String) should be true. Was false. -FAIL checkNumericGetStrict(true, Boolean) should be true. Was false. +PASS checkNumericGetStrict(1, Number) is true +PASS checkNumericGetStrict('hello', String) is true +PASS checkNumericGetStrict(true, Boolean) is true FAIL checkNumericSetStrict(1, Number) should be true. Was false. FAIL checkNumericSetStrict('hello', String) should be true. Was false. FAIL checkNumericSetStrict(true, Boolean) should be true. Was false. diff --git a/deps/v8/test/webkit/webkit.status b/deps/v8/test/webkit/webkit.status index d8c6864105..57d86cb921 100644 --- a/deps/v8/test/webkit/webkit.status +++ b/deps/v8/test/webkit/webkit.status @@ -49,9 +49,11 @@ }], # 'mode == debug' ['simulator', { # Skip tests that timeout with turbofan. - 'dfg-int-overflow-in-loop': [PASS, NO_VARIANTS], 'array-iterate-backwards': [PASS, NO_VARIANTS], 'function-apply-aliased': [SKIP], + + # Skip tests that are too slow for simulators. + 'dfg-int-overflow-in-loop': [SKIP], }], # 'simulator' ['arch == arm64 and simulator_run == True', { 'dfg-int-overflow-in-loop': [SKIP], |