diff options
author | Ben Murdoch <benm@google.com> | 2012-04-12 10:51:47 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2012-04-16 16:41:38 +0100 |
commit | 3ef787dbeca8a5fb1086949cda830dccee07bfbd (patch) | |
tree | 0a22edd97aa148abffdd405c585b22213fccbc82 /test | |
parent | 85b71799222b55eb5dd74ea26efe0c64ab655c8c (diff) | |
download | v8-3ef787dbeca8a5fb1086949cda830dccee07bfbd.tar.gz |
Merge V8 at 3.9.24.13
Bug: 5688872
Change-Id: Id0aa8d23375030494d3189c31774059c0f5398fc
Diffstat (limited to 'test')
213 files changed, 22157 insertions, 3728 deletions
diff --git a/test/cctest/SConscript b/test/cctest/SConscript index 5c926718..bcd1e987 100644 --- a/test/cctest/SConscript +++ b/test/cctest/SConscript @@ -1,4 +1,4 @@ -# Copyright 2008 the V8 project authors. All rights reserved. +# 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: @@ -62,6 +62,7 @@ SOURCES = { 'test-conversions.cc', 'test-cpu-profiler.cc', 'test-dataflow.cc', + 'test-date.cc', 'test-debug.cc', 'test-decls.cc', 'test-deoptimization.cc', @@ -86,6 +87,7 @@ SOURCES = { 'test-parsing.cc', 'test-platform-tls.cc', 'test-profile-generator.cc', + 'test-random.cc', 'test-regexp.cc', 'test-reloc-info.cc', 'test-serialize.cc', @@ -111,7 +113,8 @@ SOURCES = { ], 'arch:x64': ['test-assembler-x64.cc', 'test-macro-assembler-x64.cc', - 'test-log-stack-tracer.cc'], + 'test-log-stack-tracer.cc', + 'test-disasm-x64.cc'], 'arch:mips': ['test-assembler-mips.cc', 'test-disasm-mips.cc'], 'os:linux': ['test-platform-linux.cc'], diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp index 5d0cab3e..a242fe3c 100644 --- a/test/cctest/cctest.gyp +++ b/test/cctest/cctest.gyp @@ -1,4 +1,4 @@ -# Copyright 2011 the V8 project authors. All rights reserved. +# 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: @@ -57,6 +57,7 @@ 'test-conversions.cc', 'test-cpu-profiler.cc', 'test-dataflow.cc', + 'test-date.cc', 'test-debug.cc', 'test-decls.cc', 'test-deoptimization.cc', @@ -68,6 +69,7 @@ 'test-fixed-dtoa.cc', 'test-flags.cc', 'test-func-name-inference.cc', + 'test-hashing.cc', 'test-hashmap.cc', 'test-heap.cc', 'test-heap-profiler.cc', @@ -80,6 +82,7 @@ 'test-parsing.cc', 'test-platform-tls.cc', 'test-profile-generator.cc', + 'test-random.cc', 'test-regexp.cc', 'test-reloc-info.cc', 'test-serialize.cc', @@ -91,7 +94,8 @@ 'test-threads.cc', 'test-unbound-queue.cc', 'test-utils.cc', - 'test-version.cc' + 'test-version.cc', + 'test-weakmaps.cc' ], 'conditions': [ ['v8_target_arch=="ia32"', { @@ -134,6 +138,12 @@ 'sources': [ 'test-platform-win32.cc', ], + 'msvs_settings': { + 'VCCLCompilerTool': { + # MSVS wants this for gay-{precision,shortest}.cc. + 'AdditionalOptions': ['/bigobj'], + }, + }, }], ['component=="shared_library"', { # cctest can't be built against a shared library, so we need to diff --git a/test/cctest/cctest.h b/test/cctest/cctest.h index c04d893c..0b935622 100644 --- a/test/cctest/cctest.h +++ b/test/cctest/cctest.h @@ -104,7 +104,7 @@ class ApiTestFuzzer: public v8::internal::Thread { FOURTH_PART, LAST_PART = FOURTH_PART }; - static void Setup(PartOfTest part); + static void SetUp(PartOfTest part); static void RunAllTests(); static void TearDown(); // This method switches threads if we are running the Threading test. diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status index 5122da5a..af28be19 100644 --- a/test/cctest/cctest.status +++ b/test/cctest/cctest.status @@ -33,11 +33,22 @@ test-api/Bug*: FAIL # BUG(382): Weird test. Can't guarantee that it never times out. test-api/ApplyInterruption: PASS || TIMEOUT +# BUG(484): This test which we thought was originally corrected in r5236 +# is re-appearing. Disabled until bug in test is fixed. This only fails +# when snapshot is on, so I am marking it PASS || FAIL +test-heap-profiler/HeapSnapshotsDiff: PASS || FAIL + # These tests always fail. They are here to test test.py. If # they don't fail then test.py has failed. test-serialize/TestThatAlwaysFails: FAIL test-serialize/DependentTestThatAlwaysFails: FAIL +# TODO(gc): Temporarily disabled in the GC branch. +test-log/EquivalenceOfLoggingAndTraversal: PASS || FAIL + +# BUG(1261): Flakey test. +test-profile-generator/RecordStackTraceAtStartProfiling: PASS || FAIL + # We do not yet shrink weak maps after they have been emptied by the GC test-weakmaps/Shrinking: FAIL @@ -73,10 +84,8 @@ test-debug/DebugBreakLoop: SKIP ############################################################################## -[ $arch == mips ] -test-deoptimization: SKIP -test-serialize: SKIP +[ $arch == mips && $crankshaft ] -# Tests that may time out. -test-api/ExternalArrays: PASS || TIMEOUT -test-api/Threading: PASS || TIMEOUT +# Tests that time out with crankshaft. +test-debug/ThreadedDebugging: SKIP +test-debug/DebugBreakLoop: SKIP diff --git a/test/cctest/test-accessors.cc b/test/cctest/test-accessors.cc index d95536d2..b1900f9e 100644 --- a/test/cctest/test-accessors.cc +++ b/test/cctest/test-accessors.cc @@ -241,7 +241,7 @@ static v8::Handle<Value> CheckAccessorArgsCorrect(Local<String> name, ApiTestFuzzer::Fuzz(); CHECK(info.This() == info.Holder()); CHECK(info.Data()->Equals(v8::String::New("data"))); - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK(info.This() == info.Holder()); CHECK(info.Data()->Equals(v8::String::New("data"))); return v8::Integer::New(17); diff --git a/test/cctest/test-alloc.cc b/test/cctest/test-alloc.cc index 97671923..769fe7be 100644 --- a/test/cctest/test-alloc.cc +++ b/test/cctest/test-alloc.cc @@ -1,4 +1,4 @@ -// Copyright 2007-2008 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -72,11 +72,29 @@ static MaybeObject* AllocateAfterFailures() { } CHECK(!heap->AllocateRawAsciiString(100, TENURED)->IsFailure()); + // Old pointer space. + OldSpace* old_pointer_space = heap->old_pointer_space(); + static const int kOldPointerSpaceFillerLength = 10000; + static const int kOldPointerSpaceFillerSize = FixedArray::SizeFor( + kOldPointerSpaceFillerLength); + while (old_pointer_space->Available() > kOldPointerSpaceFillerSize) { + CHECK(!heap->AllocateFixedArray(kOldPointerSpaceFillerLength, TENURED)-> + IsFailure()); + } + CHECK(!heap->AllocateFixedArray(kOldPointerSpaceFillerLength, TENURED)-> + IsFailure()); + // Large object space. - while (!heap->OldGenerationAllocationLimitReached()) { - CHECK(!heap->AllocateFixedArray(10000, TENURED)->IsFailure()); + static const int kLargeObjectSpaceFillerLength = 300000; + static const int kLargeObjectSpaceFillerSize = FixedArray::SizeFor( + kLargeObjectSpaceFillerLength); + ASSERT(kLargeObjectSpaceFillerSize > heap->old_pointer_space()->AreaSize()); + while (heap->OldGenerationSpaceAvailable() > kLargeObjectSpaceFillerSize) { + CHECK(!heap->AllocateFixedArray(kLargeObjectSpaceFillerLength, TENURED)-> + IsFailure()); } - CHECK(!heap->AllocateFixedArray(10000, TENURED)->IsFailure()); + CHECK(!heap->AllocateFixedArray(kLargeObjectSpaceFillerLength, TENURED)-> + IsFailure()); // Map space. MapSpace* map_space = heap->map_space(); @@ -175,20 +193,20 @@ unsigned int Pseudorandom() { // Plain old data class. Represents a block of allocated memory. class Block { public: - Block(void* base_arg, int size_arg) + Block(Address base_arg, int size_arg) : base(base_arg), size(size_arg) {} - void *base; + Address base; int size; }; TEST(CodeRange) { - const int code_range_size = 16*MB; - OS::Setup(); + const int code_range_size = 32*MB; + OS::SetUp(); Isolate::Current()->InitializeLoggingAndCounters(); CodeRange* code_range = new CodeRange(Isolate::Current()); - code_range->Setup(code_range_size); + code_range->SetUp(code_range_size); int current_allocated = 0; int total_allocated = 0; List<Block> blocks(1000); @@ -196,11 +214,15 @@ TEST(CodeRange) { while (total_allocated < 5 * code_range_size) { if (current_allocated < code_range_size / 10) { // Allocate a block. - // Geometrically distributed sizes, greater than Page::kPageSize. - size_t requested = (Page::kPageSize << (Pseudorandom() % 6)) + - Pseudorandom() % 5000 + 1; + // Geometrically distributed sizes, greater than + // Page::kMaxNonCodeHeapObjectSize (which is greater than code page area). + // TODO(gc): instead of using 3 use some contant based on code_range_size + // kMaxHeapObjectSize. + size_t requested = + (Page::kMaxNonCodeHeapObjectSize << (Pseudorandom() % 3)) + + Pseudorandom() % 5000 + 1; size_t allocated = 0; - void* base = code_range->AllocateRawMemory(requested, &allocated); + Address base = code_range->AllocateRawMemory(requested, &allocated); CHECK(base != NULL); blocks.Add(Block(base, static_cast<int>(allocated))); current_allocated += static_cast<int>(allocated); diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index c1c8aae5..b1a23c1e 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// 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: @@ -80,6 +80,11 @@ static void ExpectString(const char* code, const char* expected) { CHECK_EQ(expected, *ascii); } +static void ExpectInt32(const char* code, int expected) { + Local<Value> result = CompileRun(code); + CHECK(result->IsInt32()); + CHECK_EQ(expected, result->Int32Value()); +} static void ExpectBoolean(const char* code, bool expected) { Local<Value> result = CompileRun(code); @@ -393,11 +398,11 @@ THREADED_TEST(ScriptUsingStringResource) { CHECK(source->IsExternal()); CHECK_EQ(resource, static_cast<TestResource*>(source->GetExternalStringResource())); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(0, dispose_count); } v8::internal::Isolate::Current()->compilation_cache()->Clear(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllAvailableGarbage(); CHECK_EQ(1, dispose_count); } @@ -415,11 +420,11 @@ THREADED_TEST(ScriptUsingAsciiStringResource) { Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(0, dispose_count); } i::Isolate::Current()->compilation_cache()->Clear(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllAvailableGarbage(); CHECK_EQ(1, dispose_count); } @@ -441,11 +446,11 @@ THREADED_TEST(ScriptMakingExternalString) { Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(0, dispose_count); } i::Isolate::Current()->compilation_cache()->Clear(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); CHECK_EQ(1, dispose_count); } @@ -467,11 +472,11 @@ THREADED_TEST(ScriptMakingExternalAsciiString) { Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(0, dispose_count); } i::Isolate::Current()->compilation_cache()->Clear(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); CHECK_EQ(1, dispose_count); } @@ -484,7 +489,7 @@ TEST(MakingExternalStringConditions) { HEAP->CollectGarbage(i::NEW_SPACE); HEAP->CollectGarbage(i::NEW_SPACE); - uint16_t* two_byte_string = AsciiToTwoByteString("small"); + uint16_t* two_byte_string = AsciiToTwoByteString("s1"); Local<String> small_string = String::New(two_byte_string); i::DeleteArray(two_byte_string); @@ -496,7 +501,7 @@ TEST(MakingExternalStringConditions) { // Old space strings should be accepted. CHECK(small_string->CanMakeExternal()); - two_byte_string = AsciiToTwoByteString("small 2"); + two_byte_string = AsciiToTwoByteString("small string 2"); small_string = String::New(two_byte_string); i::DeleteArray(two_byte_string); @@ -530,7 +535,7 @@ TEST(MakingExternalAsciiStringConditions) { HEAP->CollectGarbage(i::NEW_SPACE); HEAP->CollectGarbage(i::NEW_SPACE); - Local<String> small_string = String::New("small"); + Local<String> small_string = String::New("s1"); // We should refuse to externalize newly created small string. CHECK(!small_string->CanMakeExternal()); // Trigger GCs so that the newly allocated string moves to old gen. @@ -539,7 +544,7 @@ TEST(MakingExternalAsciiStringConditions) { // Old space strings should be accepted. CHECK(small_string->CanMakeExternal()); - small_string = String::New("small 2"); + small_string = String::New("small string 2"); // We should refuse externalizing newly created small string. CHECK(!small_string->CanMakeExternal()); for (int i = 0; i < 100; i++) { @@ -572,8 +577,8 @@ THREADED_TEST(UsingExternalString) { i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring); CHECK(isymbol->IsSymbol()); } - HEAP->CollectAllGarbage(false); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -590,8 +595,8 @@ THREADED_TEST(UsingExternalAsciiString) { i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring); CHECK(isymbol->IsSymbol()); } - HEAP->CollectAllGarbage(false); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -672,11 +677,11 @@ TEST(ExternalStringWithDisposeHandling) { Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllAvailableGarbage(); CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count); } i::Isolate::Current()->compilation_cache()->Clear(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllAvailableGarbage(); CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls); CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count); @@ -693,11 +698,11 @@ TEST(ExternalStringWithDisposeHandling) { Local<Value> value = script->Run(); CHECK(value->IsNumber()); CHECK_EQ(7, value->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllAvailableGarbage(); CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count); } i::Isolate::Current()->compilation_cache()->Clear(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllAvailableGarbage(); CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls); CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count); } @@ -744,8 +749,8 @@ THREADED_TEST(StringConcat) { CHECK_EQ(68, value->Int32Value()); } i::Isolate::Current()->compilation_cache()->Clear(); - HEAP->CollectAllGarbage(false); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -1182,9 +1187,8 @@ THREADED_TEST(GlobalPrototype) { templ->Set("x", v8_num(200)); templ->SetAccessor(v8_str("m"), GetM); LocalContext env(0, templ); - v8::Handle<v8::Object> obj = env->Global(); - v8::Handle<Script> script = v8_compile("dummy()"); - v8::Handle<Value> result = script->Run(); + v8::Handle<Script> script(v8_compile("dummy()")); + v8::Handle<Value> result(script->Run()); CHECK_EQ(13.4, result->NumberValue()); CHECK_EQ(200, v8_compile("x")->Run()->Int32Value()); CHECK_EQ(876, v8_compile("m")->Run()->Int32Value()); @@ -1294,6 +1298,279 @@ static v8::Handle<Value> EchoNamedProperty(Local<String> name, return name; } +// Helper functions for Interceptor/Accessor interaction tests + +Handle<Value> SimpleAccessorGetter(Local<String> name, + const AccessorInfo& info) { + Handle<Object> self = info.This(); + return self->Get(String::Concat(v8_str("accessor_"), name)); +} + +void SimpleAccessorSetter(Local<String> name, Local<Value> value, + const AccessorInfo& info) { + Handle<Object> self = info.This(); + self->Set(String::Concat(v8_str("accessor_"), name), value); +} + +Handle<Value> EmptyInterceptorGetter(Local<String> name, + const AccessorInfo& info) { + return Handle<Value>(); +} + +Handle<Value> EmptyInterceptorSetter(Local<String> name, + Local<Value> value, + const AccessorInfo& info) { + return Handle<Value>(); +} + +Handle<Value> InterceptorGetter(Local<String> name, + const AccessorInfo& info) { + // Intercept names that start with 'interceptor_'. + String::AsciiValue ascii(name); + char* name_str = *ascii; + char prefix[] = "interceptor_"; + int i; + for (i = 0; name_str[i] && prefix[i]; ++i) { + if (name_str[i] != prefix[i]) return Handle<Value>(); + } + Handle<Object> self = info.This(); + return self->GetHiddenValue(v8_str(name_str + i)); +} + +Handle<Value> InterceptorSetter(Local<String> name, + Local<Value> value, + const AccessorInfo& info) { + // Intercept accesses that set certain integer values. + if (value->IsInt32() && value->Int32Value() < 10000) { + Handle<Object> self = info.This(); + self->SetHiddenValue(name, value); + return value; + } + return Handle<Value>(); +} + +void AddAccessor(Handle<FunctionTemplate> templ, + Handle<String> name, + v8::AccessorGetter getter, + v8::AccessorSetter setter) { + templ->PrototypeTemplate()->SetAccessor(name, getter, setter); +} + +void AddInterceptor(Handle<FunctionTemplate> templ, + v8::NamedPropertyGetter getter, + v8::NamedPropertySetter setter) { + templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter); +} + +THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) { + v8::HandleScope scope; + Handle<FunctionTemplate> parent = FunctionTemplate::New(); + Handle<FunctionTemplate> child = FunctionTemplate::New(); + child->Inherit(parent); + AddAccessor(parent, v8_str("age"), + SimpleAccessorGetter, SimpleAccessorSetter); + AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Child"), child->GetFunction()); + CompileRun("var child = new Child;" + "child.age = 10;"); + ExpectBoolean("child.hasOwnProperty('age')", false); + ExpectInt32("child.age", 10); + ExpectInt32("child.accessor_age", 10); +} + +THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) { + v8::HandleScope scope; + Handle<FunctionTemplate> parent = FunctionTemplate::New(); + Handle<FunctionTemplate> child = FunctionTemplate::New(); + child->Inherit(parent); + AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Child"), child->GetFunction()); + CompileRun("var child = new Child;" + "var parent = child.__proto__;" + "Object.defineProperty(parent, 'age', " + " {get: function(){ return this.accessor_age; }, " + " set: function(v){ this.accessor_age = v; }, " + " enumerable: true, configurable: true});" + "child.age = 10;"); + ExpectBoolean("child.hasOwnProperty('age')", false); + ExpectInt32("child.age", 10); + ExpectInt32("child.accessor_age", 10); +} + +THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) { + v8::HandleScope scope; + Handle<FunctionTemplate> parent = FunctionTemplate::New(); + Handle<FunctionTemplate> child = FunctionTemplate::New(); + child->Inherit(parent); + AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Child"), child->GetFunction()); + CompileRun("var child = new Child;" + "var parent = child.__proto__;" + "parent.name = 'Alice';"); + ExpectBoolean("child.hasOwnProperty('name')", false); + ExpectString("child.name", "Alice"); + CompileRun("child.name = 'Bob';"); + ExpectString("child.name", "Bob"); + ExpectBoolean("child.hasOwnProperty('name')", true); + ExpectString("parent.name", "Alice"); +} + +THREADED_TEST(SwitchFromInterceptorToAccessor) { + v8::HandleScope scope; + Handle<FunctionTemplate> templ = FunctionTemplate::New(); + AddAccessor(templ, v8_str("age"), + SimpleAccessorGetter, SimpleAccessorSetter); + AddInterceptor(templ, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Obj"), templ->GetFunction()); + CompileRun("var obj = new Obj;" + "function setAge(i){ obj.age = i; };" + "for(var i = 0; i <= 10000; i++) setAge(i);"); + // All i < 10000 go to the interceptor. + ExpectInt32("obj.interceptor_age", 9999); + // The last i goes to the accessor. + ExpectInt32("obj.accessor_age", 10000); +} + +THREADED_TEST(SwitchFromAccessorToInterceptor) { + v8::HandleScope scope; + Handle<FunctionTemplate> templ = FunctionTemplate::New(); + AddAccessor(templ, v8_str("age"), + SimpleAccessorGetter, SimpleAccessorSetter); + AddInterceptor(templ, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Obj"), templ->GetFunction()); + CompileRun("var obj = new Obj;" + "function setAge(i){ obj.age = i; };" + "for(var i = 20000; i >= 9999; i--) setAge(i);"); + // All i >= 10000 go to the accessor. + ExpectInt32("obj.accessor_age", 10000); + // The last i goes to the interceptor. + ExpectInt32("obj.interceptor_age", 9999); +} + +THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) { + v8::HandleScope scope; + Handle<FunctionTemplate> parent = FunctionTemplate::New(); + Handle<FunctionTemplate> child = FunctionTemplate::New(); + child->Inherit(parent); + AddAccessor(parent, v8_str("age"), + SimpleAccessorGetter, SimpleAccessorSetter); + AddInterceptor(child, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Child"), child->GetFunction()); + CompileRun("var child = new Child;" + "function setAge(i){ child.age = i; };" + "for(var i = 0; i <= 10000; i++) setAge(i);"); + // All i < 10000 go to the interceptor. + ExpectInt32("child.interceptor_age", 9999); + // The last i goes to the accessor. + ExpectInt32("child.accessor_age", 10000); +} + +THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) { + v8::HandleScope scope; + Handle<FunctionTemplate> parent = FunctionTemplate::New(); + Handle<FunctionTemplate> child = FunctionTemplate::New(); + child->Inherit(parent); + AddAccessor(parent, v8_str("age"), + SimpleAccessorGetter, SimpleAccessorSetter); + AddInterceptor(child, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Child"), child->GetFunction()); + CompileRun("var child = new Child;" + "function setAge(i){ child.age = i; };" + "for(var i = 20000; i >= 9999; i--) setAge(i);"); + // All i >= 10000 go to the accessor. + ExpectInt32("child.accessor_age", 10000); + // The last i goes to the interceptor. + ExpectInt32("child.interceptor_age", 9999); +} + +THREADED_TEST(SwitchFromInterceptorToJSAccessor) { + v8::HandleScope scope; + Handle<FunctionTemplate> templ = FunctionTemplate::New(); + AddInterceptor(templ, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Obj"), templ->GetFunction()); + CompileRun("var obj = new Obj;" + "function setter(i) { this.accessor_age = i; };" + "function getter() { return this.accessor_age; };" + "function setAge(i) { obj.age = i; };" + "Object.defineProperty(obj, 'age', { get:getter, set:setter });" + "for(var i = 0; i <= 10000; i++) setAge(i);"); + // All i < 10000 go to the interceptor. + ExpectInt32("obj.interceptor_age", 9999); + // The last i goes to the JavaScript accessor. + ExpectInt32("obj.accessor_age", 10000); + // The installed JavaScript getter is still intact. + // This last part is a regression test for issue 1651 and relies on the fact + // that both interceptor and accessor are being installed on the same object. + ExpectInt32("obj.age", 10000); + ExpectBoolean("obj.hasOwnProperty('age')", true); + ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value"); +} + +THREADED_TEST(SwitchFromJSAccessorToInterceptor) { + v8::HandleScope scope; + Handle<FunctionTemplate> templ = FunctionTemplate::New(); + AddInterceptor(templ, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Obj"), templ->GetFunction()); + CompileRun("var obj = new Obj;" + "function setter(i) { this.accessor_age = i; };" + "function getter() { return this.accessor_age; };" + "function setAge(i) { obj.age = i; };" + "Object.defineProperty(obj, 'age', { get:getter, set:setter });" + "for(var i = 20000; i >= 9999; i--) setAge(i);"); + // All i >= 10000 go to the accessor. + ExpectInt32("obj.accessor_age", 10000); + // The last i goes to the interceptor. + ExpectInt32("obj.interceptor_age", 9999); + // The installed JavaScript getter is still intact. + // This last part is a regression test for issue 1651 and relies on the fact + // that both interceptor and accessor are being installed on the same object. + ExpectInt32("obj.age", 10000); + ExpectBoolean("obj.hasOwnProperty('age')", true); + ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value"); +} + +THREADED_TEST(SwitchFromInterceptorToProperty) { + v8::HandleScope scope; + Handle<FunctionTemplate> parent = FunctionTemplate::New(); + Handle<FunctionTemplate> child = FunctionTemplate::New(); + child->Inherit(parent); + AddInterceptor(child, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Child"), child->GetFunction()); + CompileRun("var child = new Child;" + "function setAge(i){ child.age = i; };" + "for(var i = 0; i <= 10000; i++) setAge(i);"); + // All i < 10000 go to the interceptor. + ExpectInt32("child.interceptor_age", 9999); + // The last i goes to child's own property. + ExpectInt32("child.age", 10000); +} + +THREADED_TEST(SwitchFromPropertyToInterceptor) { + v8::HandleScope scope; + Handle<FunctionTemplate> parent = FunctionTemplate::New(); + Handle<FunctionTemplate> child = FunctionTemplate::New(); + child->Inherit(parent); + AddInterceptor(child, InterceptorGetter, InterceptorSetter); + LocalContext env; + env->Global()->Set(v8_str("Child"), child->GetFunction()); + CompileRun("var child = new Child;" + "function setAge(i){ child.age = i; };" + "for(var i = 20000; i >= 9999; i--) setAge(i);"); + // All i >= 10000 go to child's own property. + ExpectInt32("child.age", 10000); + // The last i goes to the interceptor. + ExpectInt32("child.interceptor_age", 9999); +} THREADED_TEST(NamedPropertyHandlerGetter) { echo_named_call_count = 0; @@ -1567,7 +1844,7 @@ THREADED_TEST(DeepCrossLanguageRecursion) { env->Global()->Set(v8_str("depth"), v8::Integer::New(0)); call_recursively_script = v8_compile("callScriptRecursively()"); - v8::Handle<Value> result = call_recursively_script->Run(); + call_recursively_script->Run(); call_recursively_script = v8::Handle<Script>(); env->Global()->Set(v8_str("depth"), v8::Integer::New(0)); @@ -1666,12 +1943,12 @@ THREADED_TEST(InternalFieldsNativePointers) { // Check reading and writing aligned pointers. obj->SetPointerInInternalField(0, aligned); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(aligned, obj->GetPointerFromInternalField(0)); // Check reading and writing unaligned pointers. obj->SetPointerInInternalField(0, unaligned); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0)); delete[] data; @@ -1697,19 +1974,19 @@ THREADED_TEST(InternalFieldsNativePointersAndExternal) { CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1)); obj->SetPointerInInternalField(0, aligned); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(aligned, v8::External::Unwrap(obj->GetInternalField(0))); obj->SetPointerInInternalField(0, unaligned); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(unaligned, v8::External::Unwrap(obj->GetInternalField(0))); obj->SetInternalField(0, v8::External::Wrap(aligned)); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(aligned, obj->GetPointerFromInternalField(0)); obj->SetInternalField(0, v8::External::Wrap(unaligned)); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0)); delete[] data; @@ -1722,7 +1999,7 @@ THREADED_TEST(IdentityHash) { // Ensure that the test starts with an fresh heap to test whether the hash // code is based on the address. - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); Local<v8::Object> obj = v8::Object::New(); int hash = obj->GetIdentityHash(); int hash1 = obj->GetIdentityHash(); @@ -1732,7 +2009,7 @@ THREADED_TEST(IdentityHash) { // objects should not be assigned the same hash code. If the test below fails // the random number generator should be evaluated. CHECK_NE(hash, hash2); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); int hash3 = v8::Object::New()->GetIdentityHash(); // Make sure that the identity hash is not based on the initial address of // the object alone. If the test below fails the random number generator @@ -1769,7 +2046,7 @@ THREADED_TEST(HiddenProperties) { v8::Local<v8::String> empty = v8_str(""); v8::Local<v8::String> prop_name = v8_str("prop_name"); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); // Make sure delete of a non-existent hidden value works CHECK(obj->DeleteHiddenValue(key)); @@ -1779,7 +2056,7 @@ THREADED_TEST(HiddenProperties) { CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002))); CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); // Make sure we do not find the hidden property. CHECK(!obj->Has(empty)); @@ -1790,7 +2067,7 @@ THREADED_TEST(HiddenProperties) { CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); CHECK_EQ(2003, obj->Get(empty)->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); // Add another property and delete it afterwards to force the object in // slow case. @@ -1801,7 +2078,7 @@ THREADED_TEST(HiddenProperties) { CHECK(obj->Delete(prop_name)); CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK(obj->DeleteHiddenValue(key)); CHECK(obj->GetHiddenValue(key).IsEmpty()); @@ -1908,19 +2185,30 @@ THREADED_TEST(GlobalHandle) { } -static int NumberOfWeakCalls = 0; +class WeakCallCounter { + public: + explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { } + int id() { return id_; } + void increment() { number_of_weak_calls_++; } + int NumberOfWeakCalls() { return number_of_weak_calls_; } + private: + int id_; + int number_of_weak_calls_; +}; + + static void WeakPointerCallback(Persistent<Value> handle, void* id) { - CHECK_EQ(reinterpret_cast<void*>(1234), id); - NumberOfWeakCalls++; + WeakCallCounter* counter = reinterpret_cast<WeakCallCounter*>(id); + CHECK_EQ(1234, counter->id()); + counter->increment(); handle.Dispose(); } + THREADED_TEST(ApiObjectGroups) { HandleScope scope; LocalContext env; - NumberOfWeakCalls = 0; - Persistent<Object> g1s1; Persistent<Object> g1s2; Persistent<Object> g1c1; @@ -1928,21 +2216,23 @@ THREADED_TEST(ApiObjectGroups) { Persistent<Object> g2s2; Persistent<Object> g2c1; + WeakCallCounter counter(1234); + { HandleScope scope; g1s1 = Persistent<Object>::New(Object::New()); g1s2 = Persistent<Object>::New(Object::New()); g1c1 = Persistent<Object>::New(Object::New()); - g1s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g1s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g1c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + g1s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g1s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g1c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); g2s1 = Persistent<Object>::New(Object::New()); g2s2 = Persistent<Object>::New(Object::New()); g2c1 = Persistent<Object>::New(Object::New()); - g2s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g2s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g2c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + g2s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g2s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g2c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); } Persistent<Object> root = Persistent<Object>::New(g1s1); // make a root. @@ -1961,14 +2251,14 @@ THREADED_TEST(ApiObjectGroups) { V8::AddObjectGroup(g2_objects, 2); V8::AddImplicitReferences(g2s2, g2_children, 1); } - // Do a full GC - HEAP->CollectGarbage(i::OLD_POINTER_SPACE); + // Do a single full GC, ensure incremental marking is stopped. + HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); // All object should be alive. - CHECK_EQ(0, NumberOfWeakCalls); + CHECK_EQ(0, counter.NumberOfWeakCalls()); // Weaken the root. - root.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + root.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); // But make children strong roots---all the objects (except for children) // should be collectable now. g1c1.ClearWeak(); @@ -1986,17 +2276,17 @@ THREADED_TEST(ApiObjectGroups) { V8::AddImplicitReferences(g2s2, g2_children, 1); } - HEAP->CollectGarbage(i::OLD_POINTER_SPACE); + HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); // All objects should be gone. 5 global handles in total. - CHECK_EQ(5, NumberOfWeakCalls); + CHECK_EQ(5, counter.NumberOfWeakCalls()); // And now make children weak again and collect them. - g1c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g2c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + g1c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g2c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); - HEAP->CollectGarbage(i::OLD_POINTER_SPACE); - CHECK_EQ(7, NumberOfWeakCalls); + HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); + CHECK_EQ(7, counter.NumberOfWeakCalls()); } @@ -2004,7 +2294,7 @@ THREADED_TEST(ApiObjectGroupsCycle) { HandleScope scope; LocalContext env; - NumberOfWeakCalls = 0; + WeakCallCounter counter(1234); Persistent<Object> g1s1; Persistent<Object> g1s2; @@ -2017,18 +2307,18 @@ THREADED_TEST(ApiObjectGroupsCycle) { HandleScope scope; g1s1 = Persistent<Object>::New(Object::New()); g1s2 = Persistent<Object>::New(Object::New()); - g1s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g1s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + g1s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g1s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); g2s1 = Persistent<Object>::New(Object::New()); g2s2 = Persistent<Object>::New(Object::New()); - g2s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g2s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + g2s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g2s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); g3s1 = Persistent<Object>::New(Object::New()); g3s2 = Persistent<Object>::New(Object::New()); - g3s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); - g3s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + g3s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); + g3s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); } Persistent<Object> root = Persistent<Object>::New(g1s1); // make a root. @@ -2050,14 +2340,14 @@ THREADED_TEST(ApiObjectGroupsCycle) { V8::AddObjectGroup(g3_objects, 2); V8::AddImplicitReferences(g3s1, g3_children, 1); } - // Do a full GC - HEAP->CollectGarbage(i::OLD_POINTER_SPACE); + // Do a single full GC + HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); // All object should be alive. - CHECK_EQ(0, NumberOfWeakCalls); + CHECK_EQ(0, counter.NumberOfWeakCalls()); // Weaken the root. - root.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); + root.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); // Groups are deleted, rebuild groups. { @@ -2075,10 +2365,10 @@ THREADED_TEST(ApiObjectGroupsCycle) { V8::AddImplicitReferences(g3s1, g3_children, 1); } - HEAP->CollectGarbage(i::OLD_POINTER_SPACE); + HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); // All objects should be gone. 7 global handles in total. - CHECK_EQ(7, NumberOfWeakCalls); + CHECK_EQ(7, counter.NumberOfWeakCalls()); } @@ -2573,6 +2863,16 @@ THREADED_TEST(isNumberType) { obj = env->Global()->Get(v8_str("obj")); CHECK(!obj->IsInt32()); CHECK(!obj->IsUint32()); + // Positive zero + CompileRun("var obj = 0.0;"); + obj = env->Global()->Get(v8_str("obj")); + CHECK(obj->IsInt32()); + CHECK(obj->IsUint32()); + // Positive zero + CompileRun("var obj = -0.0;"); + obj = env->Global()->Get(v8_str("obj")); + CHECK(!obj->IsInt32()); + CHECK(!obj->IsUint32()); } @@ -4172,7 +4472,7 @@ THREADED_TEST(ExtensibleOnUndetectable) { source = v8_str("undetectable.y = 2000;"); script = Script::Compile(source); - Local<Value> result = script->Run(); + script->Run(); ExpectBoolean("undetectable.y == undefined", true); } @@ -4305,6 +4605,47 @@ THREADED_TEST(SimpleExtensions) { } +static const char* kEmbeddedExtensionSource = + "function Ret54321(){return 54321;}~~@@$" + "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS."; +static const int kEmbeddedExtensionSourceValidLen = 34; + + +THREADED_TEST(ExtensionMissingSourceLength) { + v8::HandleScope handle_scope; + v8::RegisterExtension(new Extension("srclentest_fail", + kEmbeddedExtensionSource)); + const char* extension_names[] = { "srclentest_fail" }; + v8::ExtensionConfiguration extensions(1, extension_names); + v8::Handle<Context> context = Context::New(&extensions); + CHECK_EQ(0, *context); +} + + +THREADED_TEST(ExtensionWithSourceLength) { + for (int source_len = kEmbeddedExtensionSourceValidLen - 1; + source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) { + v8::HandleScope handle_scope; + i::ScopedVector<char> extension_name(32); + i::OS::SNPrintF(extension_name, "ext #%d", source_len); + v8::RegisterExtension(new Extension(extension_name.start(), + kEmbeddedExtensionSource, 0, 0, + source_len)); + const char* extension_names[1] = { extension_name.start() }; + v8::ExtensionConfiguration extensions(1, extension_names); + v8::Handle<Context> context = Context::New(&extensions); + if (source_len == kEmbeddedExtensionSourceValidLen) { + Context::Scope lock(context); + v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run(); + CHECK_EQ(v8::Integer::New(54321), result); + } else { + // Anything but exactly the right length should fail to compile. + CHECK_EQ(0, *context); + } + } +} + + static const char* kEvalExtensionSource1 = "function UseEval1() {" " var x = 42;" @@ -4483,10 +4824,11 @@ THREADED_TEST(NativeFunctionDeclarationError) { "native\nfunction foo();")); const char* extension_names[] = { name }; v8::ExtensionConfiguration extensions(1, extension_names); - v8::Handle<Context> context = Context::New(&extensions); - ASSERT(context.IsEmpty()); + v8::Handle<Context> context(Context::New(&extensions)); + CHECK(context.IsEmpty()); } + THREADED_TEST(NativeFunctionDeclarationErrorEscape) { v8::HandleScope handle_scope; const char* name = "nativedeclerresc"; @@ -4497,8 +4839,8 @@ THREADED_TEST(NativeFunctionDeclarationErrorEscape) { "nativ\\u0065 function foo();")); const char* extension_names[] = { name }; v8::ExtensionConfiguration extensions(1, extension_names); - v8::Handle<Context> context = Context::New(&extensions); - ASSERT(context.IsEmpty()); + v8::Handle<Context> context(Context::New(&extensions)); + CHECK(context.IsEmpty()); } @@ -4664,7 +5006,7 @@ TEST(RegexpOutOfMemory) { Local<Script> script = Script::Compile(String::New(js_code_causing_huge_string_flattening)); last_location = NULL; - Local<Value> result = script->Run(); + script->Run(); CHECK(false); // Should not return. } @@ -4805,7 +5147,7 @@ static void InvokeScavenge() { static void InvokeMarkSweep() { - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -4898,7 +5240,7 @@ static v8::Handle<Value> ArgumentsTestCallback(const v8::Arguments& args) { CHECK_EQ(v8::Integer::New(3), args[2]); CHECK_EQ(v8::Undefined(), args[3]); v8::HandleScope scope; - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); return v8::Undefined(); } @@ -5184,68 +5526,121 @@ static int StrNCmp16(uint16_t* a, uint16_t* b, int n) { } +int GetUtf8Length(Handle<String> str) { + int len = str->Utf8Length(); + if (len < 0) { + i::Handle<i::String> istr(v8::Utils::OpenHandle(*str)); + i::FlattenString(istr); + len = str->Utf8Length(); + } + return len; +} + + THREADED_TEST(StringWrite) { + LocalContext context; v8::HandleScope scope; v8::Handle<String> str = v8_str("abcde"); // abc<Icelandic eth><Unicode snowman>. v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203"); + const int kStride = 4; // Must match stride in for loops in JS below. + CompileRun( + "var left = '';" + "for (var i = 0; i < 0xd800; i += 4) {" + " left = left + String.fromCharCode(i);" + "}"); + CompileRun( + "var right = '';" + "for (var i = 0; i < 0xd800; i += 4) {" + " right = String.fromCharCode(i) + right;" + "}"); + v8::Handle<v8::Object> global = Context::GetCurrent()->Global(); + Handle<String> left_tree = global->Get(v8_str("left")).As<String>(); + Handle<String> right_tree = global->Get(v8_str("right")).As<String>(); CHECK_EQ(5, str2->Length()); + CHECK_EQ(0xd800 / kStride, left_tree->Length()); + CHECK_EQ(0xd800 / kStride, right_tree->Length()); char buf[100]; - char utf8buf[100]; + char utf8buf[0xd800 * 3]; uint16_t wbuf[100]; int len; int charlen; - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen); CHECK_EQ(9, len); CHECK_EQ(5, charlen); CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203")); - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, 8, &charlen); CHECK_EQ(8, len); CHECK_EQ(5, charlen); CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9)); - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, 7, &charlen); CHECK_EQ(5, len); CHECK_EQ(4, charlen); CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5)); - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, 6, &charlen); CHECK_EQ(5, len); CHECK_EQ(4, charlen); CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5)); - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, 5, &charlen); CHECK_EQ(5, len); CHECK_EQ(4, charlen); CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5)); - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, 4, &charlen); CHECK_EQ(3, len); CHECK_EQ(3, charlen); CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4)); - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, 3, &charlen); CHECK_EQ(3, len); CHECK_EQ(3, charlen); CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4)); - memset(utf8buf, 0x1, sizeof(utf8buf)); + memset(utf8buf, 0x1, 1000); len = str2->WriteUtf8(utf8buf, 2, &charlen); CHECK_EQ(2, len); CHECK_EQ(2, charlen); CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3)); + memset(utf8buf, 0x1, sizeof(utf8buf)); + len = GetUtf8Length(left_tree); + int utf8_expected = + (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride; + CHECK_EQ(utf8_expected, len); + len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen); + CHECK_EQ(utf8_expected, len); + CHECK_EQ(0xd800 / kStride, charlen); + CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3])); + CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2])); + CHECK_EQ(0xc0 - kStride, + static_cast<unsigned char>(utf8buf[utf8_expected - 1])); + CHECK_EQ(1, utf8buf[utf8_expected]); + + memset(utf8buf, 0x1, sizeof(utf8buf)); + len = GetUtf8Length(right_tree); + CHECK_EQ(utf8_expected, len); + len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen); + CHECK_EQ(utf8_expected, len); + CHECK_EQ(0xd800 / kStride, charlen); + CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0])); + CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1])); + CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2])); + CHECK_EQ(1, utf8buf[utf8_expected]); + memset(buf, 0x1, sizeof(buf)); memset(wbuf, 0x1, sizeof(wbuf)); len = str->WriteAscii(buf); @@ -5361,6 +5756,225 @@ THREADED_TEST(StringWrite) { } +static void Utf16Helper( + LocalContext& context, + const char* name, + const char* lengths_name, + int len) { + Local<v8::Array> a = + Local<v8::Array>::Cast(context->Global()->Get(v8_str(name))); + Local<v8::Array> alens = + Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name))); + for (int i = 0; i < len; i++) { + Local<v8::String> string = + Local<v8::String>::Cast(a->Get(i)); + Local<v8::Number> expected_len = + Local<v8::Number>::Cast(alens->Get(i)); + CHECK_EQ(expected_len->Value() != string->Length(), + string->MayContainNonAscii()); + int length = GetUtf8Length(string); + CHECK_EQ(static_cast<int>(expected_len->Value()), length); + } +} + + +static uint16_t StringGet(Handle<String> str, int index) { + i::Handle<i::String> istring = + v8::Utils::OpenHandle(String::Cast(*str)); + return istring->Get(index); +} + + +static void WriteUtf8Helper( + LocalContext& context, + const char* name, + const char* lengths_name, + int len) { + Local<v8::Array> b = + Local<v8::Array>::Cast(context->Global()->Get(v8_str(name))); + Local<v8::Array> alens = + Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name))); + char buffer[1000]; + char buffer2[1000]; + for (int i = 0; i < len; i++) { + Local<v8::String> string = + Local<v8::String>::Cast(b->Get(i)); + Local<v8::Number> expected_len = + Local<v8::Number>::Cast(alens->Get(i)); + int utf8_length = static_cast<int>(expected_len->Value()); + for (int j = utf8_length + 1; j >= 0; j--) { + memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer)); + memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2)); + int nchars; + int utf8_written = + string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS); + int utf8_written2 = + string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION); + CHECK_GE(utf8_length + 1, utf8_written); + CHECK_GE(utf8_length, utf8_written2); + for (int k = 0; k < utf8_written2; k++) { + CHECK_EQ(buffer[k], buffer2[k]); + } + CHECK(nchars * 3 >= utf8_written - 1); + CHECK(nchars <= utf8_written); + if (j == utf8_length + 1) { + CHECK_EQ(utf8_written2, utf8_length); + CHECK_EQ(utf8_written2 + 1, utf8_written); + } + CHECK_EQ(buffer[utf8_written], 42); + if (j > utf8_length) { + if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0); + if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42); + Handle<String> roundtrip = v8_str(buffer); + CHECK(roundtrip->Equals(string)); + } else { + if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42); + } + if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42); + if (nchars >= 2) { + uint16_t trail = StringGet(string, nchars - 1); + uint16_t lead = StringGet(string, nchars - 2); + if (((lead & 0xfc00) == 0xd800) && + ((trail & 0xfc00) == 0xdc00)) { + unsigned char u1 = buffer2[utf8_written2 - 4]; + unsigned char u2 = buffer2[utf8_written2 - 3]; + unsigned char u3 = buffer2[utf8_written2 - 2]; + unsigned char u4 = buffer2[utf8_written2 - 1]; + CHECK_EQ((u1 & 0xf8), 0xf0); + CHECK_EQ((u2 & 0xc0), 0x80); + CHECK_EQ((u3 & 0xc0), 0x80); + CHECK_EQ((u4 & 0xc0), 0x80); + uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff); + CHECK_EQ((u4 & 0x3f), (c & 0x3f)); + CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f)); + CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f)); + CHECK_EQ((u1 & 0x3), c >> 18); + } + } + } + } +} + + +THREADED_TEST(Utf16) { + LocalContext context; + v8::HandleScope scope; + CompileRun( + "var pad = '01234567890123456789';" + "var p = [];" + "var plens = [20, 3, 3];" + "p.push('01234567890123456789');" + "var lead = 0xd800;" + "var trail = 0xdc00;" + "p.push(String.fromCharCode(0xd800));" + "p.push(String.fromCharCode(0xdc00));" + "var a = [];" + "var b = [];" + "var c = [];" + "var alens = [];" + "for (var i = 0; i < 3; i++) {" + " p[1] = String.fromCharCode(lead++);" + " for (var j = 0; j < 3; j++) {" + " p[2] = String.fromCharCode(trail++);" + " a.push(p[i] + p[j]);" + " b.push(p[i] + p[j]);" + " c.push(p[i] + p[j]);" + " alens.push(plens[i] + plens[j]);" + " }" + "}" + "alens[5] -= 2;" // Here the surrogate pairs match up. + "var a2 = [];" + "var b2 = [];" + "var c2 = [];" + "var a2lens = [];" + "for (var m = 0; m < 9; m++) {" + " for (var n = 0; n < 9; n++) {" + " a2.push(a[m] + a[n]);" + " b2.push(b[m] + b[n]);" + " var newc = 'x' + c[m] + c[n] + 'y';" + " c2.push(newc.substring(1, newc.length - 1));" + " var utf = alens[m] + alens[n];" // And here. + // The 'n's that start with 0xdc.. are 6-8 + // The 'm's that end with 0xd8.. are 1, 4 and 7 + " if ((m % 3) == 1 && n >= 6) utf -= 2;" + " a2lens.push(utf);" + " }" + "}"); + Utf16Helper(context, "a", "alens", 9); + Utf16Helper(context, "a2", "a2lens", 81); + WriteUtf8Helper(context, "b", "alens", 9); + WriteUtf8Helper(context, "b2", "a2lens", 81); + WriteUtf8Helper(context, "c2", "a2lens", 81); +} + + +static bool SameSymbol(Handle<String> s1, Handle<String> s2) { + i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1)); + i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2)); + return *is1 == *is2; +} + + +static void SameSymbolHelper(const char* a, const char* b) { + Handle<String> symbol1 = v8::String::NewSymbol(a); + Handle<String> symbol2 = v8::String::NewSymbol(b); + CHECK(SameSymbol(symbol1, symbol2)); +} + + +THREADED_TEST(Utf16Symbol) { + LocalContext context; + v8::HandleScope scope; + + Handle<String> symbol1 = v8::String::NewSymbol("abc"); + Handle<String> symbol2 = v8::String::NewSymbol("abc"); + CHECK(SameSymbol(symbol1, symbol2)); + + SameSymbolHelper("\360\220\220\205", // 4 byte encoding. + "\355\240\201\355\260\205"); // 2 3-byte surrogates. + SameSymbolHelper("\355\240\201\355\260\206", // 2 3-byte surrogates. + "\360\220\220\206"); // 4 byte encoding. + SameSymbolHelper("x\360\220\220\205", // 4 byte encoding. + "x\355\240\201\355\260\205"); // 2 3-byte surrogates. + SameSymbolHelper("x\355\240\201\355\260\206", // 2 3-byte surrogates. + "x\360\220\220\206"); // 4 byte encoding. + CompileRun( + "var sym0 = 'benedictus';" + "var sym0b = 'S\303\270ren';" + "var sym1 = '\355\240\201\355\260\207';" + "var sym2 = '\360\220\220\210';" + "var sym3 = 'x\355\240\201\355\260\207';" + "var sym4 = 'x\360\220\220\210';" + "if (sym1.length != 2) throw sym1;" + "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);" + "if (sym2.length != 2) throw sym2;" + "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);" + "if (sym3.length != 3) throw sym3;" + "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);" + "if (sym4.length != 3) throw sym4;" + "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);"); + Handle<String> sym0 = v8::String::NewSymbol("benedictus"); + Handle<String> sym0b = v8::String::NewSymbol("S\303\270ren"); + Handle<String> sym1 = v8::String::NewSymbol("\355\240\201\355\260\207"); + Handle<String> sym2 = v8::String::NewSymbol("\360\220\220\210"); + Handle<String> sym3 = v8::String::NewSymbol("x\355\240\201\355\260\207"); + Handle<String> sym4 = v8::String::NewSymbol("x\360\220\220\210"); + v8::Local<v8::Object> global = context->Global(); + Local<Value> s0 = global->Get(v8_str("sym0")); + Local<Value> s0b = global->Get(v8_str("sym0b")); + Local<Value> s1 = global->Get(v8_str("sym1")); + Local<Value> s2 = global->Get(v8_str("sym2")); + Local<Value> s3 = global->Get(v8_str("sym3")); + Local<Value> s4 = global->Get(v8_str("sym4")); + CHECK(SameSymbol(sym0, Handle<String>(String::Cast(*s0)))); + CHECK(SameSymbol(sym0b, Handle<String>(String::Cast(*s0b)))); + CHECK(SameSymbol(sym1, Handle<String>(String::Cast(*s1)))); + CHECK(SameSymbol(sym2, Handle<String>(String::Cast(*s2)))); + CHECK(SameSymbol(sym3, Handle<String>(String::Cast(*s3)))); + CHECK(SameSymbol(sym4, Handle<String>(String::Cast(*s4)))); +} + + THREADED_TEST(ToArrayIndex) { v8::HandleScope scope; LocalContext context; @@ -5400,7 +6014,6 @@ THREADED_TEST(ErrorConstruction) { v8::Handle<String> message = v8_str("message"); v8::Handle<Value> range_error = v8::Exception::RangeError(foo); CHECK(range_error->IsObject()); - v8::Handle<v8::Object> range_obj = range_error.As<v8::Object>(); CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo)); v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo); CHECK(reference_error->IsObject()); @@ -6970,7 +7583,7 @@ THREADED_TEST(CallKnownGlobalReceiver) { // Create new environment reusing the global object. LocalContext env(NULL, instance_template, global_object); env->Global()->Set(v8_str("foo"), foo); - Local<Value> value = Script::Compile(v8_str("foo()"))->Run(); + Script::Compile(v8_str("foo()"))->Run(); } } @@ -7158,6 +7771,60 @@ THREADED_TEST(SetPrototype) { } +// Getting property names of an object with a prototype chain that +// triggers dictionary elements in GetLocalPropertyNames() shouldn't +// crash the runtime. +THREADED_TEST(Regress91517) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope handle_scope; + LocalContext context; + + Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(); + t1->SetHiddenPrototype(true); + t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1)); + Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(); + t2->SetHiddenPrototype(true); + t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2)); + t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New()); + t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2)); + Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(); + t3->SetHiddenPrototype(true); + t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3)); + Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(); + t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4)); + + // Force dictionary-based properties. + i::ScopedVector<char> name_buf(1024); + for (int i = 1; i <= 1000; i++) { + i::OS::SNPrintF(name_buf, "sdf%d", i); + t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2)); + } + + Local<v8::Object> o1 = t1->GetFunction()->NewInstance(); + Local<v8::Object> o2 = t2->GetFunction()->NewInstance(); + Local<v8::Object> o3 = t3->GetFunction()->NewInstance(); + Local<v8::Object> o4 = t4->GetFunction()->NewInstance(); + + // Create prototype chain of hidden prototypes. + CHECK(o4->SetPrototype(o3)); + CHECK(o3->SetPrototype(o2)); + CHECK(o2->SetPrototype(o1)); + + // Call the runtime version of GetLocalPropertyNames() on the natively + // created object through JavaScript. + context->Global()->Set(v8_str("obj"), o4); + CompileRun("var names = %GetLocalPropertyNames(obj);"); + + ExpectInt32("names.length", 1006); + ExpectTrue("names.indexOf(\"baz\") >= 0"); + ExpectTrue("names.indexOf(\"boo\") >= 0"); + ExpectTrue("names.indexOf(\"foo\") >= 0"); + ExpectTrue("names.indexOf(\"fuz1\") >= 0"); + ExpectTrue("names.indexOf(\"fuz2\") >= 0"); + ExpectFalse("names[1005] == undefined"); +} + + THREADED_TEST(FunctionReadOnlyPrototype) { v8::HandleScope handle_scope; LocalContext context; @@ -7241,7 +7908,8 @@ THREADED_TEST(Constructor) { Local<Function> cons = templ->GetFunction(); context->Global()->Set(v8_str("Fun"), cons); Local<v8::Object> inst = cons->NewInstance(); - i::Handle<i::JSObject> obj = v8::Utils::OpenHandle(*inst); + i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst)); + CHECK(obj->IsJSObject()); Local<Value> value = CompileRun("(new Fun()).constructor === Fun"); CHECK(value->BooleanValue()); } @@ -7492,9 +8160,11 @@ THREADED_TEST(EvalAliasedDynamic) { " var bar = 2;" " with (x) { return eval('bar'); }" "}" - "f(this)")); + "result4 = f(this)")); script->Run(); - CHECK(try_catch.HasCaught()); + CHECK(!try_catch.HasCaught()); + CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value()); + try_catch.Reset(); } @@ -7508,7 +8178,7 @@ THREADED_TEST(CrossEval) { other->SetSecurityToken(token); current->SetSecurityToken(token); - // Setup reference from current to other. + // Set up reference from current to other. current->Global()->Set(v8_str("other"), other->Global()); // Check that new variables are introduced in other context. @@ -7588,7 +8258,7 @@ THREADED_TEST(EvalInDetachedGlobal) { v8::Persistent<Context> context0 = Context::New(); v8::Persistent<Context> context1 = Context::New(); - // Setup function in context0 that uses eval from context0. + // Set up function in context0 that uses eval from context0. context0->Enter(); v8::Handle<v8::Value> fun = CompileRun("var x = 42;" @@ -7626,7 +8296,7 @@ THREADED_TEST(CrossLazyLoad) { other->SetSecurityToken(token); current->SetSecurityToken(token); - // Setup reference from current to other. + // Set up reference from current to other. current->Global()->Set(v8_str("other"), other->Global()); // Trigger lazy loading in other context. @@ -7710,7 +8380,8 @@ THREADED_TEST(CallAsFunction) { } { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); - Local<ObjectTemplate> instance_template = t->InstanceTemplate(); + Local<ObjectTemplate> instance_template(t->InstanceTemplate()); + USE(instance_template); Local<v8::Object> instance = t->GetFunction()->NewInstance(); context->Global()->Set(v8_str("obj2"), instance); v8::TryCatch try_catch; @@ -7815,7 +8486,7 @@ static int Recurse(int depth, int iterations) { v8::HandleScope scope; if (depth == 0) return CountHandles(); for (int i = 0; i < iterations; i++) { - Local<v8::Number> n = v8::Integer::New(42); + Local<v8::Number> n(v8::Integer::New(42)); } return Recurse(depth - 1, iterations); } @@ -7829,7 +8500,7 @@ THREADED_TEST(HandleIteration) { v8::HandleScope scope1; CHECK_EQ(0, CountHandles()); for (int i = 0; i < kIterations; i++) { - Local<v8::Number> n = v8::Integer::New(42); + Local<v8::Number> n(v8::Integer::New(42)); CHECK_EQ(i + 1, CountHandles()); } @@ -7837,7 +8508,7 @@ THREADED_TEST(HandleIteration) { { v8::HandleScope scope2; for (int j = 0; j < kIterations; j++) { - Local<v8::Number> n = v8::Integer::New(42); + Local<v8::Number> n(v8::Integer::New(42)); CHECK_EQ(j + 1 + kIterations, CountHandles()); } } @@ -7883,7 +8554,7 @@ static v8::Handle<Value> InterceptorHasOwnPropertyGetterGC( Local<String> name, const AccessorInfo& info) { ApiTestFuzzer::Fuzz(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); return v8::Handle<Value>(); } @@ -8340,10 +9011,10 @@ THREADED_TEST(InterceptorStoreIC) { 0, 0, 0, v8_str("data")); LocalContext context; context->Global()->Set(v8_str("o"), templ->NewInstance()); - v8::Handle<Value> value = CompileRun( - "for (var i = 0; i < 1000; i++) {" - " o.x = 42;" - "}"); + CompileRun( + "for (var i = 0; i < 1000; i++) {" + " o.x = 42;" + "}"); } @@ -8469,17 +9140,6 @@ THREADED_TEST(InterceptorCallICInvalidatedCacheable) { } -static v8::Handle<Value> call_ic_function5; -static v8::Handle<Value> InterceptorCallICGetter5(Local<String> name, - const AccessorInfo& info) { - ApiTestFuzzer::Fuzz(); - if (v8_str("x")->Equals(name)) - return call_ic_function5; - else - return Local<Value>(); -} - - // This test checks that if interceptor doesn't provide a function, // cached constant function is used THREADED_TEST(InterceptorCallICConstantFunctionUsed) { @@ -8500,6 +9160,17 @@ THREADED_TEST(InterceptorCallICConstantFunctionUsed) { } +static v8::Handle<Value> call_ic_function5; +static v8::Handle<Value> InterceptorCallICGetter5(Local<String> name, + const AccessorInfo& info) { + ApiTestFuzzer::Fuzz(); + if (v8_str("x")->Equals(name)) + return call_ic_function5; + else + return Local<Value>(); +} + + // This test checks that if interceptor provides a function, // even if we cached constant function, interceptor's function // is invoked @@ -8523,6 +9194,48 @@ THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) { } +static v8::Handle<Value> call_ic_function6; +static v8::Handle<Value> InterceptorCallICGetter6(Local<String> name, + const AccessorInfo& info) { + ApiTestFuzzer::Fuzz(); + if (v8_str("x")->Equals(name)) + return call_ic_function6; + else + return Local<Value>(); +} + + +// Same test as above, except the code is wrapped in a function +// to test the optimized compiler. +THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope scope; + v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(); + templ->SetNamedPropertyHandler(InterceptorCallICGetter6); + LocalContext context; + context->Global()->Set(v8_str("o"), templ->NewInstance()); + call_ic_function6 = + v8_compile("function f(x) { return x - 1; }; f")->Run(); + v8::Handle<Value> value = CompileRun( + "function inc(x) { return x + 1; };" + "inc(1);" + "o.x = inc;" + "function test() {" + " var result = 0;" + " for (var i = 0; i < 1000; i++) {" + " result = o.x(42);" + " }" + " return result;" + "};" + "test();" + "test();" + "test();" + "%OptimizeFunctionOnNextCall(test);" + "test()"); + CHECK_EQ(41, value->Int32Value()); +} + + // Test the case when we stored constant function into // a stub, but it got invalidated later on THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) { @@ -8613,7 +9326,7 @@ static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name, int* call_count = reinterpret_cast<int*>(v8::External::Unwrap(info.Data())); ++(*call_count); if ((*call_count) % 20 == 0) { - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } return v8::Handle<Value>(); } @@ -8769,7 +9482,7 @@ THREADED_TEST(InterceptorCallICFastApi_TrivialSignature) { v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::Handle<Value> value = CompileRun( + CompileRun( "var result = 0;" "for (var i = 0; i < 100; i++) {" " result = o.method(41);" @@ -8796,7 +9509,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature) { v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::Handle<Value> value = CompileRun( + CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" @@ -8826,7 +9539,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) { v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::Handle<Value> value = CompileRun( + CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" @@ -8862,7 +9575,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) { v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::Handle<Value> value = CompileRun( + CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" @@ -8899,7 +9612,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) { GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); v8::TryCatch try_catch; - v8::Handle<Value> value = CompileRun( + CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" @@ -8938,7 +9651,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) { GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); v8::TryCatch try_catch; - v8::Handle<Value> value = CompileRun( + CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" @@ -8967,12 +9680,13 @@ THREADED_TEST(CallICFastApi_TrivialSignature) { v8::Handle<v8::Signature>()); v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); proto_templ->Set(v8_str("method"), method_templ); - v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); + v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate()); + USE(templ); LocalContext context; v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::Handle<Value> value = CompileRun( + CompileRun( "var result = 0;" "for (var i = 0; i < 100; i++) {" " result = o.method(41);" @@ -8990,12 +9704,13 @@ THREADED_TEST(CallICFastApi_SimpleSignature) { v8::Signature::New(fun_templ)); v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); proto_templ->Set(v8_str("method"), method_templ); - v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); + v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate()); + CHECK(!templ.IsEmpty()); LocalContext context; v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::Handle<Value> value = CompileRun( + CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" @@ -9016,12 +9731,13 @@ THREADED_TEST(CallICFastApi_SimpleSignature_Miss1) { v8::Signature::New(fun_templ)); v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); proto_templ->Set(v8_str("method"), method_templ); - v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); + v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate()); + CHECK(!templ.IsEmpty()); LocalContext context; v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); - v8::Handle<Value> value = CompileRun( + CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" @@ -9047,13 +9763,14 @@ THREADED_TEST(CallICFastApi_SimpleSignature_Miss2) { v8::Signature::New(fun_templ)); v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); proto_templ->Set(v8_str("method"), method_templ); - v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate(); + v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate()); + CHECK(!templ.IsEmpty()); LocalContext context; v8::Handle<v8::Function> fun = fun_templ->GetFunction(); GenerateSomeGarbage(); context->Global()->Set(v8_str("o"), fun->NewInstance()); v8::TryCatch try_catch; - v8::Handle<Value> value = CompileRun( + CompileRun( "o.foo = 17;" "var receiver = {};" "receiver.__proto__ = o;" @@ -9093,7 +9810,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChange1) { templ->SetNamedPropertyHandler(NoBlockGetterX); LocalContext context; context->Global()->Set(v8_str("o"), templ->NewInstance()); - v8::Handle<Value> value = CompileRun( + CompileRun( "proto = new Object();" "proto.y = function(x) { return x + 1; };" "proto.z = function(x) { return x - 1; };" @@ -9119,7 +9836,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChange2) { context->Global()->Set(v8_str("proto1"), templ->NewInstance()); keyed_call_ic_function = v8_compile("function f(x) { return x - 1; }; f")->Run(); - v8::Handle<Value> value = CompileRun( + CompileRun( "o = new Object();" "proto2 = new Object();" "o.y = function(x) { return x + 1; };" @@ -9144,7 +9861,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) { templ->SetNamedPropertyHandler(NoBlockGetterX); LocalContext context; context->Global()->Set(v8_str("o"), templ->NewInstance()); - v8::Handle<Value> value = CompileRun( + CompileRun( "function inc(x) { return x + 1; };" "inc(1);" "function dec(x) { return x - 1; };" @@ -9170,7 +9887,7 @@ THREADED_TEST(InterceptorKeyedCallICFromGlobal) { LocalContext context; context->Global()->Set(v8_str("o"), templ_o->NewInstance()); - v8::Handle<Value> value = CompileRun( + CompileRun( "function len(x) { return x.length; };" "o.__proto__ = this;" "var m = 'parseFloat';" @@ -9194,7 +9911,7 @@ THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) { LocalContext context; context->Global()->Set(v8_str("proto"), templ_o->NewInstance()); - v8::Handle<Value> value = CompileRun( + CompileRun( "var o = new Object();" "o.__proto__ = proto;" "o.method = function(x) { return x + 1; };" @@ -9216,7 +9933,7 @@ THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) { LocalContext context; context->Global()->Set(v8_str("o"), templ_o->NewInstance()); - v8::Handle<Value> value = CompileRun( + CompileRun( "var proto = new Object();" "o.__proto__ = proto;" "proto.method = function(x) { return x + 1; };" @@ -9737,7 +10454,7 @@ void ApiTestFuzzer::Run() { static unsigned linear_congruential_generator; -void ApiTestFuzzer::Setup(PartOfTest part) { +void ApiTestFuzzer::SetUp(PartOfTest part) { linear_congruential_generator = i::FLAG_testing_prng_seed; fuzzing_ = true; int count = RegisterThreadedTest::count(); @@ -9801,25 +10518,25 @@ void ApiTestFuzzer::TearDown() { // Lets not be needlessly self-referential. TEST(Threading) { - ApiTestFuzzer::Setup(ApiTestFuzzer::FIRST_PART); + ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART); ApiTestFuzzer::RunAllTests(); ApiTestFuzzer::TearDown(); } TEST(Threading2) { - ApiTestFuzzer::Setup(ApiTestFuzzer::SECOND_PART); + ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART); ApiTestFuzzer::RunAllTests(); ApiTestFuzzer::TearDown(); } TEST(Threading3) { - ApiTestFuzzer::Setup(ApiTestFuzzer::THIRD_PART); + ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART); ApiTestFuzzer::RunAllTests(); ApiTestFuzzer::TearDown(); } TEST(Threading4) { - ApiTestFuzzer::Setup(ApiTestFuzzer::FOURTH_PART); + ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART); ApiTestFuzzer::RunAllTests(); ApiTestFuzzer::TearDown(); } @@ -9964,6 +10681,7 @@ THREADED_TEST(LockUnlockLock) { static int GetGlobalObjectsCount() { + i::Isolate::Current()->heap()->EnsureHeapIsIterable(); int count = 0; i::HeapIterator it; for (i::HeapObject* object = it.next(); object != NULL; object = it.next()) @@ -9978,9 +10696,8 @@ static void CheckSurvivingGlobalObjectsCount(int expected) { // the first garbage collection but some of the maps have already // been marked at that point. Therefore some of the maps are not // collected until the second garbage collection. - HEAP->global_context_map(); - HEAP->CollectAllGarbage(false); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); int count = GetGlobalObjectsCount(); #ifdef DEBUG if (count != expected) HEAP->TracePathToGlobal(); @@ -10049,7 +10766,7 @@ THREADED_TEST(NewPersistentHandleFromWeakCallback) { // weak callback of the first handle would be able to 'reallocate' it. handle1.MakeWeak(NULL, NewPersistentHandleCallback); handle2.Dispose(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -10057,7 +10774,7 @@ v8::Persistent<v8::Object> to_be_disposed; void DisposeAndForceGcCallback(v8::Persistent<v8::Value> handle, void*) { to_be_disposed.Dispose(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); handle.Dispose(); } @@ -10073,7 +10790,7 @@ THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) { } handle1.MakeWeak(NULL, DisposeAndForceGcCallback); to_be_disposed = handle2; - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } void DisposingCallback(v8::Persistent<v8::Value> handle, void*) { @@ -10099,7 +10816,7 @@ THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) { } handle2.MakeWeak(NULL, DisposingCallback); handle3.MakeWeak(NULL, HandleCreatingCallback); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -10141,7 +10858,8 @@ THREADED_TEST(NestedHandleScopeAndContexts) { v8::Persistent<Context> env = Context::New(); env->Enter(); v8::Handle<Value> value = NestedScope(env); - v8::Handle<String> str = value->ToString(); + v8::Handle<String> str(value->ToString()); + CHECK(!str.IsEmpty()); env->Exit(); env.Dispose(); } @@ -10149,7 +10867,8 @@ THREADED_TEST(NestedHandleScopeAndContexts) { THREADED_TEST(ExternalAllocatedMemory) { v8::HandleScope outer; - v8::Persistent<Context> env = Context::New(); + v8::Persistent<Context> env(Context::New()); + CHECK(!env.IsEmpty()); const int kSize = 1024*1024; CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(kSize), kSize); CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(-kSize), 0); @@ -10487,7 +11206,8 @@ THREADED_TEST(AccessControlRepeatedContextCreation) { i::Handle<i::FunctionTemplateInfo> constructor( i::FunctionTemplateInfo::cast(internal_template->constructor())); CHECK(!constructor->access_check_info()->IsUndefined()); - v8::Persistent<Context> context0 = Context::New(NULL, global_template); + v8::Persistent<Context> context0(Context::New(NULL, global_template)); + CHECK(!context0.IsEmpty()); CHECK(!constructor->access_check_info()->IsUndefined()); } @@ -10557,14 +11277,18 @@ THREADED_TEST(TurnOnAccessCheck) { } -v8::Handle<v8::String> a; -v8::Handle<v8::String> h; +static const char* kPropertyA = "a"; +static const char* kPropertyH = "h"; static bool NamedGetAccessBlockAandH(Local<v8::Object> obj, Local<Value> name, v8::AccessType type, Local<Value> data) { - return !(name->Equals(a) || name->Equals(h)); + if (!name->IsString()) return false; + i::Handle<i::String> name_handle = + v8::Utils::OpenHandle(String::Cast(*name)); + return !name_handle->IsEqualTo(i::CStrVector(kPropertyA)) + && !name_handle->IsEqualTo(i::CStrVector(kPropertyH)); } @@ -10573,9 +11297,7 @@ THREADED_TEST(TurnOnAccessCheckAndRecompile) { // Create an environment with access check to the global object disabled by // default. When the registered access checker will block access to properties - // a and h - a = v8_str("a"); - h = v8_str("h"); + // a and h. v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(); global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH, IndexedGetAccessBlocker, @@ -10915,7 +11637,7 @@ class RegExpInterruptTest { { v8::Locker lock; // TODO(lrn): Perhaps create some garbage before collecting. - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); gc_count_++; } i::OS::Sleep(1); @@ -11037,7 +11759,7 @@ class ApplyInterruptTest { while (gc_during_apply_ < kRequiredGCs) { { v8::Locker lock; - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); gc_count_++; } i::OS::Sleep(1); @@ -11187,6 +11909,7 @@ static void MorphAString(i::String* string, // Test that we can still flatten a string if the components it is built up // from have been turned into 16 bit strings in the mean time. THREADED_TEST(MorphCompositeStringTest) { + char utf_buffer[129]; const char* c_string = "Now is the time for all good men" " to come to the aid of the party"; uint16_t* two_byte_string = AsciiToTwoByteString(c_string); @@ -11212,9 +11935,23 @@ THREADED_TEST(MorphCompositeStringTest) { "var slice = lhs.substring(1, lhs.length - 1);" "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);"); + CHECK(!lhs->MayContainNonAscii()); + CHECK(!rhs->MayContainNonAscii()); + MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource); MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource); + // This should UTF-8 without flattening, since everything is ASCII. + Handle<String> cons = v8_compile("cons")->Run().As<String>(); + CHECK_EQ(128, cons->Utf8Length()); + int nchars = -1; + CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars)); + CHECK_EQ(128, nchars); + CHECK_EQ(0, strcmp( + utf_buffer, + "Now is the time for all good men to come to the aid of the party" + "Now is the time for all good men to come to the aid of the party")); + // Now do some stuff to make sure the strings are flattened, etc. CompileRun( "/[^a-z]/.test(cons);" @@ -11666,7 +12403,7 @@ THREADED_TEST(GetCallingContext) { callback_templ->GetFunction()); calling_context0->Exit(); - // Expose context0 in context1 and setup a function that calls the + // Expose context0 in context1 and set up a function that calls the // callback function. calling_context1->Enter(); calling_context1->Global()->Set(v8_str("context0"), @@ -11753,13 +12490,15 @@ THREADED_TEST(PixelArray) { i::Handle<i::ExternalPixelArray> pixels = i::Handle<i::ExternalPixelArray>::cast( FACTORY->NewExternalArray(kElementCount, - v8::kExternalPixelArray, - pixel_data)); - HEAP->CollectAllGarbage(false); // Force GC to trigger verification. + v8::kExternalPixelArray, + pixel_data)); + // Force GC to trigger verification. + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); for (int i = 0; i < kElementCount; i++) { pixels->set(i, i % 256); } - HEAP->CollectAllGarbage(false); // Force GC to trigger verification. + // Force GC to trigger verification. + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); for (int i = 0; i < kElementCount; i++) { CHECK_EQ(i % 256, pixels->get_scalar(i)); CHECK_EQ(i % 256, pixel_data[i]); @@ -11822,18 +12561,21 @@ THREADED_TEST(PixelArray) { i::Handle<i::Smi> value(i::Smi::FromInt(2)); i::Handle<i::Object> no_failure; - no_failure = i::SetElement(jsobj, 1, value, i::kNonStrictMode); + no_failure = + i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode); ASSERT(!no_failure.is_null()); i::USE(no_failure); CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); *value.location() = i::Smi::FromInt(256); - no_failure = i::SetElement(jsobj, 1, value, i::kNonStrictMode); + no_failure = + i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode); ASSERT(!no_failure.is_null()); i::USE(no_failure); CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); *value.location() = i::Smi::FromInt(-1); - no_failure = i::SetElement(jsobj, 1, value, i::kNonStrictMode); + no_failure = + i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode); ASSERT(!no_failure.is_null()); i::USE(no_failure); CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); @@ -12235,11 +12977,13 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, i::Handle<ExternalArrayClass> array = i::Handle<ExternalArrayClass>::cast( FACTORY->NewExternalArray(kElementCount, array_type, array_data)); - HEAP->CollectAllGarbage(false); // Force GC to trigger verification. + // Force GC to trigger verification. + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); for (int i = 0; i < kElementCount; i++) { array->set(i, static_cast<ElementType>(i)); } - HEAP->CollectAllGarbage(false); // Force GC to trigger verification. + // Force GC to trigger verification. + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); for (int i = 0; i < kElementCount; i++) { CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array->get_scalar(i))); @@ -12357,7 +13101,8 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, " }" "}" "sum;"); - HEAP->CollectAllGarbage(false); // Force GC to trigger verification. + // Force GC to trigger verification. + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(28, result->Int32Value()); // Make sure out-of-range loads do not throw. @@ -12392,8 +13137,15 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, "}" "ext_array[7];"); CHECK_EQ(0, result->Int32Value()); - CHECK_EQ( - 0, static_cast<int>(jsobj->GetElement(7)->ToObjectChecked()->Number())); + if (array_type == v8::kExternalDoubleArray || + array_type == v8::kExternalFloatArray) { + CHECK_EQ( + static_cast<int>(i::OS::nan_value()), + static_cast<int>(jsobj->GetElement(7)->ToObjectChecked()->Number())); + } else { + CHECK_EQ(0, static_cast<int>( + jsobj->GetElement(7)->ToObjectChecked()->Number())); + } result = CompileRun("for (var i = 0; i < 8; i++) {" " ext_array[6] = '2.3';" @@ -12546,11 +13298,6 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, const int kLargeElementCount = kXSize * kYSize * 4; ElementType* large_array_data = static_cast<ElementType*>(malloc(kLargeElementCount * element_size)); - i::Handle<ExternalArrayClass> large_array = - i::Handle<ExternalArrayClass>::cast( - FACTORY->NewExternalArray(kLargeElementCount, - array_type, - array_data)); v8::Handle<v8::Object> large_obj = v8::Object::New(); // Set the elements to be the external array. large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data, @@ -12949,10 +13696,10 @@ TEST(CaptureStackTrace) { "}\n" "var x;eval('new foo();');"; v8::Handle<v8::String> overview_src = v8::String::New(overview_source); - v8::Handle<Value> overview_result = - v8::Script::New(overview_src, origin)->Run(); - ASSERT(!overview_result.IsEmpty()); - ASSERT(overview_result->IsObject()); + v8::Handle<Value> overview_result( + v8::Script::New(overview_src, origin)->Run()); + CHECK(!overview_result.IsEmpty()); + CHECK(overview_result->IsObject()); // Test getting DETAILED information. const char *detailed_source = @@ -12970,9 +13717,9 @@ TEST(CaptureStackTrace) { v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset); v8::Handle<v8::Script> detailed_script( v8::Script::New(detailed_src, &detailed_origin)); - v8::Handle<Value> detailed_result = detailed_script->Run(); - ASSERT(!detailed_result.IsEmpty()); - ASSERT(detailed_result->IsObject()); + v8::Handle<Value> detailed_result(detailed_script->Run()); + CHECK(!detailed_result.IsEmpty()); + CHECK(detailed_result->IsObject()); } @@ -13030,6 +13777,137 @@ TEST(CaptureStackTraceForUncaughtExceptionAndSetters) { } +static void RethrowStackTraceHandler(v8::Handle<v8::Message> message, + v8::Handle<v8::Value> data) { + // Use the frame where JavaScript is called from. + v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace(); + CHECK(!stack_trace.IsEmpty()); + int frame_count = stack_trace->GetFrameCount(); + CHECK_EQ(3, frame_count); + int line_number[] = {1, 2, 5}; + for (int i = 0; i < frame_count; i++) { + CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber()); + } +} + + +// Test that we only return the stack trace at the site where the exception +// is first thrown (not where it is rethrown). +TEST(RethrowStackTrace) { + v8::HandleScope scope; + LocalContext env; + // We make sure that + // - the stack trace of the ReferenceError in g() is reported. + // - the stack trace is not overwritten when e1 is rethrown by t(). + // - the stack trace of e2 does not overwrite that of e1. + const char* source = + "function g() { error; } \n" + "function f() { g(); } \n" + "function t(e) { throw e; } \n" + "try { \n" + " f(); \n" + "} catch (e1) { \n" + " try { \n" + " error; \n" + " } catch (e2) { \n" + " t(e1); \n" + " } \n" + "} \n"; + v8::V8::AddMessageListener(RethrowStackTraceHandler); + v8::V8::SetCaptureStackTraceForUncaughtExceptions(true); + CompileRun(source); + v8::V8::SetCaptureStackTraceForUncaughtExceptions(false); + v8::V8::RemoveMessageListeners(RethrowStackTraceHandler); +} + + +static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message, + v8::Handle<v8::Value> data) { + v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace(); + CHECK(!stack_trace.IsEmpty()); + int frame_count = stack_trace->GetFrameCount(); + CHECK_EQ(2, frame_count); + int line_number[] = {3, 7}; + for (int i = 0; i < frame_count; i++) { + CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber()); + } +} + + +// Test that we do not recognize identity for primitive exceptions. +TEST(RethrowPrimitiveStackTrace) { + v8::HandleScope scope; + LocalContext env; + // We do not capture stack trace for non Error objects on creation time. + // Instead, we capture the stack trace on last throw. + const char* source = + "function g() { throw 404; } \n" + "function f() { g(); } \n" + "function t(e) { throw e; } \n" + "try { \n" + " f(); \n" + "} catch (e1) { \n" + " t(e1) \n" + "} \n"; + v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler); + v8::V8::SetCaptureStackTraceForUncaughtExceptions(true); + CompileRun(source); + v8::V8::SetCaptureStackTraceForUncaughtExceptions(false); + v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler); +} + + +static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message, + v8::Handle<v8::Value> data) { + // Use the frame where JavaScript is called from. + v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace(); + CHECK(!stack_trace.IsEmpty()); + CHECK_EQ(1, stack_trace->GetFrameCount()); + CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber()); +} + + +// Test that the stack trace is captured when the error object is created and +// not where it is thrown. +TEST(RethrowExistingStackTrace) { + v8::HandleScope scope; + LocalContext env; + const char* source = + "var e = new Error(); \n" + "throw e; \n"; + v8::V8::AddMessageListener(RethrowExistingStackTraceHandler); + v8::V8::SetCaptureStackTraceForUncaughtExceptions(true); + CompileRun(source); + v8::V8::SetCaptureStackTraceForUncaughtExceptions(false); + v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler); +} + + +static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message, + v8::Handle<v8::Value> data) { + // Use the frame where JavaScript is called from. + v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace(); + CHECK(!stack_trace.IsEmpty()); + CHECK_EQ(1, stack_trace->GetFrameCount()); + CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber()); +} + + +// Test that the stack trace is captured where the bogus Error object is thrown. +TEST(RethrowBogusErrorStackTrace) { + v8::HandleScope scope; + LocalContext env; + const char* source = + "var e = {__proto__: new Error()} \n" + "throw e; \n"; + v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler); + v8::V8::SetCaptureStackTraceForUncaughtExceptions(true); + CompileRun(source); + v8::V8::SetCaptureStackTraceForUncaughtExceptions(false); + v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler); +} + + v8::Handle<Value> AnalyzeStackOfEvalWithSourceURL(const v8::Arguments& args) { v8::HandleScope scope; v8::Handle<v8::StackTrace> stackTrace = @@ -13070,14 +13948,71 @@ TEST(SourceURLInStackTrace) { // Test that idle notification can be handled and eventually returns true. +// This just checks the contract of the IdleNotification() function, +// and does not verify that it does reasonable work. THREADED_TEST(IdleNotification) { - bool rv = false; - for (int i = 0; i < 100; i++) { - rv = v8::V8::IdleNotification(); - if (rv) - break; + v8::HandleScope scope; + LocalContext env; + { + // Create garbage in old-space to generate work for idle notification. + i::AlwaysAllocateScope always_allocate; + for (int i = 0; i < 100; i++) { + FACTORY->NewFixedArray(1000, i::TENURED); + } } - CHECK(rv == true); + bool finshed_idle_work = false; + for (int i = 0; i < 100 && !finshed_idle_work; i++) { + finshed_idle_work = v8::V8::IdleNotification(); + } + CHECK(finshed_idle_work); +} + +// Test that idle notification can be handled and eventually returns true. +// This just checks the contract of the IdleNotification() function, +// and does not verify that it does reasonable work. +TEST(IdleNotificationWithSmallHint) { + v8::HandleScope scope; + LocalContext env; + { + // Create garbage in old-space to generate work for idle notification. + i::AlwaysAllocateScope always_allocate; + for (int i = 0; i < 100; i++) { + FACTORY->NewFixedArray(1000, i::TENURED); + } + } + intptr_t old_size = HEAP->SizeOfObjects(); + bool finshed_idle_work = false; + bool no_idle_work = v8::V8::IdleNotification(10); + for (int i = 0; i < 200 && !finshed_idle_work; i++) { + finshed_idle_work = v8::V8::IdleNotification(10); + } + intptr_t new_size = HEAP->SizeOfObjects(); + CHECK(finshed_idle_work); + CHECK(no_idle_work || new_size < old_size); +} + + +// This just checks the contract of the IdleNotification() function, +// and does not verify that it does reasonable work. +TEST(IdleNotificationWithLargeHint) { + v8::HandleScope scope; + LocalContext env; + { + // Create garbage in old-space to generate work for idle notification. + i::AlwaysAllocateScope always_allocate; + for (int i = 0; i < 100; i++) { + FACTORY->NewFixedArray(1000, i::TENURED); + } + } + intptr_t old_size = HEAP->SizeOfObjects(); + bool finshed_idle_work = false; + bool no_idle_work = v8::V8::IdleNotification(900); + for (int i = 0; i < 200 && !finshed_idle_work; i++) { + finshed_idle_work = v8::V8::IdleNotification(900); + } + intptr_t new_size = HEAP->SizeOfObjects(); + CHECK(finshed_idle_work); + CHECK(no_idle_work || new_size < old_size); } @@ -13168,6 +14103,63 @@ THREADED_TEST(GetHeapStatistics) { } +class VisitorImpl : public v8::ExternalResourceVisitor { + public: + VisitorImpl(TestResource* r1, TestResource* r2) + : resource1_(r1), + resource2_(r2), + found_resource1_(false), + found_resource2_(false) {} + virtual ~VisitorImpl() {} + virtual void VisitExternalString(v8::Handle<v8::String> string) { + if (!string->IsExternal()) { + CHECK(string->IsExternalAscii()); + return; + } + v8::String::ExternalStringResource* resource = + string->GetExternalStringResource(); + CHECK(resource); + if (resource1_ == resource) { + CHECK(!found_resource1_); + found_resource1_ = true; + } + if (resource2_ == resource) { + CHECK(!found_resource2_); + found_resource2_ = true; + } + } + void CheckVisitedResources() { + CHECK(found_resource1_); + CHECK(found_resource2_); + } + + private: + v8::String::ExternalStringResource* resource1_; + v8::String::ExternalStringResource* resource2_; + bool found_resource1_; + bool found_resource2_; +}; + +TEST(VisitExternalStrings) { + v8::HandleScope scope; + LocalContext env; + const char* string = "Some string"; + uint16_t* two_byte_string = AsciiToTwoByteString(string); + TestResource* resource1 = new TestResource(two_byte_string); + v8::Local<v8::String> string1 = v8::String::NewExternal(resource1); + TestResource* resource2 = new TestResource(two_byte_string); + v8::Local<v8::String> string2 = v8::String::NewExternal(resource2); + + // We need to add usages for string1 and string2 to avoid warnings in GCC 4.7 + CHECK(string1->IsExternal()); + CHECK(string2->IsExternal()); + + VisitorImpl visitor(resource1, resource2); + v8::V8::VisitExternalResources(&visitor); + visitor.CheckVisitedResources(); +} + + static double DoubleFromBits(uint64_t value) { double target; memcpy(&target, &value, sizeof(target)); @@ -13250,7 +14242,13 @@ THREADED_TEST(QuietSignalingNaNs) { } else { uint64_t stored_bits = DoubleToBits(stored_number); // Check if quiet nan (bits 51..62 all set). +#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR) + // Most significant fraction bit for quiet nan is set to 0 + // on MIPS architecture. Allowed by IEEE-754. + CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff)); +#else CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff)); +#endif } // Check that Date::New preserves non-NaNs in the date range and @@ -13263,7 +14261,13 @@ THREADED_TEST(QuietSignalingNaNs) { } else { uint64_t stored_bits = DoubleToBits(stored_date); // Check if quiet nan (bits 51..62 all set). +#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR) + // Most significant fraction bit for quiet nan is set to 0 + // on MIPS architecture. Allowed by IEEE-754. + CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff)); +#else CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff)); +#endif } } } @@ -13272,7 +14276,8 @@ THREADED_TEST(QuietSignalingNaNs) { static v8::Handle<Value> SpaghettiIncident(const v8::Arguments& args) { v8::HandleScope scope; v8::TryCatch tc; - v8::Handle<v8::String> str = args[0]->ToString(); + v8::Handle<v8::String> str(args[0]->ToString()); + USE(str); if (tc.HasCaught()) return tc.ReThrow(); return v8::Undefined(); @@ -13337,7 +14342,7 @@ TEST(Regress528) { other_context->Enter(); CompileRun(source_simple); other_context->Exit(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); if (GetGlobalObjectsCount() == 1) break; } CHECK_GE(2, gc_count); @@ -13359,7 +14364,7 @@ TEST(Regress528) { other_context->Enter(); CompileRun(source_eval); other_context->Exit(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); if (GetGlobalObjectsCount() == 1) break; } CHECK_GE(2, gc_count); @@ -13386,7 +14391,7 @@ TEST(Regress528) { other_context->Enter(); CompileRun(source_exception); other_context->Exit(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); if (GetGlobalObjectsCount() == 1) break; } CHECK_GE(2, gc_count); @@ -13417,6 +14422,17 @@ THREADED_TEST(ScriptOrigin) { CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value()); } +THREADED_TEST(FunctionGetInferredName) { + v8::HandleScope scope; + LocalContext env; + v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test")); + v8::Handle<v8::String> script = v8::String::New( + "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;"); + v8::Script::Compile(script, &origin)->Run(); + v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast( + env->Global()->Get(v8::String::New("f"))); + CHECK_EQ("foo.bar.baz", *v8::String::AsciiValue(f->GetInferredName())); +} THREADED_TEST(ScriptLineNumber) { v8::HandleScope scope; @@ -13434,6 +14450,41 @@ THREADED_TEST(ScriptLineNumber) { } +THREADED_TEST(ScriptColumnNumber) { + v8::HandleScope scope; + LocalContext env; + v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"), + v8::Integer::New(3), v8::Integer::New(2)); + v8::Handle<v8::String> script = v8::String::New( + "function foo() {}\n\n function bar() {}"); + v8::Script::Compile(script, &origin)->Run(); + v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast( + env->Global()->Get(v8::String::New("foo"))); + v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast( + env->Global()->Get(v8::String::New("bar"))); + CHECK_EQ(14, foo->GetScriptColumnNumber()); + CHECK_EQ(17, bar->GetScriptColumnNumber()); +} + + +THREADED_TEST(FunctionGetScriptId) { + v8::HandleScope scope; + LocalContext env; + v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"), + v8::Integer::New(3), v8::Integer::New(2)); + v8::Handle<v8::String> scriptSource = v8::String::New( + "function foo() {}\n\n function bar() {}"); + v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin)); + script->Run(); + v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast( + env->Global()->Get(v8::String::New("foo"))); + v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast( + env->Global()->Get(v8::String::New("bar"))); + CHECK_EQ(script->Id(), foo->GetScriptId()); + CHECK_EQ(script->Id(), bar->GetScriptId()); +} + + static v8::Handle<Value> GetterWhichReturns42(Local<String> name, const AccessorInfo& info) { return v8_num(42); @@ -13604,26 +14655,26 @@ TEST(GCCallbacks) { v8::V8::AddGCEpilogueCallback(EpilogueCallback); CHECK_EQ(0, prologue_call_count); CHECK_EQ(0, epilogue_call_count); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(1, prologue_call_count); CHECK_EQ(1, epilogue_call_count); v8::V8::AddGCPrologueCallback(PrologueCallbackSecond); v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(2, prologue_call_count); CHECK_EQ(2, epilogue_call_count); CHECK_EQ(1, prologue_call_count_second); CHECK_EQ(1, epilogue_call_count_second); v8::V8::RemoveGCPrologueCallback(PrologueCallback); v8::V8::RemoveGCEpilogueCallback(EpilogueCallback); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(2, prologue_call_count); CHECK_EQ(2, epilogue_call_count); CHECK_EQ(2, prologue_call_count_second); CHECK_EQ(2, epilogue_call_count_second); v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond); v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK_EQ(2, prologue_call_count); CHECK_EQ(2, epilogue_call_count); CHECK_EQ(2, prologue_call_count_second); @@ -13694,7 +14745,7 @@ THREADED_TEST(RoundRobinGetFromCache) { " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);" " for (var i = 0; i < 16; i++) {" " var v = %_GetFromCache(0, keys[i]);" - " if (v !== values[i])" + " if (v.toString() !== values[i].toString())" " return 'Wrong value for ' + " " keys[i] + ': ' + v + ' vs. ' + values[i];" " };" @@ -13840,7 +14891,7 @@ THREADED_TEST(TwoByteStringInAsciiCons) { void FailedAccessCheckCallbackGC(Local<v8::Object> target, v8::AccessType type, Local<v8::Value> data) { - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -14414,7 +15465,7 @@ TEST(DontDeleteCellLoadIC) { "})()", "ReferenceError: cell is not defined"); CompileRun("cell = \"new_second\";"); - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); ExpectString("readCell()", "new_second"); ExpectString("readCell()", "new_second"); } @@ -14535,8 +15586,8 @@ TEST(RegExp) { // RegExps are objects on which you can set properties. re->Set(v8_str("property"), v8::Integer::New(32)); - v8::Handle<v8::Value> value = CompileRun("re.property"); - ASSERT_EQ(32, value->Int32Value()); + v8::Handle<v8::Value> value(CompileRun("re.property")); + CHECK_EQ(32, value->Int32Value()); v8::TryCatch try_catch; re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone); @@ -14887,10 +15938,12 @@ THREADED_TEST(AllowCodeGenFromStrings) { LocalContext context; // eval and the Function constructor allowed by default. + CHECK(context->IsCodeGenerationFromStringsAllowed()); CheckCodeGenerationAllowed(); // Disallow eval and the Function constructor. context->AllowCodeGenerationFromStrings(false); + CHECK(!context->IsCodeGenerationFromStringsAllowed()); CheckCodeGenerationDisallowed(); // Allow again. @@ -14900,10 +15953,12 @@ THREADED_TEST(AllowCodeGenFromStrings) { // Disallow but setting a global callback that will allow the calls. context->AllowCodeGenerationFromStrings(false); V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed); + CHECK(!context->IsCodeGenerationFromStringsAllowed()); CheckCodeGenerationAllowed(); // Set a callback that disallows the code generation. V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed); + CHECK(!context->IsCodeGenerationFromStringsAllowed()); CheckCodeGenerationDisallowed(); } @@ -15182,3 +16237,167 @@ THREADED_TEST(ForeignFunctionReceiver) { foreign_context.Dispose(); } + + +uint8_t callback_fired = 0; + + +void CallCompletedCallback1() { + i::OS::Print("Firing callback 1.\n"); + callback_fired ^= 1; // Toggle first bit. +} + + +void CallCompletedCallback2() { + i::OS::Print("Firing callback 2.\n"); + callback_fired ^= 2; // Toggle second bit. +} + + +Handle<Value> RecursiveCall(const Arguments& args) { + int32_t level = args[0]->Int32Value(); + if (level < 3) { + level++; + i::OS::Print("Entering recursion level %d.\n", level); + char script[64]; + i::Vector<char> script_vector(script, sizeof(script)); + i::OS::SNPrintF(script_vector, "recursion(%d)", level); + CompileRun(script_vector.start()); + i::OS::Print("Leaving recursion level %d.\n", level); + CHECK_EQ(0, callback_fired); + } else { + i::OS::Print("Recursion ends.\n"); + CHECK_EQ(0, callback_fired); + } + return Undefined(); +} + + +TEST(CallCompletedCallback) { + v8::HandleScope scope; + LocalContext env; + v8::Handle<v8::FunctionTemplate> recursive_runtime = + v8::FunctionTemplate::New(RecursiveCall); + env->Global()->Set(v8_str("recursion"), + recursive_runtime->GetFunction()); + // Adding the same callback a second time has no effect. + v8::V8::AddCallCompletedCallback(CallCompletedCallback1); + v8::V8::AddCallCompletedCallback(CallCompletedCallback1); + v8::V8::AddCallCompletedCallback(CallCompletedCallback2); + i::OS::Print("--- Script (1) ---\n"); + Local<Script> script = + v8::Script::Compile(v8::String::New("recursion(0)")); + script->Run(); + CHECK_EQ(3, callback_fired); + + i::OS::Print("\n--- Script (2) ---\n"); + callback_fired = 0; + v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1); + script->Run(); + CHECK_EQ(2, callback_fired); + + i::OS::Print("\n--- Function ---\n"); + callback_fired = 0; + Local<Function> recursive_function = + Local<Function>::Cast(env->Global()->Get(v8_str("recursion"))); + v8::Handle<Value> args[] = { v8_num(0) }; + recursive_function->Call(env->Global(), 1, args); + CHECK_EQ(2, callback_fired); +} + + +void CallCompletedCallbackNoException() { + v8::HandleScope scope; + CompileRun("1+1;"); +} + + +void CallCompletedCallbackException() { + v8::HandleScope scope; + CompileRun("throw 'second exception';"); +} + + +TEST(CallCompletedCallbackOneException) { + v8::HandleScope scope; + LocalContext env; + v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException); + CompileRun("throw 'exception';"); +} + + +TEST(CallCompletedCallbackTwoExceptions) { + v8::HandleScope scope; + LocalContext env; + v8::V8::AddCallCompletedCallback(CallCompletedCallbackException); + CompileRun("throw 'first exception';"); +} + + +static int probes_counter = 0; +static int misses_counter = 0; +static int updates_counter = 0; + + +static int* LookupCounter(const char* name) { + if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) { + return &probes_counter; + } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) { + return &misses_counter; + } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) { + return &updates_counter; + } + return NULL; +} + + +static const char* kMegamorphicTestProgram = + "function ClassA() { };" + "function ClassB() { };" + "ClassA.prototype.foo = function() { };" + "ClassB.prototype.foo = function() { };" + "function fooify(obj) { obj.foo(); };" + "var a = new ClassA();" + "var b = new ClassB();" + "for (var i = 0; i < 10000; i++) {" + " fooify(a);" + " fooify(b);" + "}"; + + +static void StubCacheHelper(bool primary) { + V8::SetCounterFunction(LookupCounter); + USE(kMegamorphicTestProgram); +#ifdef DEBUG + i::FLAG_native_code_counters = true; + if (primary) { + i::FLAG_test_primary_stub_cache = true; + } else { + i::FLAG_test_secondary_stub_cache = true; + } + i::FLAG_crankshaft = false; + v8::HandleScope scope; + LocalContext env; + int initial_probes = probes_counter; + int initial_misses = misses_counter; + int initial_updates = updates_counter; + CompileRun(kMegamorphicTestProgram); + int probes = probes_counter - initial_probes; + int misses = misses_counter - initial_misses; + int updates = updates_counter - initial_updates; + CHECK_LT(updates, 10); + CHECK_LT(misses, 10); + CHECK_GE(probes, 10000); +#endif +} + + +TEST(SecondaryStubCache) { + StubCacheHelper(true); +} + + +TEST(PrimaryStubCache) { + StubCacheHelper(false); +} + diff --git a/test/cctest/test-assembler-ia32.cc b/test/cctest/test-assembler-ia32.cc index 839b7f56..815e6184 100644 --- a/test/cctest/test-assembler-ia32.cc +++ b/test/cctest/test-assembler-ia32.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -93,15 +93,15 @@ TEST(AssemblerIa321) { Label L, C; __ mov(edx, Operand(esp, 4)); - __ xor_(eax, Operand(eax)); // clear eax + __ xor_(eax, eax); // clear eax __ jmp(&C); __ bind(&L); - __ add(eax, Operand(edx)); - __ sub(Operand(edx), Immediate(1)); + __ add(eax, edx); + __ sub(edx, Immediate(1)); __ bind(&C); - __ test(edx, Operand(edx)); + __ test(edx, edx); __ j(not_zero, &L); __ ret(0); @@ -135,11 +135,11 @@ TEST(AssemblerIa322) { __ jmp(&C); __ bind(&L); - __ imul(eax, Operand(edx)); - __ sub(Operand(edx), Immediate(1)); + __ imul(eax, edx); + __ sub(edx, Immediate(1)); __ bind(&C); - __ test(edx, Operand(edx)); + __ test(edx, edx); __ j(not_zero, &L); __ ret(0); @@ -275,10 +275,10 @@ TEST(AssemblerIa326) { __ subsd(xmm0, xmm1); __ divsd(xmm0, xmm1); // Copy xmm0 to st(0) using eight bytes of stack. - __ sub(Operand(esp), Immediate(8)); + __ sub(esp, Immediate(8)); __ movdbl(Operand(esp, 0), xmm0); __ fld_d(Operand(esp, 0)); - __ add(Operand(esp), Immediate(8)); + __ add(esp, Immediate(8)); __ ret(0); CodeDesc desc; @@ -314,12 +314,12 @@ TEST(AssemblerIa328) { v8::internal::byte buffer[256]; Assembler assm(Isolate::Current(), buffer, sizeof buffer); __ mov(eax, Operand(esp, 4)); - __ cvtsi2sd(xmm0, Operand(eax)); + __ cvtsi2sd(xmm0, eax); // Copy xmm0 to st(0) using eight bytes of stack. - __ sub(Operand(esp), Immediate(8)); + __ sub(esp, Immediate(8)); __ movdbl(Operand(esp, 0), xmm0); __ fld_d(Operand(esp, 0)); - __ add(Operand(esp), Immediate(8)); + __ add(esp, Immediate(8)); __ ret(0); CodeDesc desc; assm.GetCode(&desc); @@ -408,4 +408,72 @@ TEST(AssemblerIa3210) { __ nop(); } + +TEST(AssemblerMultiByteNop) { + InitializeVM(); + v8::HandleScope scope; + v8::internal::byte buffer[1024]; + Assembler assm(Isolate::Current(), buffer, sizeof(buffer)); + __ push(ebx); + __ push(ecx); + __ push(edx); + __ push(edi); + __ push(esi); + __ mov(eax, 1); + __ mov(ebx, 2); + __ mov(ecx, 3); + __ mov(edx, 4); + __ mov(edi, 5); + __ mov(esi, 6); + for (int i = 0; i < 16; i++) { + int before = assm.pc_offset(); + __ Nop(i); + CHECK_EQ(assm.pc_offset() - before, i); + } + + Label fail; + __ cmp(eax, 1); + __ j(not_equal, &fail); + __ cmp(ebx, 2); + __ j(not_equal, &fail); + __ cmp(ecx, 3); + __ j(not_equal, &fail); + __ cmp(edx, 4); + __ j(not_equal, &fail); + __ cmp(edi, 5); + __ j(not_equal, &fail); + __ cmp(esi, 6); + __ j(not_equal, &fail); + __ mov(eax, 42); + __ pop(esi); + __ pop(edi); + __ pop(edx); + __ pop(ecx); + __ pop(ebx); + __ ret(0); + __ bind(&fail); + __ mov(eax, 13); + __ pop(esi); + __ pop(edi); + __ pop(edx); + __ pop(ecx); + __ pop(ebx); + __ ret(0); + + CodeDesc desc; + assm.GetCode(&desc); + Code* code = Code::cast(HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked()); + CHECK(code->IsCode()); + + F0 f = FUNCTION_CAST<F0>(code->entry()); + int res = f(); + CHECK_EQ(42, res); +} + + + + #undef __ diff --git a/test/cctest/test-assembler-mips.cc b/test/cctest/test-assembler-mips.cc index a6c76f03..6985433d 100644 --- a/test/cctest/test-assembler-mips.cc +++ b/test/cctest/test-assembler-mips.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// 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: @@ -219,21 +219,21 @@ TEST(MIPS2) { // Bit twiddling instructions & conditional moves. // Uses t0-t7 as set above. - __ clz(v0, t0); // 29 - __ clz(v1, t1); // 19 + __ Clz(v0, t0); // 29 + __ Clz(v1, t1); // 19 __ addu(v0, v0, v1); // 48 - __ clz(v1, t2); // 3 + __ Clz(v1, t2); // 3 __ addu(v0, v0, v1); // 51 - __ clz(v1, t7); // 0 + __ Clz(v1, t7); // 0 __ addu(v0, v0, v1); // 51 __ Branch(&error, ne, v0, Operand(51)); - __ movn(a0, t3, t0); // Move a0<-t3 (t0 is NOT 0). + __ Movn(a0, t3, t0); // Move a0<-t3 (t0 is NOT 0). __ Ins(a0, t1, 12, 8); // 0x7ff34fff __ Branch(&error, ne, a0, Operand(0x7ff34fff)); - __ movz(a0, t6, t7); // a0 not updated (t7 is NOT 0). + __ Movz(a0, t6, t7); // a0 not updated (t7 is NOT 0). __ Ext(a1, a0, 8, 12); // 0x34f __ Branch(&error, ne, a1, Operand(0x34f)); - __ movz(a0, t6, v1); // a0<-t6, v0 is 0, from 8 instr back. + __ Movz(a0, t6, v1); // a0<-t6, v0 is 0, from 8 instr back. __ Branch(&error, ne, a0, Operand(t6)); // Everything was correctly executed. Load the expected result. @@ -579,8 +579,13 @@ TEST(MIPS7) { __ bind(&neither_is_nan); - __ c(OLT, D, f6, f4, 2); - __ bc1t(&less_than, 2); + if (kArchVariant == kLoongson) { + __ c(OLT, D, f6, f4); + __ bc1t(&less_than); + } else { + __ c(OLT, D, f6, f4, 2); + __ bc1t(&less_than, 2); + } __ nop(); __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); __ Branch(&outa_here); @@ -774,7 +779,7 @@ TEST(MIPS10) { Assembler assm(Isolate::Current(), NULL, 0); Label L, C; - if (CpuFeatures::IsSupported(FPU) && mips32r2) { + if (CpuFeatures::IsSupported(FPU) && kArchVariant == kMips32r2) { CpuFeatures::Scope scope(FPU); // Load all structure elements to registers. diff --git a/test/cctest/test-assembler-x64.cc b/test/cctest/test-assembler-x64.cc index 28f7c9b7..d81923fa 100644 --- a/test/cctest/test-assembler-x64.cc +++ b/test/cctest/test-assembler-x64.cc @@ -36,6 +36,7 @@ #include "cctest.h" using v8::internal::Assembler; +using v8::internal::Code; using v8::internal::CodeDesc; using v8::internal::FUNCTION_CAST; using v8::internal::Immediate; @@ -53,6 +54,7 @@ using v8::internal::r15; using v8::internal::r8; using v8::internal::r9; using v8::internal::rax; +using v8::internal::rbx; using v8::internal::rbp; using v8::internal::rcx; using v8::internal::rdi; @@ -86,8 +88,18 @@ static const v8::internal::Register arg2 = rsi; #define __ assm. +static v8::Persistent<v8::Context> env; + + +static void InitializeVM() { + if (env.IsEmpty()) { + env = v8::Context::New(); + } +} + + TEST(AssemblerX64ReturnOperation) { - OS::Setup(); + OS::SetUp(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -109,7 +121,7 @@ TEST(AssemblerX64ReturnOperation) { } TEST(AssemblerX64StackOperations) { - OS::Setup(); + OS::SetUp(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -141,7 +153,7 @@ TEST(AssemblerX64StackOperations) { } TEST(AssemblerX64ArithmeticOperations) { - OS::Setup(); + OS::SetUp(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -163,7 +175,7 @@ TEST(AssemblerX64ArithmeticOperations) { } TEST(AssemblerX64ImulOperation) { - OS::Setup(); + OS::SetUp(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -191,7 +203,7 @@ TEST(AssemblerX64ImulOperation) { } TEST(AssemblerX64MemoryOperands) { - OS::Setup(); + OS::SetUp(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -225,7 +237,7 @@ TEST(AssemblerX64MemoryOperands) { } TEST(AssemblerX64ControlFlow) { - OS::Setup(); + OS::SetUp(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -254,7 +266,7 @@ TEST(AssemblerX64ControlFlow) { } TEST(AssemblerX64LoopImmediates) { - OS::Setup(); + OS::SetUp(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -359,4 +371,73 @@ TEST(AssemblerX64LabelChaining) { __ nop(); } + +TEST(AssemblerMultiByteNop) { + InitializeVM(); + v8::HandleScope scope; + v8::internal::byte buffer[1024]; + Assembler assm(Isolate::Current(), buffer, sizeof(buffer)); + __ push(rbx); + __ push(rcx); + __ push(rdx); + __ push(rdi); + __ push(rsi); + __ movq(rax, Immediate(1)); + __ movq(rbx, Immediate(2)); + __ movq(rcx, Immediate(3)); + __ movq(rdx, Immediate(4)); + __ movq(rdi, Immediate(5)); + __ movq(rsi, Immediate(6)); + for (int i = 0; i < 16; i++) { + int before = assm.pc_offset(); + __ Nop(i); + CHECK_EQ(assm.pc_offset() - before, i); + } + + Label fail; + __ cmpq(rax, Immediate(1)); + __ j(not_equal, &fail); + __ cmpq(rbx, Immediate(2)); + __ j(not_equal, &fail); + __ cmpq(rcx, Immediate(3)); + __ j(not_equal, &fail); + __ cmpq(rdx, Immediate(4)); + __ j(not_equal, &fail); + __ cmpq(rdi, Immediate(5)); + __ j(not_equal, &fail); + __ cmpq(rsi, Immediate(6)); + __ j(not_equal, &fail); + __ movq(rax, Immediate(42)); + __ pop(rsi); + __ pop(rdi); + __ pop(rdx); + __ pop(rcx); + __ pop(rbx); + __ ret(0); + __ bind(&fail); + __ movq(rax, Immediate(13)); + __ pop(rsi); + __ pop(rdi); + __ pop(rdx); + __ pop(rcx); + __ pop(rbx); + __ ret(0); + + CodeDesc desc; + assm.GetCode(&desc); + Code* code = Code::cast(HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + v8::internal::Handle<v8::internal::Object>( + HEAP->undefined_value()))->ToObjectChecked()); + CHECK(code->IsCode()); + + F0 f = FUNCTION_CAST<F0>(code->entry()); + int res = f(); + CHECK_EQ(42, res); +} + + + + #undef __ diff --git a/test/cctest/test-ast.cc b/test/cctest/test-ast.cc index 2aa72078..80c7fdff 100644 --- a/test/cctest/test-ast.cc +++ b/test/cctest/test-ast.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// 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: @@ -40,7 +40,8 @@ TEST(List) { CHECK_EQ(0, list->length()); ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); - AstNode* node = new(ZONE) EmptyStatement(); + AstNodeFactory<AstNullVisitor> factory(Isolate::Current()); + AstNode* node = factory.NewEmptyStatement(); list->Add(node); CHECK_EQ(1, list->length()); CHECK_EQ(node, list->at(0)); diff --git a/test/cctest/test-compiler.cc b/test/cctest/test-compiler.cc index 2d9b0120..9ca0b0a1 100644 --- a/test/cctest/test-compiler.cc +++ b/test/cctest/test-compiler.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// 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: @@ -270,8 +270,7 @@ TEST(UncaughtThrow) { CHECK(!fun.is_null()); bool has_pending_exception; Handle<JSObject> global(Isolate::Current()->context()->global()); - Handle<Object> result = - Execution::Call(fun, global, 0, NULL, &has_pending_exception); + Execution::Call(fun, global, 0, NULL, &has_pending_exception); CHECK(has_pending_exception); CHECK_EQ(42.0, Isolate::Current()->pending_exception()-> ToObjectChecked()->Number()); @@ -305,10 +304,11 @@ TEST(C2JSFrames) { Handle<Object> fun1(fun1_object->ToObjectChecked()); CHECK(fun1->IsJSFunction()); - Object** argv[1] = { - Handle<Object>::cast(FACTORY->LookupAsciiSymbol("hello")).location() - }; - Execution::Call(Handle<JSFunction>::cast(fun1), global, 1, argv, + Handle<Object> argv[] = { FACTORY->LookupAsciiSymbol("hello") }; + Execution::Call(Handle<JSFunction>::cast(fun1), + global, + ARRAY_SIZE(argv), + argv, &has_pending_exception); CHECK(!has_pending_exception); } diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc index f567a0f7..b10e6889 100644 --- a/test/cctest/test-cpu-profiler.cc +++ b/test/cctest/test-cpu-profiler.cc @@ -216,7 +216,7 @@ TEST(TickEvents) { TEST(CrashIfStoppingLastNonExistentProfile) { InitializeVM(); TestSetup test_setup; - CpuProfiler::Setup(); + CpuProfiler::SetUp(); CpuProfiler::StartProfiling("1"); CpuProfiler::StopProfiling("2"); CpuProfiler::StartProfiling("1"); @@ -268,7 +268,7 @@ TEST(Issue1398) { TEST(DeleteAllCpuProfiles) { InitializeVM(); TestSetup test_setup; - CpuProfiler::Setup(); + CpuProfiler::SetUp(); CHECK_EQ(0, CpuProfiler::GetProfilesCount()); CpuProfiler::DeleteAllProfiles(); CHECK_EQ(0, CpuProfiler::GetProfilesCount()); diff --git a/test/cctest/test-dataflow.cc b/test/cctest/test-dataflow.cc index ad48f550..a63008d2 100644 --- a/test/cctest/test-dataflow.cc +++ b/test/cctest/test-dataflow.cc @@ -1,4 +1,4 @@ -// Copyright 2010 the V8 project authors. All rights reserved. +// 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: @@ -36,16 +36,17 @@ using namespace v8::internal; TEST(BitVector) { v8::internal::V8::Initialize(NULL); - ZoneScope zone(Isolate::Current(), DELETE_ON_EXIT); + ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); + Zone* zone = ZONE; { - BitVector v(15); + BitVector v(15, zone); v.Add(1); CHECK(v.Contains(1)); v.Remove(0); CHECK(!v.Contains(0)); v.Add(0); v.Add(1); - BitVector w(15); + BitVector w(15, zone); w.Add(1); v.Intersect(w); CHECK(!v.Contains(0)); @@ -53,7 +54,7 @@ TEST(BitVector) { } { - BitVector v(64); + BitVector v(64, zone); v.Add(27); v.Add(30); v.Add(31); @@ -71,9 +72,9 @@ TEST(BitVector) { } { - BitVector v(15); + BitVector v(15, zone); v.Add(0); - BitVector w(15); + BitVector w(15, zone); w.Add(1); v.Union(w); CHECK(v.Contains(0)); @@ -81,13 +82,13 @@ TEST(BitVector) { } { - BitVector v(15); + BitVector v(15, zone); v.Add(0); - BitVector w(15); + BitVector w(15, zone); w = v; CHECK(w.Contains(0)); w.Add(1); - BitVector u(w); + BitVector u(w, zone); CHECK(u.Contains(0)); CHECK(u.Contains(1)); v.Union(w); @@ -96,9 +97,9 @@ TEST(BitVector) { } { - BitVector v(35); + BitVector v(35, zone); v.Add(0); - BitVector w(35); + BitVector w(35, zone); w.Add(33); v.Union(w); CHECK(v.Contains(0)); @@ -106,15 +107,15 @@ TEST(BitVector) { } { - BitVector v(35); + BitVector v(35, zone); v.Add(32); v.Add(33); - BitVector w(35); + BitVector w(35, zone); w.Add(33); v.Intersect(w); CHECK(!v.Contains(32)); CHECK(v.Contains(33)); - BitVector r(35); + BitVector r(35, zone); r.CopyFrom(v); CHECK(!r.Contains(32)); CHECK(r.Contains(33)); diff --git a/test/cctest/test-date.cc b/test/cctest/test-date.cc new file mode 100644 index 00000000..903a63a5 --- /dev/null +++ b/test/cctest/test-date.cc @@ -0,0 +1,168 @@ +// 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. + +#include "v8.h" + +#include "global-handles.h" +#include "snapshot.h" +#include "cctest.h" + +using namespace v8::internal; + +class DateCacheMock: public DateCache { + public: + struct Rule { + int year, start_month, start_day, end_month, end_day, offset_sec; + }; + + DateCacheMock(int local_offset, Rule* rules, int rules_count) + : local_offset_(local_offset), rules_(rules), rules_count_(rules_count) {} + + protected: + virtual int GetDaylightSavingsOffsetFromOS(int64_t time_sec) { + int days = DaysFromTime(time_sec * 1000); + int time_in_day_sec = TimeInDay(time_sec * 1000, days) / 1000; + int year, month, day; + YearMonthDayFromDays(days, &year, &month, &day); + Rule* rule = FindRuleFor(year, month, day, time_in_day_sec); + return rule == NULL ? 0 : rule->offset_sec * 1000; + } + + + virtual int GetLocalOffsetFromOS() { + return local_offset_; + } + + private: + Rule* FindRuleFor(int year, int month, int day, int time_in_day_sec) { + Rule* result = NULL; + for (int i = 0; i < rules_count_; i++) + if (Match(&rules_[i], year, month, day, time_in_day_sec)) { + result = &rules_[i]; + } + return result; + } + + + bool Match(Rule* rule, int year, int month, int day, int time_in_day_sec) { + if (rule->year != 0 && rule->year != year) return false; + if (rule->start_month > month) return false; + if (rule->end_month < month) return false; + int start_day = ComputeRuleDay(year, rule->start_month, rule->start_day); + if (rule->start_month == month && start_day > day) return false; + if (rule->start_month == month && start_day == day && + 2 * 3600 > time_in_day_sec) + return false; + int end_day = ComputeRuleDay(year, rule->end_month, rule->end_day); + if (rule->end_month == month && end_day < day) return false; + if (rule->end_month == month && end_day == day && + 2 * 3600 <= time_in_day_sec) + return false; + return true; + } + + + int ComputeRuleDay(int year, int month, int day) { + if (day != 0) return day; + int days = DaysFromYearMonth(year, month); + // Find the first Sunday of the month. + while (Weekday(days + day) != 6) day++; + return day + 1; + } + + int local_offset_; + Rule* rules_; + int rules_count_; +}; + +static int64_t TimeFromYearMonthDay(DateCache* date_cache, + int year, + int month, + int day) { + int64_t result = date_cache->DaysFromYearMonth(year, month); + return (result + day - 1) * DateCache::kMsPerDay; +} + +static void CheckDST(int64_t time) { + Isolate* isolate = Isolate::Current(); + DateCache* date_cache = isolate->date_cache(); + int64_t actual = date_cache->ToLocal(time); + int64_t expected = time + date_cache->GetLocalOffsetFromOS() + + date_cache->GetDaylightSavingsOffsetFromOS(time / 1000); + CHECK_EQ(actual, expected); +} + + +TEST(DaylightSavingsTime) { + LocalContext context; + v8::HandleScope scope; + Isolate* isolate = Isolate::Current(); + DateCacheMock::Rule rules[] = { + {0, 2, 0, 10, 0, 3600}, // DST from March to November in any year. + {2010, 2, 0, 7, 20, 3600}, // DST from March to August 20 in 2010. + {2010, 7, 20, 8, 10, 0}, // No DST from August 20 to September 10 in 2010. + {2010, 8, 10, 10, 0, 3600}, // DST from September 10 to November in 2010. + }; + + int local_offset_ms = -36000000; // -10 hours. + + DateCacheMock* date_cache = + new DateCacheMock(local_offset_ms, rules, ARRAY_SIZE(rules)); + + isolate->set_date_cache(date_cache); + + int64_t start_of_2010 = TimeFromYearMonthDay(date_cache, 2010, 0, 1); + int64_t start_of_2011 = TimeFromYearMonthDay(date_cache, 2011, 0, 1); + int64_t august_20 = TimeFromYearMonthDay(date_cache, 2010, 7, 20); + int64_t september_10 = TimeFromYearMonthDay(date_cache, 2010, 8, 10); + CheckDST((august_20 + september_10) / 2); + CheckDST(september_10); + CheckDST(september_10 + 2 * 3600); + CheckDST(september_10 + 2 * 3600 - 1000); + CheckDST(august_20 + 2 * 3600); + CheckDST(august_20 + 2 * 3600 - 1000); + CheckDST(august_20); + // Check each day of 2010. + for (int64_t time = start_of_2011 + 2 * 3600; + time >= start_of_2010; + time -= DateCache::kMsPerDay) { + CheckDST(time); + CheckDST(time - 1000); + CheckDST(time + 1000); + } + // Check one day from 2010 to 2100. + for (int year = 2100; year >= 2010; year--) { + CheckDST(TimeFromYearMonthDay(date_cache, year, 5, 5)); + } + CheckDST((august_20 + september_10) / 2); + CheckDST(september_10); + CheckDST(september_10 + 2 * 3600); + CheckDST(september_10 + 2 * 3600 - 1000); + CheckDST(august_20 + 2 * 3600); + CheckDST(august_20 + 2 * 3600 - 1000); + CheckDST(august_20); +} diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc index 45da6dc0..ffa84581 100644 --- a/test/cctest/test-debug.cc +++ b/test/cctest/test-debug.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// 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: @@ -409,11 +409,8 @@ Handle<FixedArray> GetDebuggedFunctions() { static Handle<Code> ComputeCallDebugBreak(int argc) { - CALL_HEAP_FUNCTION( - v8::internal::Isolate::Current(), - v8::internal::Isolate::Current()->stub_cache()->ComputeCallDebugBreak( - argc, Code::CALL_IC), - Code); + return Isolate::Current()->stub_cache()->ComputeCallDebugBreak(argc, + Code::CALL_IC); } @@ -425,8 +422,8 @@ void CheckDebuggerUnloaded(bool check_functions) { CHECK_EQ(NULL, Isolate::Current()->debug()->debug_info_list_); // Collect garbage to ensure weak handles are cleared. - HEAP->CollectAllGarbage(false); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask); // Iterate the head and check that there are no debugger related objects left. HeapIterator iterator; @@ -859,7 +856,7 @@ static void DebugEventRemoveBreakPoint(v8::DebugEvent event, if (event == v8::Break) { break_point_hit_count++; - v8::Handle<v8::Function> fun = v8::Handle<v8::Function>::Cast(data); + CHECK(data->IsFunction()); ClearBreakPoint(debug_event_remove_break_point); } } @@ -944,7 +941,7 @@ static void DebugEventBreakPointCollectGarbage( HEAP->CollectGarbage(v8::internal::NEW_SPACE); } else { // Mark sweep compact. - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); } } } @@ -1417,8 +1414,7 @@ TEST(GCDuringBreakPointProcessing) { // Call the function three times with different garbage collections in between // and make sure that the break point survives. static void CallAndGC(v8::Local<v8::Object> recv, - v8::Local<v8::Function> f, - bool force_compaction) { + v8::Local<v8::Function> f) { break_point_hit_count = 0; for (int i = 0; i < 3; i++) { @@ -1432,14 +1428,15 @@ static void CallAndGC(v8::Local<v8::Object> recv, CHECK_EQ(2 + i * 3, break_point_hit_count); // Mark sweep (and perhaps compact) and call function. - HEAP->CollectAllGarbage(force_compaction); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); f->Call(recv, 0, NULL); CHECK_EQ(3 + i * 3, break_point_hit_count); } } -static void TestBreakPointSurviveGC(bool force_compaction) { +// Test that a break point can be set at a return store location. +TEST(BreakPointSurviveGC) { break_point_hit_count = 0; v8::HandleScope scope; DebugLocalContext env; @@ -1450,50 +1447,45 @@ static void TestBreakPointSurviveGC(bool force_compaction) { // Test IC store break point with garbage collection. { - v8::Local<v8::Function> bar = - CompileFunction(&env, "function foo(){}", "foo"); + CompileFunction(&env, "function foo(){}", "foo"); foo = CompileFunction(&env, "function foo(){bar=0;}", "foo"); SetBreakPoint(foo, 0); } - CallAndGC(env->Global(), foo, force_compaction); + CallAndGC(env->Global(), foo); // Test IC load break point with garbage collection. { - v8::Local<v8::Function> bar = - CompileFunction(&env, "function foo(){}", "foo"); + CompileFunction(&env, "function foo(){}", "foo"); foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo"); SetBreakPoint(foo, 0); } - CallAndGC(env->Global(), foo, force_compaction); + CallAndGC(env->Global(), foo); // Test IC call break point with garbage collection. { - v8::Local<v8::Function> bar = - CompileFunction(&env, "function foo(){}", "foo"); + CompileFunction(&env, "function foo(){}", "foo"); foo = CompileFunction(&env, "function bar(){};function foo(){bar();}", "foo"); SetBreakPoint(foo, 0); } - CallAndGC(env->Global(), foo, force_compaction); + CallAndGC(env->Global(), foo); // Test return break point with garbage collection. { - v8::Local<v8::Function> bar = - CompileFunction(&env, "function foo(){}", "foo"); + CompileFunction(&env, "function foo(){}", "foo"); foo = CompileFunction(&env, "function foo(){}", "foo"); SetBreakPoint(foo, 0); } - CallAndGC(env->Global(), foo, force_compaction); + CallAndGC(env->Global(), foo); // Test non IC break point with garbage collection. { - v8::Local<v8::Function> bar = - CompileFunction(&env, "function foo(){}", "foo"); + CompileFunction(&env, "function foo(){}", "foo"); foo = CompileFunction(&env, "function foo(){var bar=0;}", "foo"); SetBreakPoint(foo, 0); } - CallAndGC(env->Global(), foo, force_compaction); + CallAndGC(env->Global(), foo); v8::Debug::SetDebugEventListener(NULL); @@ -1501,13 +1493,6 @@ static void TestBreakPointSurviveGC(bool force_compaction) { } -// Test that a break point can be set at a return store location. -TEST(BreakPointSurviveGC) { - TestBreakPointSurviveGC(false); - TestBreakPointSurviveGC(true); -} - - // Test that break points can be set using the global Debug object. TEST(BreakPointThroughJavaScript) { break_point_hit_count = 0; @@ -2259,7 +2244,7 @@ TEST(ScriptBreakPointLineTopLevel) { } f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f"))); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); SetScriptBreakPointByNameFromJS("test.html", 3, -1); @@ -2753,14 +2738,14 @@ TEST(DebugStepKeyedLoadLoop) { v8::Handle<v8::Value> args[kArgc] = { a }; foo->Call(env->Global(), kArgc, args); - // Setup break point and step through the function. + // Set up break point and step through the function. SetBreakPoint(foo, 3); step_action = StepNext; break_point_hit_count = 0; foo->Call(env->Global(), kArgc, args); // With stepping all break locations are hit. - CHECK_EQ(33, break_point_hit_count); + CHECK_EQ(34, break_point_hit_count); v8::Debug::SetDebugEventListener(NULL); CheckDebuggerUnloaded(); @@ -2800,14 +2785,14 @@ TEST(DebugStepKeyedStoreLoop) { v8::Handle<v8::Value> args[kArgc] = { a }; foo->Call(env->Global(), kArgc, args); - // Setup break point and step through the function. + // Set up break point and step through the function. SetBreakPoint(foo, 3); step_action = StepNext; break_point_hit_count = 0; foo->Call(env->Global(), kArgc, args); // With stepping all break locations are hit. - CHECK_EQ(32, break_point_hit_count); + CHECK_EQ(33, break_point_hit_count); v8::Debug::SetDebugEventListener(NULL); CheckDebuggerUnloaded(); @@ -2844,14 +2829,14 @@ TEST(DebugStepNamedLoadLoop) { // Call function without any break points to ensure inlining is in place. foo->Call(env->Global(), 0, NULL); - // Setup break point and step through the function. + // Set up break point and step through the function. SetBreakPoint(foo, 4); step_action = StepNext; break_point_hit_count = 0; foo->Call(env->Global(), 0, NULL); // With stepping all break locations are hit. - CHECK_EQ(53, break_point_hit_count); + CHECK_EQ(54, break_point_hit_count); v8::Debug::SetDebugEventListener(NULL); CheckDebuggerUnloaded(); @@ -2879,7 +2864,7 @@ static void DoDebugStepNamedStoreLoop(int expected) { // Call function without any break points to ensure inlining is in place. foo->Call(env->Global(), 0, NULL); - // Setup break point and step through the function. + // Set up break point and step through the function. SetBreakPoint(foo, 3); step_action = StepNext; break_point_hit_count = 0; @@ -2895,7 +2880,7 @@ static void DoDebugStepNamedStoreLoop(int expected) { // Test of the stepping mechanism for named load in a loop. TEST(DebugStepNamedStoreLoop) { - DoDebugStepNamedStoreLoop(22); + DoDebugStepNamedStoreLoop(23); } @@ -3267,7 +3252,7 @@ TEST(DebugStepForContinue) { v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) }; result = foo->Call(env->Global(), argc, argv_10); CHECK_EQ(5, result->Int32Value()); - CHECK_EQ(50, break_point_hit_count); + CHECK_EQ(51, break_point_hit_count); // Looping 100 times. step_action = StepIn; @@ -3275,7 +3260,7 @@ TEST(DebugStepForContinue) { v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) }; result = foo->Call(env->Global(), argc, argv_100); CHECK_EQ(50, result->Int32Value()); - CHECK_EQ(455, break_point_hit_count); + CHECK_EQ(456, break_point_hit_count); // Get rid of the debug event listener. v8::Debug::SetDebugEventListener(NULL); @@ -3319,7 +3304,7 @@ TEST(DebugStepForBreak) { v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) }; result = foo->Call(env->Global(), argc, argv_10); CHECK_EQ(9, result->Int32Value()); - CHECK_EQ(53, break_point_hit_count); + CHECK_EQ(54, break_point_hit_count); // Looping 100 times. step_action = StepIn; @@ -3327,7 +3312,7 @@ TEST(DebugStepForBreak) { v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) }; result = foo->Call(env->Global(), argc, argv_100); CHECK_EQ(99, result->Int32Value()); - CHECK_EQ(503, break_point_hit_count); + CHECK_EQ(504, break_point_hit_count); // Get rid of the debug event listener. v8::Debug::SetDebugEventListener(NULL); @@ -3761,8 +3746,7 @@ TEST(BreakOnException) { v8::internal::Isolate::Current()->TraceException(false); // Create functions for testing break on exception. - v8::Local<v8::Function> throws = - CompileFunction(&env, "function throws(){throw 1;}", "throws"); + CompileFunction(&env, "function throws(){throw 1;}", "throws"); v8::Local<v8::Function> caught = CompileFunction(&env, "function caught(){try {throws();} catch(e) {};}", @@ -4238,9 +4222,9 @@ TEST(InterceptorPropertyMirror) { // Get mirrors for the three objects with interceptor. CompileRun( - "named_mirror = debug.MakeMirror(intercepted_named);" - "indexed_mirror = debug.MakeMirror(intercepted_indexed);" - "both_mirror = debug.MakeMirror(intercepted_both)"); + "var named_mirror = debug.MakeMirror(intercepted_named);" + "var indexed_mirror = debug.MakeMirror(intercepted_indexed);" + "var both_mirror = debug.MakeMirror(intercepted_both)"); CHECK(CompileRun( "named_mirror instanceof debug.ObjectMirror")->BooleanValue()); CHECK(CompileRun( @@ -4281,7 +4265,7 @@ TEST(InterceptorPropertyMirror) { CHECK_EQ(5, CompileRun(source)->Int32Value()); // Get the interceptor properties for the object with only named interceptor. - CompileRun("named_values = named_mirror.properties()"); + CompileRun("var named_values = named_mirror.properties()"); // Check that the properties are interceptor properties. for (int i = 0; i < 3; i++) { @@ -4300,7 +4284,7 @@ TEST(InterceptorPropertyMirror) { // Get the interceptor properties for the object with only indexed // interceptor. - CompileRun("indexed_values = indexed_mirror.properties()"); + CompileRun("var indexed_values = indexed_mirror.properties()"); // Check that the properties are interceptor properties. for (int i = 0; i < 2; i++) { @@ -4312,7 +4296,7 @@ TEST(InterceptorPropertyMirror) { // Get the interceptor properties for the object with both types of // interceptors. - CompileRun("both_values = both_mirror.properties()"); + CompileRun("var both_values = both_mirror.properties()"); // Check that the properties are interceptor properties. for (int i = 0; i < 5; i++) { @@ -4368,10 +4352,10 @@ TEST(HiddenPrototypePropertyMirror) { // Get mirrors for the four objects. CompileRun( - "o0_mirror = debug.MakeMirror(o0);" - "o1_mirror = debug.MakeMirror(o1);" - "o2_mirror = debug.MakeMirror(o2);" - "o3_mirror = debug.MakeMirror(o3)"); + "var o0_mirror = debug.MakeMirror(o0);" + "var o1_mirror = debug.MakeMirror(o1);" + "var o2_mirror = debug.MakeMirror(o2);" + "var o3_mirror = debug.MakeMirror(o3)"); CHECK(CompileRun("o0_mirror instanceof debug.ObjectMirror")->BooleanValue()); CHECK(CompileRun("o1_mirror instanceof debug.ObjectMirror")->BooleanValue()); CHECK(CompileRun("o2_mirror instanceof debug.ObjectMirror")->BooleanValue()); @@ -4457,11 +4441,11 @@ TEST(NativeGetterPropertyMirror) { CHECK_EQ(10, CompileRun("instance.x")->Int32Value()); // Get mirror for the object with property getter. - CompileRun("instance_mirror = debug.MakeMirror(instance);"); + CompileRun("var instance_mirror = debug.MakeMirror(instance);"); CHECK(CompileRun( "instance_mirror instanceof debug.ObjectMirror")->BooleanValue()); - CompileRun("named_names = instance_mirror.propertyNames();"); + CompileRun("var named_names = instance_mirror.propertyNames();"); CHECK_EQ(1, CompileRun("named_names.length")->Int32Value()); CHECK(CompileRun("named_names[0] == 'x'")->BooleanValue()); CHECK(CompileRun( @@ -4493,7 +4477,7 @@ TEST(NativeGetterThrowingErrorPropertyMirror) { env->Global()->Set(v8::String::New("instance"), named->NewInstance()); // Get mirror for the object with property getter. - CompileRun("instance_mirror = debug.MakeMirror(instance);"); + CompileRun("var instance_mirror = debug.MakeMirror(instance);"); CHECK(CompileRun( "instance_mirror instanceof debug.ObjectMirror")->BooleanValue()); CompileRun("named_names = instance_mirror.propertyNames();"); @@ -5557,10 +5541,8 @@ TEST(DebuggerUnload) { v8::HandleScope scope; // Get the test functions again. - v8::Local<v8::Function> foo = - v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo"))); - v8::Local<v8::Function> bar = - v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo"))); + v8::Local<v8::Function> foo(v8::Local<v8::Function>::Cast( + env->Global()->Get(v8::String::New("foo")))); foo->Call(env->Global(), 0, NULL); CHECK_EQ(0, break_point_hit_count); @@ -5719,7 +5701,7 @@ void HostDispatchV8Thread::Run() { v8::HandleScope scope; DebugLocalContext env; - // Setup message and host dispatch handlers. + // Set up message and host dispatch handlers. v8::Debug::SetMessageHandler2(HostDispatchMessageHandler); v8::Debug::SetHostDispatchHandler(HostDispatchDispatchHandler, 10 /* ms */); @@ -5807,7 +5789,7 @@ void DebugMessageDispatchV8Thread::Run() { v8::HandleScope scope; DebugLocalContext env; - // Setup debug message dispatch handler. + // Set up debug message dispatch handler. v8::Debug::SetDebugMessageDispatchHandler(DebugMessageHandler); CompileRun("var y = 1 + 2;\n"); @@ -5861,7 +5843,7 @@ TEST(DebuggerAgent) { bool ok; // Initialize the socket library. - i::Socket::Setup(); + i::Socket::SetUp(); // Test starting and stopping the agent without any client connection. debugger->StartAgent("test", kPort1); @@ -5959,7 +5941,7 @@ TEST(DebuggerAgentProtocolOverflowHeader) { OS::SNPrintF(i::Vector<char>(port_str, kPortBufferLen), "%d", kPort); // Initialize the socket library. - i::Socket::Setup(); + i::Socket::SetUp(); // Create a socket server to receive a debugger agent message. DebuggerAgentProtocolServerThread* server = @@ -6037,7 +6019,9 @@ TEST(DebugGetLoadedScripts) { EmptyExternalStringResource source_ext_str; v8::Local<v8::String> source = v8::String::NewExternal(&source_ext_str); - v8::Handle<v8::Script> evil_script = v8::Script::Compile(source); + v8::Handle<v8::Script> evil_script(v8::Script::Compile(source)); + // "use" evil_script to make the compiler happy. + (void) 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 @@ -6472,7 +6456,7 @@ TEST(ScriptCollectedEvent) { // Do garbage collection to ensure that only the script in this test will be // collected afterwards. - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); script_collected_count = 0; v8::Debug::SetDebugEventListener(DebugEventScriptCollectedEvent, @@ -6484,7 +6468,7 @@ TEST(ScriptCollectedEvent) { // Do garbage collection to collect the script above which is no longer // referenced. - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); CHECK_EQ(2, script_collected_count); @@ -6520,7 +6504,7 @@ TEST(ScriptCollectedEventContext) { // Do garbage collection to ensure that only the script in this test will be // collected afterwards. - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); v8::Debug::SetMessageHandler2(ScriptCollectedMessageHandler); { @@ -6531,7 +6515,7 @@ TEST(ScriptCollectedEventContext) { // Do garbage collection to collect the script above which is no longer // referenced. - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); CHECK_EQ(2, script_collected_message_count); @@ -6685,7 +6669,7 @@ static void BreakMessageHandler(const v8::Debug::Message& message) { break_point_hit_count++; v8::HandleScope scope; - v8::Handle<v8::String> json = message.GetJSON(); + message.GetJSON(); SendContinueCommand(); } else if (message.IsEvent() && message.GetEvent() == v8::AfterCompile) { @@ -6696,7 +6680,7 @@ static void BreakMessageHandler(const v8::Debug::Message& message) { isolate->stack_guard()->DebugBreak(); // Force serialization to trigger some internal JS execution. - v8::Handle<v8::String> json = message.GetJSON(); + message.GetJSON(); // Restore previous state. if (is_debug_break) { @@ -6879,7 +6863,7 @@ TEST(DebugBreakFunctionApply) { foo->Call(env->Global(), 0, NULL); // When keeping the debug break several break will happen. - CHECK_EQ(3, break_point_hit_count); + CHECK_GT(break_point_hit_count, 1); v8::Debug::SetDebugEventListener(NULL); CheckDebuggerUnloaded(); @@ -7224,10 +7208,10 @@ static void TestDebugBreakInLoop(const char* loop_head, // Receive 100 breaks for each test and then terminate JavaScript execution. static const int kBreaksPerTest = 100; - for (int i = 0; i < 1 && loop_bodies[i] != NULL; i++) { + for (int i = 0; loop_bodies[i] != NULL; i++) { // Perform a lazy deoptimization after various numbers of breaks // have been hit. - for (int j = 0; j < 10; j++) { + for (int j = 0; j < 11; j++) { break_point_hit_count_deoptimize = j; if (j == 10) { break_point_hit_count_deoptimize = kBreaksPerTest; @@ -7302,4 +7286,65 @@ TEST(DebugBreakLoop) { } +v8::Local<v8::Script> inline_script; + +static void DebugBreakInlineListener(v8::DebugEvent event, + v8::Handle<v8::Object> exec_state, + v8::Handle<v8::Object> event_data, + v8::Handle<v8::Value> data) { + if (event != v8::Break) return; + + int expected_frame_count = 4; + int expected_line_number[] = {1, 4, 7, 12}; + + i::Handle<i::Object> compiled_script = v8::Utils::OpenHandle(*inline_script); + i::Handle<i::Script> source_script = i::Handle<i::Script>(i::Script::cast( + i::JSFunction::cast(*compiled_script)->shared()->script())); + + int break_id = v8::internal::Isolate::Current()->debug()->break_id(); + char script[128]; + i::Vector<char> script_vector(script, sizeof(script)); + OS::SNPrintF(script_vector, "%%GetFrameCount(%d)", break_id); + v8::Local<v8::Value> result = CompileRun(script); + + int frame_count = result->Int32Value(); + CHECK_EQ(expected_frame_count, frame_count); + + for (int i = 0; i < frame_count; i++) { + // The 5. element in the returned array of GetFrameDetails contains the + // source position of that frame. + OS::SNPrintF(script_vector, "%%GetFrameDetails(%d, %d)[5]", break_id, i); + v8::Local<v8::Value> result = CompileRun(script); + CHECK_EQ(expected_line_number[i], + i::GetScriptLineNumber(source_script, result->Int32Value())); + } + v8::Debug::SetDebugEventListener(NULL); + v8::V8::TerminateExecution(); +} + + +TEST(DebugBreakInline) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope scope; + DebugLocalContext env; + const char* source = + "function debug(b) { \n" + " if (b) debugger; \n" + "} \n" + "function f(b) { \n" + " debug(b) \n" + "}; \n" + "function g(b) { \n" + " f(b); \n" + "}; \n" + "g(false); \n" + "g(false); \n" + "%OptimizeFunctionOnNextCall(g); \n" + "g(true);"; + v8::Debug::SetDebugEventListener(DebugBreakInlineListener); + inline_script = v8::Script::Compile(v8::String::New(source)); + inline_script->Run(); +} + + #endif // ENABLE_DEBUGGER_SUPPORT diff --git a/test/cctest/test-decls.cc b/test/cctest/test-decls.cc index 61983918..aa733c70 100644 --- a/test/cctest/test-decls.cc +++ b/test/cctest/test-decls.cc @@ -232,7 +232,7 @@ TEST(Unknown) { context.Check("const x; x", 1, // access 2, // declaration + initialization - 2, // declaration + initialization + 1, // declaration EXPECT_RESULT, Undefined()); } @@ -240,7 +240,7 @@ TEST(Unknown) { context.Check("const x = 0; x", 1, // access 2, // declaration + initialization - 2, // declaration + initialization + 1, // declaration EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579 } } @@ -285,18 +285,18 @@ TEST(Present) { { PresentPropertyContext context; context.Check("const x; x", - 0, - 0, + 1, // access + 1, // initialization 1, // (re-)declaration - EXPECT_EXCEPTION); // x has already been declared! + EXPECT_RESULT, Undefined()); } { PresentPropertyContext context; context.Check("const x = 0; x", - 0, - 0, + 1, // access + 1, // initialization 1, // (re-)declaration - EXPECT_EXCEPTION); // x has already been declared! + EXPECT_RESULT, Number::New(0)); } } @@ -341,7 +341,7 @@ TEST(Absent) { context.Check("const x; x", 1, // access 2, // declaration + initialization - 2, // declaration + initializetion + 1, // declaration EXPECT_RESULT, Undefined()); } @@ -349,7 +349,7 @@ TEST(Absent) { context.Check("const x = 0; x", 1, // access 2, // declaration + initialization - 2, // declaration + initialization + 1, // declaration EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579 } @@ -429,18 +429,20 @@ TEST(Appearing) { { AppearingPropertyContext context; context.Check("const x; x", - 0, - 1, // declaration + 1, // access 2, // declaration + initialization - EXPECT_EXCEPTION); // x has already been declared! + 1, // declaration + EXPECT_RESULT, Undefined()); } { AppearingPropertyContext context; context.Check("const x = 0; x", - 0, - 1, // declaration + 1, // access 2, // declaration + initialization - EXPECT_EXCEPTION); // x has already been declared! + 1, // declaration + EXPECT_RESULT, Undefined()); + // Result is undefined because declaration succeeded but + // initialization to 0 failed (due to context behavior). } } @@ -496,9 +498,9 @@ TEST(Reappearing) { { ReappearingPropertyContext context; context.Check("const x; var x = 0", 0, - 2, // var declaration + const initialization - 4, // 2 x declaration + 2 x initialization - EXPECT_EXCEPTION); // x has already been declared! + 3, // const declaration+initialization, var initialization + 3, // 2 x declaration + var initialization + EXPECT_RESULT, Undefined()); } } diff --git a/test/cctest/test-deoptimization.cc b/test/cctest/test-deoptimization.cc index 056c9818..c52c5788 100644 --- a/test/cctest/test-deoptimization.cc +++ b/test/cctest/test-deoptimization.cc @@ -1,4 +1,4 @@ -// Copyright 2007-2010 the V8 project authors. All rights reserved. +// 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: @@ -97,6 +97,13 @@ class AllowNativesSyntaxNoInlining { }; +// Abort any ongoing incremental marking to make sure that all weak global +// handle callbacks are processed. +static void NonIncrementalGC() { + HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); +} + + static Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj, const char* property_name) { v8::Local<v8::Function> fun = @@ -107,9 +114,7 @@ static Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj, TEST(DeoptimizeSimple) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; // Test lazy deoptimization of a simple function. { @@ -119,9 +124,9 @@ TEST(DeoptimizeSimple) { "function h() { %DeoptimizeFunction(f); }" "function g() { count++; h(); }" "function f() { g(); };" - "f();" - "gc(); gc()"); + "f();"); } + NonIncrementalGC(); CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); @@ -135,9 +140,9 @@ TEST(DeoptimizeSimple) { "var count = 0;" "function g() { count++; %DeoptimizeFunction(f); f(false); }" "function f(x) { if (x) { g(); } else { return } };" - "f(true);" - "gc(); gc()"); + "f(true);"); } + NonIncrementalGC(); CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); @@ -147,9 +152,7 @@ TEST(DeoptimizeSimple) { TEST(DeoptimizeSimpleWithArguments) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; // Test lazy deoptimization of a simple function with some arguments. { @@ -159,9 +162,9 @@ TEST(DeoptimizeSimpleWithArguments) { "function h(x) { %DeoptimizeFunction(f); }" "function g(x, y) { count++; h(x); }" "function f(x, y, z) { g(1,x); y+z; };" - "f(1, \"2\", false);" - "gc(); gc()"); + "f(1, \"2\", false);"); } + NonIncrementalGC(); CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); @@ -176,9 +179,9 @@ TEST(DeoptimizeSimpleWithArguments) { "var count = 0;" "function g(x, y) { count++; %DeoptimizeFunction(f); f(false, 1, y); }" "function f(x, y, z) { if (x) { g(x, y); } else { return y + z; } };" - "f(true, 1, \"2\");" - "gc(); gc()"); + "f(true, 1, \"2\");"); } + NonIncrementalGC(); CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); @@ -188,9 +191,7 @@ TEST(DeoptimizeSimpleWithArguments) { TEST(DeoptimizeSimpleNested) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; // Test lazy deoptimization of a simple function. Have a nested function call // do the deoptimization. @@ -202,8 +203,8 @@ TEST(DeoptimizeSimpleNested) { "function h(x, y, z) { return x + y + z; }" "function g(z) { count++; %DeoptimizeFunction(f); return z;}" "function f(x,y,z) { return h(x, y, g(z)); };" - "result = f(1, 2, 3);" - "gc(); gc()"); + "result = f(1, 2, 3);"); + NonIncrementalGC(); CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(6, env->Global()->Get(v8_str("result"))->Int32Value()); @@ -215,9 +216,7 @@ TEST(DeoptimizeSimpleNested) { TEST(DeoptimizeRecursive) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; { // Test lazy deoptimization of a simple function called recursively. Call @@ -228,8 +227,9 @@ TEST(DeoptimizeRecursive) { "var calls = 0;" "function g() { count++; %DeoptimizeFunction(f); }" "function f(x) { calls++; if (x > 0) { f(x - 1); } else { g(); } };" - "f(10); gc(); gc()"); + "f(10);"); } + NonIncrementalGC(); CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(11, env->Global()->Get(v8_str("calls"))->Int32Value()); @@ -237,15 +237,13 @@ TEST(DeoptimizeRecursive) { v8::Local<v8::Function> fun = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f"))); - Handle<v8::internal::JSFunction> f = v8::Utils::OpenHandle(*fun); + CHECK(!fun.IsEmpty()); } TEST(DeoptimizeMultiple) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; { AlwaysOptimizeAllowNativesSyntaxNoInlining options; @@ -261,9 +259,9 @@ TEST(DeoptimizeMultiple) { "function f3(x, y, z) { f4(); return x + y + z; };" "function f2(x, y) { return x + f3(y + 1, y + 1, y + 1) + y; };" "function f1(x) { return f2(x + 1, x + 1) + x; };" - "result = f1(1);" - "gc(); gc()"); + "result = f1(1);"); } + NonIncrementalGC(); CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(14, env->Global()->Get(v8_str("result"))->Int32Value()); @@ -273,9 +271,7 @@ TEST(DeoptimizeMultiple) { TEST(DeoptimizeConstructor) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; { AlwaysOptimizeAllowNativesSyntaxNoInlining options; @@ -284,9 +280,9 @@ TEST(DeoptimizeConstructor) { "function g() { count++;" " %DeoptimizeFunction(f); }" "function f() { g(); };" - "result = new f() instanceof f;" - "gc(); gc()"); + "result = new f() instanceof f;"); } + NonIncrementalGC(); CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK(env->Global()->Get(v8_str("result"))->IsTrue()); @@ -301,9 +297,9 @@ TEST(DeoptimizeConstructor) { " %DeoptimizeFunction(f); }" "function f(x, y) { this.x = x; g(); this.y = y; };" "result = new f(1, 2);" - "result = result.x + result.y;" - "gc(); gc()"); + "result = result.x + result.y;"); } + NonIncrementalGC(); CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(3, env->Global()->Get(v8_str("result"))->Int32Value()); @@ -313,9 +309,7 @@ TEST(DeoptimizeConstructor) { TEST(DeoptimizeConstructorMultiple) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; { AlwaysOptimizeAllowNativesSyntaxNoInlining options; @@ -332,9 +326,9 @@ TEST(DeoptimizeConstructorMultiple) { "function f2(x, y) {" " this.result = x + new f3(y + 1, y + 1, y + 1).result + y; };" "function f1(x) { this.result = new f2(x + 1, x + 1).result + x; };" - "result = new f1(1).result;" - "gc(); gc()"); + "result = new f1(1).result;"); } + NonIncrementalGC(); CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); CHECK_EQ(14, env->Global()->Get(v8_str("result"))->Int32Value()); @@ -344,9 +338,7 @@ TEST(DeoptimizeConstructorMultiple) { TEST(DeoptimizeBinaryOperationADDString) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; const char* f_source = "function f(x, y) { return x + y; };"; @@ -376,9 +368,9 @@ TEST(DeoptimizeBinaryOperationADDString) { // Call f and force deoptimization while processing the binary operation. CompileRun("deopt = true;" - "var result = f('a+', new X());" - "gc(); gc();"); + "var result = f('a+', new X());"); } + NonIncrementalGC(); CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); @@ -428,18 +420,15 @@ static void TestDeoptimizeBinaryOpHelper(LocalContext* env, // Call f and force deoptimization while processing the binary operation. CompileRun("deopt = true;" - "var result = f(7, new X());" - "gc(); gc();"); - + "var result = f(7, new X());"); + NonIncrementalGC(); CHECK(!GetJSFunction((*env)->Global(), "f")->IsOptimized()); } TEST(DeoptimizeBinaryOperationADD) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; TestDeoptimizeBinaryOpHelper(&env, "+"); @@ -451,9 +440,7 @@ TEST(DeoptimizeBinaryOperationADD) { TEST(DeoptimizeBinaryOperationSUB) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; TestDeoptimizeBinaryOpHelper(&env, "-"); @@ -465,9 +452,7 @@ TEST(DeoptimizeBinaryOperationSUB) { TEST(DeoptimizeBinaryOperationMUL) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; TestDeoptimizeBinaryOpHelper(&env, "*"); @@ -479,9 +464,7 @@ TEST(DeoptimizeBinaryOperationMUL) { TEST(DeoptimizeBinaryOperationDIV) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; TestDeoptimizeBinaryOpHelper(&env, "/"); @@ -493,9 +476,7 @@ TEST(DeoptimizeBinaryOperationDIV) { TEST(DeoptimizeBinaryOperationMOD) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; TestDeoptimizeBinaryOpHelper(&env, "%"); @@ -507,9 +488,7 @@ TEST(DeoptimizeBinaryOperationMOD) { TEST(DeoptimizeCompare) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; const char* f_source = "function f(x, y) { return x < y; };"; @@ -539,9 +518,9 @@ TEST(DeoptimizeCompare) { // Call f and force deoptimization while processing the comparison. CompileRun("deopt = true;" - "var result = f('a', new X());" - "gc(); gc();"); + "var result = f('a', new X());"); } + NonIncrementalGC(); CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); @@ -552,9 +531,7 @@ TEST(DeoptimizeCompare) { TEST(DeoptimizeLoadICStoreIC) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; // Functions to generate load/store/keyed load/keyed store IC calls. const char* f1_source = "function f1(x) { return x.y; };"; @@ -618,9 +595,9 @@ TEST(DeoptimizeLoadICStoreIC) { "var result = f1(new X());" "g1(new X());" "f2(new X(), 'z');" - "g2(new X(), 'z');" - "gc(); gc();"); + "g2(new X(), 'z');"); } + NonIncrementalGC(); CHECK(!GetJSFunction(env->Global(), "f1")->IsOptimized()); CHECK(!GetJSFunction(env->Global(), "g1")->IsOptimized()); @@ -634,9 +611,7 @@ TEST(DeoptimizeLoadICStoreIC) { TEST(DeoptimizeLoadICStoreICNested) { v8::HandleScope scope; - const char* extension_list[] = { "v8/gc" }; - v8::ExtensionConfiguration extensions(1, extension_list); - LocalContext env(&extensions); + LocalContext env; // Functions to generate load/store/keyed load/keyed store IC calls. const char* f1_source = "function f1(x) { return x.y; };"; @@ -701,9 +676,9 @@ TEST(DeoptimizeLoadICStoreICNested) { // Call functions and force deoptimization while processing the ics. CompileRun("deopt = true;" - "var result = f1(new X());" - "gc(); gc();"); + "var result = f1(new X());"); } + NonIncrementalGC(); CHECK(!GetJSFunction(env->Global(), "f1")->IsOptimized()); CHECK(!GetJSFunction(env->Global(), "g1")->IsOptimized()); diff --git a/test/cctest/test-dictionary.cc b/test/cctest/test-dictionary.cc index 15a854b3..793e228a 100644 --- a/test/cctest/test-dictionary.cc +++ b/test/cctest/test-dictionary.cc @@ -38,6 +38,7 @@ using namespace v8::internal; + TEST(ObjectHashTable) { v8::HandleScope scope; LocalContext context; @@ -66,7 +67,8 @@ TEST(ObjectHashTable) { CHECK_EQ(table->NumberOfDeletedElements(), 1); CHECK_EQ(table->Lookup(*a), HEAP->undefined_value()); - // Keys should map back to their respective values. + // Keys should map back to their respective values and also should get + // an identity hash code generated. for (int i = 0; i < 100; i++) { Handle<JSObject> key = FACTORY->NewJSArray(7); Handle<JSObject> value = FACTORY->NewJSArray(11); @@ -74,12 +76,67 @@ TEST(ObjectHashTable) { CHECK_EQ(table->NumberOfElements(), i + 1); CHECK_NE(table->FindEntry(*key), ObjectHashTable::kNotFound); CHECK_EQ(table->Lookup(*key), *value); + CHECK(key->GetIdentityHash(OMIT_CREATION)->ToObjectChecked()->IsSmi()); + } + + // Keys never added to the map which already have an identity hash + // code should not be found. + for (int i = 0; i < 100; i++) { + Handle<JSObject> key = FACTORY->NewJSArray(7); + CHECK(key->GetIdentityHash(ALLOW_CREATION)->ToObjectChecked()->IsSmi()); + CHECK_EQ(table->FindEntry(*key), ObjectHashTable::kNotFound); + CHECK_EQ(table->Lookup(*key), HEAP->undefined_value()); + CHECK(key->GetIdentityHash(OMIT_CREATION)->ToObjectChecked()->IsSmi()); } - // Keys never added to the map should not be found. - for (int i = 0; i < 1000; i++) { - Handle<JSObject> o = FACTORY->NewJSArray(100); - CHECK_EQ(table->FindEntry(*o), ObjectHashTable::kNotFound); - CHECK_EQ(table->Lookup(*o), HEAP->undefined_value()); + // Keys that don't have an identity hash should not be found and also + // should not get an identity hash code generated. + for (int i = 0; i < 100; i++) { + Handle<JSObject> key = FACTORY->NewJSArray(7); + CHECK_EQ(table->Lookup(*key), HEAP->undefined_value()); + CHECK_EQ(key->GetIdentityHash(OMIT_CREATION), HEAP->undefined_value()); } } + + +#ifdef DEBUG +TEST(ObjectHashSetCausesGC) { + v8::HandleScope scope; + LocalContext context; + Handle<ObjectHashSet> table = FACTORY->NewObjectHashSet(1); + Handle<JSObject> key = FACTORY->NewJSArray(0); + + // Simulate a full heap so that generating an identity hash code + // in subsequent calls will request GC. + FLAG_gc_interval = 0; + + // Calling Contains() should not cause GC ever. + CHECK(!table->Contains(*key)); + + // Calling Remove() should not cause GC ever. + CHECK(!table->Remove(*key)->IsFailure()); + + // Calling Add() should request GC by returning a failure. + CHECK(table->Add(*key)->IsRetryAfterGC()); +} +#endif + + +#ifdef DEBUG +TEST(ObjectHashTableCausesGC) { + v8::HandleScope scope; + LocalContext context; + Handle<ObjectHashTable> table = FACTORY->NewObjectHashTable(1); + Handle<JSObject> key = FACTORY->NewJSArray(0); + + // Simulate a full heap so that generating an identity hash code + // in subsequent calls will request GC. + FLAG_gc_interval = 0; + + // Calling Lookup() should not cause GC ever. + CHECK(table->Lookup(*key)->IsUndefined()); + + // Calling Put() should request GC by returning a failure. + CHECK(table->Put(*key, *key)->IsRetryAfterGC()); +} +#endif diff --git a/test/cctest/test-disasm-arm.cc b/test/cctest/test-disasm-arm.cc index 032e6bc0..0e9432d9 100644 --- a/test/cctest/test-disasm-arm.cc +++ b/test/cctest/test-disasm-arm.cc @@ -69,10 +69,10 @@ bool DisassembleAndCompare(byte* pc, const char* compare_string) { } -// Setup V8 to a state where we can at least run the assembler and +// Set up V8 to a state where we can at least run the assembler and // disassembler. Declare the variables and allocate the data structures used // in the rest of the macros. -#define SETUP() \ +#define SET_UP() \ InitializeVM(); \ v8::HandleScope scope; \ byte *buffer = reinterpret_cast<byte*>(malloc(4*1024)); \ @@ -102,7 +102,7 @@ if (failure) { \ TEST(Type0) { - SETUP(); + SET_UP(); COMPARE(and_(r0, r1, Operand(r2)), "e0010002 and r0, r1, r2"); @@ -329,7 +329,7 @@ TEST(Type0) { TEST(Type1) { - SETUP(); + SET_UP(); COMPARE(and_(r0, r1, Operand(0x00000000)), "e2010000 and r0, r1, #0"); @@ -358,7 +358,7 @@ TEST(Type1) { TEST(Type3) { - SETUP(); + SET_UP(); if (CpuFeatures::IsSupported(ARMv7)) { COMPARE(ubfx(r0, r1, 5, 10), @@ -413,7 +413,7 @@ TEST(Type3) { TEST(Vfp) { - SETUP(); + SET_UP(); if (CpuFeatures::IsSupported(VFP3)) { CpuFeatures::Scope scope(VFP3); @@ -546,7 +546,7 @@ TEST(Vfp) { TEST(LoadStore) { - SETUP(); + SET_UP(); COMPARE(ldrb(r0, MemOperand(r1)), "e5d10000 ldrb r0, [r1, #+0]"); diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc index 9f7d0bb6..da095054 100644 --- a/test/cctest/test-disasm-ia32.cc +++ b/test/cctest/test-disasm-ia32.cc @@ -1,4 +1,4 @@ -// Copyright 2007-2008 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -63,9 +63,9 @@ TEST(DisasmIa320) { // Short immediate instructions __ adc(eax, 12345678); - __ add(Operand(eax), Immediate(12345678)); + __ add(eax, Immediate(12345678)); __ or_(eax, 12345678); - __ sub(Operand(eax), Immediate(12345678)); + __ sub(eax, Immediate(12345678)); __ xor_(eax, 12345678); __ and_(eax, 12345678); Handle<FixedArray> foo = FACTORY->NewFixedArray(10, TENURED); @@ -75,7 +75,7 @@ TEST(DisasmIa320) { __ mov(ebx, Operand(esp, ecx, times_2, 0)); // [esp+ecx*4] // ---- All instructions that I can think of - __ add(edx, Operand(ebx)); + __ add(edx, ebx); __ add(edx, Operand(12, RelocInfo::NONE)); __ add(edx, Operand(ebx, 0)); __ add(edx, Operand(ebx, 16)); @@ -89,7 +89,7 @@ TEST(DisasmIa320) { __ add(Operand(ebp, ecx, times_4, 12), Immediate(12)); __ nop(); - __ add(Operand(ebx), Immediate(12)); + __ add(ebx, Immediate(12)); __ nop(); __ adc(ecx, 12); __ adc(ecx, 1000); @@ -116,16 +116,16 @@ TEST(DisasmIa320) { CpuFeatures::Scope fscope(RDTSC); __ rdtsc(); } - __ movsx_b(edx, Operand(ecx)); - __ movsx_w(edx, Operand(ecx)); - __ movzx_b(edx, Operand(ecx)); - __ movzx_w(edx, Operand(ecx)); + __ movsx_b(edx, ecx); + __ movsx_w(edx, ecx); + __ movzx_b(edx, ecx); + __ movzx_w(edx, ecx); __ nop(); - __ imul(edx, Operand(ecx)); - __ shld(edx, Operand(ecx)); - __ shrd(edx, Operand(ecx)); - __ bts(Operand(edx), ecx); + __ imul(edx, ecx); + __ shld(edx, ecx); + __ shrd(edx, ecx); + __ bts(edx, ecx); __ bts(Operand(ebx, ecx, times_4, 0), ecx); __ nop(); __ pushad(); @@ -146,9 +146,9 @@ TEST(DisasmIa320) { __ nop(); __ add(edx, Operand(esp, 16)); - __ add(edx, Operand(ecx)); - __ mov_b(edx, Operand(ecx)); - __ mov_b(Operand(ecx), 6); + __ add(edx, ecx); + __ mov_b(edx, ecx); + __ mov_b(ecx, 6); __ mov_b(Operand(ebx, ecx, times_4, 10000), 6); __ mov_b(Operand(esp, 16), edx); __ mov_w(edx, Operand(esp, 16)); @@ -216,22 +216,20 @@ TEST(DisasmIa320) { __ adc(edx, 12345); - __ add(Operand(ebx), Immediate(12)); + __ add(ebx, Immediate(12)); __ add(Operand(edx, ecx, times_4, 10000), Immediate(12)); __ and_(ebx, 12345); __ cmp(ebx, 12345); - __ cmp(Operand(ebx), Immediate(12)); + __ cmp(ebx, Immediate(12)); __ cmp(Operand(edx, ecx, times_4, 10000), Immediate(12)); + __ cmpb(eax, 100); __ or_(ebx, 12345); - __ sub(Operand(ebx), Immediate(12)); + __ sub(ebx, Immediate(12)); __ sub(Operand(edx, ecx, times_4, 10000), Immediate(12)); - __ subb(Operand(edx, ecx, times_4, 10000), 100); - __ subb(Operand(eax), 100); - __ subb(eax, Operand(edx, ecx, times_4, 10000)); __ xor_(ebx, 12345); @@ -244,7 +242,7 @@ TEST(DisasmIa320) { __ stos(); __ sub(edx, Operand(ebx, ecx, times_4, 10000)); - __ sub(edx, Operand(ebx)); + __ sub(edx, ebx); __ test(edx, Immediate(12345)); __ test(edx, Operand(ebx, ecx, times_8, 10000)); @@ -446,11 +444,16 @@ TEST(DisasmIa320) { { if (CpuFeatures::IsSupported(SSE4_1)) { CpuFeatures::Scope scope(SSE4_1); - __ pextrd(Operand(eax), xmm0, 1); - __ pinsrd(xmm1, Operand(eax), 0); + __ pextrd(eax, xmm0, 1); + __ pinsrd(xmm1, eax, 0); } } + // Nop instructions + for (int i = 0; i < 16; i++) { + __ Nop(i); + } + __ ret(0); CodeDesc desc; diff --git a/test/cctest/test-disasm-mips.cc b/test/cctest/test-disasm-mips.cc index 5ad99d7a..1f874245 100644 --- a/test/cctest/test-disasm-mips.cc +++ b/test/cctest/test-disasm-mips.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// 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: @@ -71,10 +71,10 @@ bool DisassembleAndCompare(byte* pc, const char* compare_string) { } -// Setup V8 to a state where we can at least run the assembler and +// Set up V8 to a state where we can at least run the assembler and // disassembler. Declare the variables and allocate the data structures used // in the rest of the macros. -#define SETUP() \ +#define SET_UP() \ InitializeVM(); \ v8::HandleScope scope; \ byte *buffer = reinterpret_cast<byte*>(malloc(4*1024)); \ @@ -104,7 +104,7 @@ if (failure) { \ TEST(Type0) { - SETUP(); + SET_UP(); COMPARE(addu(a0, a1, a2), "00a62021 addu a0, a1, a2"); @@ -148,12 +148,14 @@ TEST(Type0) { COMPARE(divu(v0, v1), "0043001b divu v0, v1"); - COMPARE(mul(a0, a1, a2), - "70a62002 mul a0, a1, a2"); - COMPARE(mul(t2, t3, t4), - "716c5002 mul t2, t3, t4"); - COMPARE(mul(v0, v1, s0), - "70701002 mul v0, v1, s0"); + if (kArchVariant != kLoongson) { + COMPARE(mul(a0, a1, a2), + "70a62002 mul a0, a1, a2"); + COMPARE(mul(t2, t3, t4), + "716c5002 mul t2, t3, t4"); + COMPARE(mul(v0, v1, s0), + "70701002 mul v0, v1, s0"); + } COMPARE(addiu(a0, a1, 0x0), "24a40000 addiu a0, a1, 0"); @@ -274,7 +276,7 @@ TEST(Type0) { COMPARE(srav(v0, v1, fp), "03c31007 srav v0, v1, fp"); - if (mips32r2) { + if (kArchVariant == kMips32r2) { COMPARE(rotr(a0, a1, 0), "00252002 rotr a0, a1, 0"); COMPARE(rotr(s0, s1, 8), @@ -377,48 +379,50 @@ TEST(Type0) { COMPARE(sltiu(v0, v1, -1), "2c62ffff sltiu v0, v1, -1"); - COMPARE(movz(a0, a1, a2), - "00a6200a movz a0, a1, a2"); - COMPARE(movz(s0, s1, s2), - "0232800a movz s0, s1, s2"); - COMPARE(movz(t2, t3, t4), - "016c500a movz t2, t3, t4"); - COMPARE(movz(v0, v1, a2), - "0066100a movz v0, v1, a2"); - COMPARE(movn(a0, a1, a2), - "00a6200b movn a0, a1, a2"); - COMPARE(movn(s0, s1, s2), - "0232800b movn s0, s1, s2"); - COMPARE(movn(t2, t3, t4), - "016c500b movn t2, t3, t4"); - COMPARE(movn(v0, v1, a2), - "0066100b movn v0, v1, a2"); - - COMPARE(movt(a0, a1, 1), - "00a52001 movt a0, a1, 1"); - COMPARE(movt(s0, s1, 2), - "02298001 movt s0, s1, 2"); - COMPARE(movt(t2, t3, 3), - "016d5001 movt t2, t3, 3"); - COMPARE(movt(v0, v1, 7), - "007d1001 movt v0, v1, 7"); - COMPARE(movf(a0, a1, 0), - "00a02001 movf a0, a1, 0"); - COMPARE(movf(s0, s1, 4), - "02308001 movf s0, s1, 4"); - COMPARE(movf(t2, t3, 5), - "01745001 movf t2, t3, 5"); - COMPARE(movf(v0, v1, 6), - "00781001 movf v0, v1, 6"); - - COMPARE(clz(a0, a1), - "70a42020 clz a0, a1"); - COMPARE(clz(s6, s7), - "72f6b020 clz s6, s7"); - COMPARE(clz(v0, v1), - "70621020 clz v0, v1"); - - if (mips32r2) { + if (kArchVariant != kLoongson) { + COMPARE(movz(a0, a1, a2), + "00a6200a movz a0, a1, a2"); + COMPARE(movz(s0, s1, s2), + "0232800a movz s0, s1, s2"); + COMPARE(movz(t2, t3, t4), + "016c500a movz t2, t3, t4"); + COMPARE(movz(v0, v1, a2), + "0066100a movz v0, v1, a2"); + COMPARE(movn(a0, a1, a2), + "00a6200b movn a0, a1, a2"); + COMPARE(movn(s0, s1, s2), + "0232800b movn s0, s1, s2"); + COMPARE(movn(t2, t3, t4), + "016c500b movn t2, t3, t4"); + COMPARE(movn(v0, v1, a2), + "0066100b movn v0, v1, a2"); + + COMPARE(movt(a0, a1, 1), + "00a52001 movt a0, a1, 1"); + COMPARE(movt(s0, s1, 2), + "02298001 movt s0, s1, 2"); + COMPARE(movt(t2, t3, 3), + "016d5001 movt t2, t3, 3"); + COMPARE(movt(v0, v1, 7), + "007d1001 movt v0, v1, 7"); + COMPARE(movf(a0, a1, 0), + "00a02001 movf a0, a1, 0"); + COMPARE(movf(s0, s1, 4), + "02308001 movf s0, s1, 4"); + COMPARE(movf(t2, t3, 5), + "01745001 movf t2, t3, 5"); + COMPARE(movf(v0, v1, 6), + "00781001 movf v0, v1, 6"); + + COMPARE(clz(a0, a1), + "70a42020 clz a0, a1"); + COMPARE(clz(s6, s7), + "72f6b020 clz s6, s7"); + COMPARE(clz(v0, v1), + "70621020 clz v0, v1"); + } + + if (kArchVariant == kMips32r2) { COMPARE(ins_(a0, a1, 31, 1), "7ca4ffc4 ins a0, a1, 31, 1"); COMPARE(ins_(s6, s7, 30, 2), diff --git a/test/cctest/test-disasm-x64.cc b/test/cctest/test-disasm-x64.cc new file mode 100644 index 00000000..da85eb93 --- /dev/null +++ b/test/cctest/test-disasm-x64.cc @@ -0,0 +1,429 @@ +// Copyright 2011 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. + +#include <stdlib.h> + +#include "v8.h" + +#include "debug.h" +#include "disasm.h" +#include "disassembler.h" +#include "macro-assembler.h" +#include "serialize.h" +#include "cctest.h" + +using namespace v8::internal; + +static v8::Persistent<v8::Context> env; + +static void InitializeVM() { + if (env.IsEmpty()) { + env = v8::Context::New(); + } +} + + +#define __ assm. + + +static void DummyStaticFunction(Object* result) { +} + + +TEST(DisasmX64) { + InitializeVM(); + v8::HandleScope scope; + v8::internal::byte buffer[2048]; + Assembler assm(Isolate::Current(), buffer, sizeof buffer); + DummyStaticFunction(NULL); // just bloody use it (DELETE; debugging) + + // Short immediate instructions + __ addq(rax, Immediate(12345678)); + __ or_(rax, Immediate(12345678)); + __ subq(rax, Immediate(12345678)); + __ xor_(rax, Immediate(12345678)); + __ and_(rax, Immediate(12345678)); + + // ---- This one caused crash + __ movq(rbx, Operand(rsp, rcx, times_2, 0)); // [rsp+rcx*4] + + // ---- All instructions that I can think of + __ addq(rdx, rbx); + __ addq(rdx, Operand(rbx, 0)); + __ addq(rdx, Operand(rbx, 16)); + __ addq(rdx, Operand(rbx, 1999)); + __ addq(rdx, Operand(rsp, 0)); + __ addq(rdx, Operand(rsp, 16)); + __ addq(rdx, Operand(rsp, 1999)); + __ nop(); + __ addq(rdi, Operand(rbp, rcx, times_4, 0)); + __ addq(rdi, Operand(rbp, rcx, times_4, 12)); + __ addq(Operand(rbp, rcx, times_4, 12), Immediate(12)); + + __ nop(); + __ addq(rbx, Immediate(12)); + __ nop(); + __ nop(); + __ and_(rdx, Immediate(3)); + __ and_(rdx, Operand(rsp, 4)); + __ cmpq(rdx, Immediate(3)); + __ cmpq(rdx, Operand(rsp, 4)); + __ cmpq(Operand(rbp, rcx, times_4, 0), Immediate(1000)); + __ cmpb(rbx, Operand(rbp, rcx, times_2, 0)); + __ cmpb(Operand(rbp, rcx, times_2, 0), rbx); + __ or_(rdx, Immediate(3)); + __ xor_(rdx, Immediate(3)); + __ nop(); + { + CHECK(CpuFeatures::IsSupported(CPUID)); + CpuFeatures::Scope fscope(CPUID); + __ cpuid(); + } + { + CHECK(CpuFeatures::IsSupported(RDTSC)); + CpuFeatures::Scope fscope(RDTSC); + __ rdtsc(); + } + __ movsxbq(rdx, Operand(rcx, 0)); + __ movsxwq(rdx, Operand(rcx, 0)); + __ movzxbl(rdx, Operand(rcx, 0)); + __ movzxwl(rdx, Operand(rcx, 0)); + __ movzxbq(rdx, Operand(rcx, 0)); + __ movzxwq(rdx, Operand(rcx, 0)); + + __ nop(); + __ imul(rdx, rcx); + __ shld(rdx, rcx); + __ shrd(rdx, rcx); + __ bts(Operand(rdx, 0), rcx); + __ bts(Operand(rbx, rcx, times_4, 0), rcx); + __ nop(); + __ push(Immediate(12)); + __ push(Immediate(23456)); + __ push(rcx); + __ push(rsi); + __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); + __ push(Operand(rbx, rcx, times_4, 0)); + __ push(Operand(rbx, rcx, times_4, 0)); + __ push(Operand(rbx, rcx, times_4, 10000)); + __ pop(rdx); + __ pop(rax); + __ pop(Operand(rbx, rcx, times_4, 0)); + __ nop(); + + __ addq(rdx, Operand(rsp, 16)); + __ addq(rdx, rcx); + __ movb(rdx, Operand(rcx, 0)); + __ movb(rcx, Immediate(6)); + __ movb(Operand(rsp, 16), rdx); + __ movw(Operand(rsp, 16), rdx); + __ nop(); + __ movsxwq(rdx, Operand(rsp, 12)); + __ movsxbq(rdx, Operand(rsp, 12)); + __ movsxlq(rdx, Operand(rsp, 12)); + __ movzxwq(rdx, Operand(rsp, 12)); + __ movzxbq(rdx, Operand(rsp, 12)); + __ nop(); + __ movq(rdx, Immediate(1234567)); + __ movq(rdx, Operand(rsp, 12)); + __ movq(Operand(rbx, rcx, times_4, 10000), Immediate(12345)); + __ movq(Operand(rbx, rcx, times_4, 10000), rdx); + __ nop(); + __ decb(rdx); + __ decb(Operand(rax, 10)); + __ decb(Operand(rbx, rcx, times_4, 10000)); + __ decq(rdx); + __ cdq(); + + __ nop(); + __ idivq(rdx); + __ mul(rdx); + __ neg(rdx); + __ not_(rdx); + __ testq(Operand(rbx, rcx, times_4, 10000), rdx); + + __ imul(rdx, Operand(rbx, rcx, times_4, 10000)); + __ imul(rdx, rcx, Immediate(12)); + __ imul(rdx, rcx, Immediate(1000)); + + __ incq(rdx); + __ incq(Operand(rbx, rcx, times_4, 10000)); + __ push(Operand(rbx, rcx, times_4, 10000)); + __ pop(Operand(rbx, rcx, times_4, 10000)); + __ jmp(Operand(rbx, rcx, times_4, 10000)); + + __ lea(rdx, Operand(rbx, rcx, times_4, 10000)); + __ or_(rdx, Immediate(12345)); + __ or_(rdx, Operand(rbx, rcx, times_4, 10000)); + + __ nop(); + + __ rcl(rdx, Immediate(1)); + __ rcl(rdx, Immediate(7)); + __ rcr(rdx, Immediate(1)); + __ rcr(rdx, Immediate(7)); + __ sar(rdx, Immediate(1)); + __ sar(rdx, Immediate(6)); + __ sar_cl(rdx); + __ sbbq(rdx, rbx); + __ shld(rdx, rbx); + __ shl(rdx, Immediate(1)); + __ shl(rdx, Immediate(6)); + __ shl_cl(rdx); + __ shrd(rdx, rbx); + __ shr(rdx, Immediate(1)); + __ shr(rdx, Immediate(7)); + __ shr_cl(rdx); + + + // Immediates + + __ addq(rbx, Immediate(12)); + __ addq(Operand(rdx, rcx, times_4, 10000), Immediate(12)); + + __ and_(rbx, Immediate(12345)); + + __ cmpq(rbx, Immediate(12345)); + __ cmpq(rbx, Immediate(12)); + __ cmpq(Operand(rdx, rcx, times_4, 10000), Immediate(12)); + __ cmpb(rax, Immediate(100)); + + __ or_(rbx, Immediate(12345)); + + __ subq(rbx, Immediate(12)); + __ subq(Operand(rdx, rcx, times_4, 10000), Immediate(12)); + + __ xor_(rbx, Immediate(12345)); + + __ imul(rdx, rcx, Immediate(12)); + __ imul(rdx, rcx, Immediate(1000)); + + __ cld(); + + __ subq(rdx, Operand(rbx, rcx, times_4, 10000)); + __ subq(rdx, rbx); + + __ testq(rdx, Immediate(12345)); + __ testq(Operand(rbx, rcx, times_8, 10000), rdx); + __ testb(Operand(rcx, rbx, times_2, 1000), rdx); + __ testb(Operand(rax, -20), Immediate(0x9A)); + __ nop(); + + __ xor_(rdx, Immediate(12345)); + __ xor_(rdx, Operand(rbx, rcx, times_8, 10000)); + __ bts(Operand(rbx, rcx, times_8, 10000), rdx); + __ hlt(); + __ int3(); + __ ret(0); + __ ret(8); + + // Calls + + Label L1, L2; + __ bind(&L1); + __ nop(); + __ call(&L1); + __ call(&L2); + __ nop(); + __ bind(&L2); + __ call(Operand(rbx, rcx, times_4, 10000)); + __ nop(); + Handle<Code> ic(Isolate::Current()->builtins()->builtin( + Builtins::kLoadIC_Initialize)); + __ call(ic, RelocInfo::CODE_TARGET); + __ nop(); + __ nop(); + + __ jmp(&L1); + __ jmp(Operand(rbx, rcx, times_4, 10000)); +#ifdef ENABLE_DEBUGGER_SUPPORT + ExternalReference after_break_target = + ExternalReference(Debug_Address::AfterBreakTarget(), + assm.isolate()); +#endif // ENABLE_DEBUGGER_SUPPORT + __ jmp(ic, RelocInfo::CODE_TARGET); + __ nop(); + + + Label Ljcc; + __ nop(); + // long jumps + __ j(overflow, &Ljcc); + __ j(no_overflow, &Ljcc); + __ j(below, &Ljcc); + __ j(above_equal, &Ljcc); + __ j(equal, &Ljcc); + __ j(not_equal, &Ljcc); + __ j(below_equal, &Ljcc); + __ j(above, &Ljcc); + __ j(sign, &Ljcc); + __ j(not_sign, &Ljcc); + __ j(parity_even, &Ljcc); + __ j(parity_odd, &Ljcc); + __ j(less, &Ljcc); + __ j(greater_equal, &Ljcc); + __ j(less_equal, &Ljcc); + __ j(greater, &Ljcc); + __ nop(); + __ bind(&Ljcc); + // short jumps + __ j(overflow, &Ljcc); + __ j(no_overflow, &Ljcc); + __ j(below, &Ljcc); + __ j(above_equal, &Ljcc); + __ j(equal, &Ljcc); + __ j(not_equal, &Ljcc); + __ j(below_equal, &Ljcc); + __ j(above, &Ljcc); + __ j(sign, &Ljcc); + __ j(not_sign, &Ljcc); + __ j(parity_even, &Ljcc); + __ j(parity_odd, &Ljcc); + __ j(less, &Ljcc); + __ j(greater_equal, &Ljcc); + __ j(less_equal, &Ljcc); + __ j(greater, &Ljcc); + + // 0xD9 instructions + __ nop(); + + __ fld(1); + __ fld1(); + __ fldz(); + __ fldpi(); + __ fabs(); + __ fchs(); + __ fprem(); + __ fprem1(); + __ fincstp(); + __ ftst(); + __ fxch(3); + __ fld_s(Operand(rbx, rcx, times_4, 10000)); + __ fstp_s(Operand(rbx, rcx, times_4, 10000)); + __ ffree(3); + __ fld_d(Operand(rbx, rcx, times_4, 10000)); + __ fstp_d(Operand(rbx, rcx, times_4, 10000)); + __ nop(); + + __ fild_s(Operand(rbx, rcx, times_4, 10000)); + __ fistp_s(Operand(rbx, rcx, times_4, 10000)); + __ fild_d(Operand(rbx, rcx, times_4, 10000)); + __ fistp_d(Operand(rbx, rcx, times_4, 10000)); + __ fnstsw_ax(); + __ nop(); + __ fadd(3); + __ fsub(3); + __ fmul(3); + __ fdiv(3); + + __ faddp(3); + __ fsubp(3); + __ fmulp(3); + __ fdivp(3); + __ fcompp(); + __ fwait(); + __ nop(); + { + if (CpuFeatures::IsSupported(SSE2)) { + CpuFeatures::Scope fscope(SSE2); + __ cvttss2si(rdx, Operand(rbx, rcx, times_4, 10000)); + __ cvttss2si(rdx, xmm1); + __ cvttsd2si(rdx, Operand(rbx, rcx, times_4, 10000)); + __ cvttsd2si(rdx, xmm1); + __ cvttsd2siq(rdx, xmm1); + __ addsd(xmm1, xmm0); + __ mulsd(xmm1, xmm0); + __ subsd(xmm1, xmm0); + __ divsd(xmm1, xmm0); + __ movsd(xmm1, Operand(rbx, rcx, times_4, 10000)); + __ movsd(Operand(rbx, rcx, times_4, 10000), xmm1); + __ ucomisd(xmm0, xmm1); + + // 128 bit move instructions. + __ movdqa(xmm0, Operand(rbx, rcx, times_4, 10000)); + __ movdqa(Operand(rbx, rcx, times_4, 10000), xmm0); + } + } + + // cmov. + { + if (CpuFeatures::IsSupported(CMOV)) { + CpuFeatures::Scope use_cmov(CMOV); + __ cmovq(overflow, rax, Operand(rax, 0)); + __ cmovq(no_overflow, rax, Operand(rax, 1)); + __ cmovq(below, rax, Operand(rax, 2)); + __ cmovq(above_equal, rax, Operand(rax, 3)); + __ cmovq(equal, rax, Operand(rbx, 0)); + __ cmovq(not_equal, rax, Operand(rbx, 1)); + __ cmovq(below_equal, rax, Operand(rbx, 2)); + __ cmovq(above, rax, Operand(rbx, 3)); + __ cmovq(sign, rax, Operand(rcx, 0)); + __ cmovq(not_sign, rax, Operand(rcx, 1)); + __ cmovq(parity_even, rax, Operand(rcx, 2)); + __ cmovq(parity_odd, rax, Operand(rcx, 3)); + __ cmovq(less, rax, Operand(rdx, 0)); + __ cmovq(greater_equal, rax, Operand(rdx, 1)); + __ cmovq(less_equal, rax, Operand(rdx, 2)); + __ cmovq(greater, rax, Operand(rdx, 3)); + } + } + + // andpd, etc. + { + if (CpuFeatures::IsSupported(SSE2)) { + CpuFeatures::Scope fscope(SSE2); + __ andpd(xmm0, xmm1); + __ andpd(xmm1, xmm2); + + __ movaps(xmm0, xmm1); + __ movaps(xmm1, xmm2); + } + } + + // Nop instructions + for (int i = 0; i < 16; i++) { + __ Nop(i); + } + + __ ret(0); + + CodeDesc desc; + assm.GetCode(&desc); + Object* code = HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); +#ifdef OBJECT_PRINT + Code::cast(code)->Print(); + byte* begin = Code::cast(code)->instruction_start(); + byte* end = begin + Code::cast(code)->instruction_size(); + disasm::Disassembler::Disassemble(stdout, begin, end); +#endif +} + +#undef __ diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc index 6c2afd47..a56f250c 100644 --- a/test/cctest/test-heap-profiler.cc +++ b/test/cctest/test-heap-profiler.cc @@ -18,14 +18,30 @@ class NamedEntriesDetector { : has_A2(false), has_B2(false), has_C2(false) { } - void Apply(i::HeapEntry** entry_ptr) { - if (IsReachableNodeWithName(*entry_ptr, "A2")) has_A2 = true; - if (IsReachableNodeWithName(*entry_ptr, "B2")) has_B2 = true; - if (IsReachableNodeWithName(*entry_ptr, "C2")) has_C2 = true; + void CheckEntry(i::HeapEntry* entry) { + if (strcmp(entry->name(), "A2") == 0) has_A2 = true; + if (strcmp(entry->name(), "B2") == 0) has_B2 = true; + if (strcmp(entry->name(), "C2") == 0) has_C2 = true; } - static bool IsReachableNodeWithName(i::HeapEntry* entry, const char* name) { - return strcmp(name, entry->name()) == 0 && entry->painted_reachable(); + void CheckAllReachables(i::HeapEntry* root) { + i::List<i::HeapEntry*> list(10); + list.Add(root); + root->paint(); + CheckEntry(root); + while (!list.is_empty()) { + i::HeapEntry* entry = list.RemoveLast(); + i::Vector<i::HeapGraphEdge> children = entry->children(); + for (int i = 0; i < children.length(); ++i) { + if (children[i].type() == i::HeapGraphEdge::kShortcut) continue; + i::HeapEntry* child = children[i].to(); + if (!child->painted()) { + list.Add(child); + child->paint(); + CheckEntry(child); + } + } + } } bool has_A2; @@ -90,10 +106,6 @@ TEST(HeapSnapshot) { const_cast<i::HeapSnapshot*>( reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2)); const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); - // Paint all nodes reachable from global object. - i_snapshot_env2->ClearPaint(); - const_cast<i::HeapEntry*>( - reinterpret_cast<const i::HeapEntry*>(global_env2))->PaintAllReachable(); // Verify, that JS global object of env2 has '..2' properties. const v8::HeapGraphNode* a2_node = @@ -105,8 +117,11 @@ TEST(HeapSnapshot) { NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_2")); CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "c2")); + // Paint all nodes reachable from global object. NamedEntriesDetector det; - i_snapshot_env2->IterateEntries(&det); + i_snapshot_env2->ClearPaint(); + det.CheckAllReachables(const_cast<i::HeapEntry*>( + reinterpret_cast<const i::HeapEntry*>(global_env2))); CHECK(det.has_A2); CHECK(det.has_B2); CHECK(det.has_C2); @@ -136,14 +151,47 @@ TEST(HeapSnapshotObjectSizes) { GetProperty(x, v8::HeapGraphEdge::kProperty, "b"); CHECK_NE(NULL, x2); - // Test approximate sizes. - CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(false)); - CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(false)); - CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(false)); - // Test exact sizes. - CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(true)); - CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(true)); - CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(true)); + // Test sizes. + CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize()); + CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize()); + CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize()); +} + + +TEST(BoundFunctionInSnapshot) { + v8::HandleScope scope; + LocalContext env; + CompileRun( + "function myFunction(a, b) { this.a = a; this.b = b; }\n" + "function AAAAA() {}\n" + "boundFunction = myFunction.bind(new AAAAA(), 20, new Number(12)); \n"); + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8_str("sizes")); + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + const v8::HeapGraphNode* f = + GetProperty(global, v8::HeapGraphEdge::kShortcut, "boundFunction"); + CHECK(f); + CHECK_EQ(v8::String::New("native_bind"), f->GetName()); + const v8::HeapGraphNode* bindings = + GetProperty(f, v8::HeapGraphEdge::kInternal, "bindings"); + CHECK_NE(NULL, bindings); + CHECK_EQ(v8::HeapGraphNode::kArray, bindings->GetType()); + CHECK_EQ(4, bindings->GetChildrenCount()); + + const v8::HeapGraphNode* bound_this = GetProperty( + f, v8::HeapGraphEdge::kShortcut, "bound_this"); + CHECK(bound_this); + CHECK_EQ(v8::HeapGraphNode::kObject, bound_this->GetType()); + + const v8::HeapGraphNode* bound_function = GetProperty( + f, v8::HeapGraphEdge::kShortcut, "bound_function"); + CHECK(bound_function); + CHECK_EQ(v8::HeapGraphNode::kClosure, bound_function->GetType()); + + const v8::HeapGraphNode* bound_argument = GetProperty( + f, v8::HeapGraphEdge::kShortcut, "bound_argument_1"); + CHECK(bound_argument); + CHECK_EQ(v8::HeapGraphNode::kObject, bound_argument->GetType()); } @@ -252,6 +300,28 @@ TEST(HeapSnapshotHeapNumbers) { CHECK_EQ(v8::HeapGraphNode::kHeapNumber, b->GetType()); } +TEST(HeapSnapshotSlicedString) { + v8::HandleScope scope; + LocalContext env; + CompileRun( + "parent_string = \"123456789.123456789.123456789.123456789.123456789." + "123456789.123456789.123456789.123456789.123456789." + "123456789.123456789.123456789.123456789.123456789." + "123456789.123456789.123456789.123456789.123456789.\";" + "child_string = parent_string.slice(100);"); + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8_str("strings")); + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + const v8::HeapGraphNode* parent_string = + GetProperty(global, v8::HeapGraphEdge::kShortcut, "parent_string"); + CHECK_NE(NULL, parent_string); + const v8::HeapGraphNode* child_string = + GetProperty(global, v8::HeapGraphEdge::kShortcut, "child_string"); + CHECK_NE(NULL, child_string); + const v8::HeapGraphNode* parent = + GetProperty(child_string, v8::HeapGraphEdge::kInternal, "parent"); + CHECK_EQ(parent_string, parent); +} TEST(HeapSnapshotInternalReferences) { v8::HandleScope scope; @@ -282,6 +352,59 @@ TEST(HeapSnapshotInternalReferences) { #define CHECK_NE_UINT64_T(a, b) \ CHECK((a) != (b)) // NOLINT +TEST(HeapEntryIdsAndArrayShift) { + v8::HandleScope scope; + LocalContext env; + + CompileRun( + "function AnObject() {\n" + " this.first = 'first';\n" + " this.second = 'second';\n" + "}\n" + "var a = new Array();\n" + "for (var i = 0; i < 10; ++i)\n" + " a.push(new AnObject());\n"); + const v8::HeapSnapshot* snapshot1 = + v8::HeapProfiler::TakeSnapshot(v8_str("s1")); + + CompileRun( + "for (var i = 0; i < 1; ++i)\n" + " a.shift();\n"); + + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); + + const v8::HeapSnapshot* snapshot2 = + v8::HeapProfiler::TakeSnapshot(v8_str("s2")); + + const v8::HeapGraphNode* global1 = GetGlobalObject(snapshot1); + const v8::HeapGraphNode* global2 = GetGlobalObject(snapshot2); + CHECK_NE_UINT64_T(0, global1->GetId()); + CHECK_EQ_UINT64_T(global1->GetId(), global2->GetId()); + + const v8::HeapGraphNode* a1 = + GetProperty(global1, v8::HeapGraphEdge::kProperty, "a"); + CHECK_NE(NULL, a1); + const v8::HeapGraphNode* e1 = + GetProperty(a1, v8::HeapGraphEdge::kHidden, "1"); + CHECK_NE(NULL, e1); + const v8::HeapGraphNode* k1 = + GetProperty(e1, v8::HeapGraphEdge::kInternal, "elements"); + CHECK_NE(NULL, k1); + const v8::HeapGraphNode* a2 = + GetProperty(global2, v8::HeapGraphEdge::kProperty, "a"); + CHECK_NE(NULL, a2); + const v8::HeapGraphNode* e2 = + GetProperty(a2, v8::HeapGraphEdge::kHidden, "1"); + CHECK_NE(NULL, e2); + const v8::HeapGraphNode* k2 = + GetProperty(e2, v8::HeapGraphEdge::kInternal, "elements"); + CHECK_NE(NULL, k2); + + CHECK_EQ_UINT64_T(a1->GetId(), a2->GetId()); + CHECK_EQ_UINT64_T(e1->GetId(), e2->GetId()); + CHECK_EQ_UINT64_T(k1->GetId(), k2->GetId()); +} + TEST(HeapEntryIdsAndGC) { v8::HandleScope scope; LocalContext env; @@ -294,7 +417,7 @@ TEST(HeapEntryIdsAndGC) { const v8::HeapSnapshot* snapshot1 = v8::HeapProfiler::TakeSnapshot(v8_str("s1")); - HEAP->CollectAllGarbage(true); // Enforce compaction. + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); const v8::HeapSnapshot* snapshot2 = v8::HeapProfiler::TakeSnapshot(v8_str("s2")); @@ -563,6 +686,22 @@ TEST(HeapSnapshotJSONSerializationAborting) { } +static void CheckChildrenIds(const v8::HeapSnapshot* snapshot, + const v8::HeapGraphNode* node, + int level, int max_level) { + if (level > max_level) return; + CHECK_EQ(node, snapshot->GetNodeById(node->GetId())); + for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { + const v8::HeapGraphEdge* prop = node->GetChild(i); + const v8::HeapGraphNode* child = + snapshot->GetNodeById(prop->GetToNode()->GetId()); + CHECK_EQ_UINT64_T(prop->GetToNode()->GetId(), child->GetId()); + CHECK_EQ(prop->GetToNode(), child); + CheckChildrenIds(snapshot, child, level + 1, max_level); + } +} + + TEST(HeapSnapshotGetNodeById) { v8::HandleScope scope; LocalContext env; @@ -570,12 +709,7 @@ TEST(HeapSnapshotGetNodeById) { const v8::HeapSnapshot* snapshot = v8::HeapProfiler::TakeSnapshot(v8_str("id")); const v8::HeapGraphNode* root = snapshot->GetRoot(); - CHECK_EQ(root, snapshot->GetNodeById(root->GetId())); - for (int i = 0, count = root->GetChildrenCount(); i < count; ++i) { - const v8::HeapGraphEdge* prop = root->GetChild(i); - CHECK_EQ( - prop->GetToNode(), snapshot->GetNodeById(prop->GetToNode()->GetId())); - } + CheckChildrenIds(snapshot, root, 0, 3); // Check a big id, which should not exist yet. CHECK_EQ(NULL, snapshot->GetNodeById(0x1000000UL)); } @@ -607,7 +741,7 @@ TEST(TakeHeapSnapshotAborting) { LocalContext env; const int snapshots_count = v8::HeapProfiler::GetSnapshotsCount(); - TestActivityControl aborting_control(3); + TestActivityControl aborting_control(1); const v8::HeapSnapshot* no_snapshot = v8::HeapProfiler::TakeSnapshot(v8_str("abort"), v8::HeapSnapshot::kFull, @@ -633,11 +767,13 @@ namespace { class TestRetainedObjectInfo : public v8::RetainedObjectInfo { public: TestRetainedObjectInfo(int hash, + const char* group_label, const char* label, intptr_t element_count = -1, intptr_t size = -1) : disposed_(false), hash_(hash), + group_label_(group_label), label_(label), element_count_(element_count), size_(size) { @@ -652,6 +788,7 @@ class TestRetainedObjectInfo : public v8::RetainedObjectInfo { return GetHash() == other->GetHash(); } virtual intptr_t GetHash() { return hash_; } + virtual const char* GetGroupLabel() { return group_label_; } virtual const char* GetLabel() { return label_; } virtual intptr_t GetElementCount() { return element_count_; } virtual intptr_t GetSizeInBytes() { return size_; } @@ -663,15 +800,15 @@ class TestRetainedObjectInfo : public v8::RetainedObjectInfo { if (wrapper->IsString()) { v8::String::AsciiValue ascii(wrapper); if (strcmp(*ascii, "AAA") == 0) - return new TestRetainedObjectInfo(1, "aaa", 100); + return new TestRetainedObjectInfo(1, "aaa-group", "aaa", 100); else if (strcmp(*ascii, "BBB") == 0) - return new TestRetainedObjectInfo(1, "aaa", 100); + return new TestRetainedObjectInfo(1, "aaa-group", "aaa", 100); } } else if (class_id == 2) { if (wrapper->IsString()) { v8::String::AsciiValue ascii(wrapper); if (strcmp(*ascii, "CCC") == 0) - return new TestRetainedObjectInfo(2, "ccc"); + return new TestRetainedObjectInfo(2, "ccc-group", "ccc"); } } CHECK(false); @@ -684,6 +821,7 @@ class TestRetainedObjectInfo : public v8::RetainedObjectInfo { bool disposed_; int category_; int hash_; + const char* group_label_; const char* label_; intptr_t element_count_; intptr_t size_; @@ -736,18 +874,21 @@ TEST(HeapSnapshotRetainedObjectInfo) { delete TestRetainedObjectInfo::instances[i]; } - const v8::HeapGraphNode* natives = GetNode( - snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(Native objects)"); - CHECK_NE(NULL, natives); - CHECK_EQ(2, natives->GetChildrenCount()); + const v8::HeapGraphNode* native_group_aaa = GetNode( + snapshot->GetRoot(), v8::HeapGraphNode::kSynthetic, "aaa-group"); + CHECK_NE(NULL, native_group_aaa); + CHECK_EQ(1, native_group_aaa->GetChildrenCount()); const v8::HeapGraphNode* aaa = GetNode( - natives, v8::HeapGraphNode::kNative, "aaa / 100 entries"); + native_group_aaa, v8::HeapGraphNode::kNative, "aaa / 100 entries"); CHECK_NE(NULL, aaa); + CHECK_EQ(2, aaa->GetChildrenCount()); + + const v8::HeapGraphNode* native_group_ccc = GetNode( + snapshot->GetRoot(), v8::HeapGraphNode::kSynthetic, "ccc-group"); const v8::HeapGraphNode* ccc = GetNode( - natives, v8::HeapGraphNode::kNative, "ccc"); + native_group_ccc, v8::HeapGraphNode::kNative, "ccc"); CHECK_NE(NULL, ccc); - CHECK_EQ(2, aaa->GetChildrenCount()); const v8::HeapGraphNode* n_AAA = GetNode( aaa, v8::HeapGraphNode::kString, "AAA"); CHECK_NE(NULL, n_AAA); @@ -765,6 +906,75 @@ TEST(HeapSnapshotRetainedObjectInfo) { } +class GraphWithImplicitRefs { + public: + static const int kObjectsCount = 4; + explicit GraphWithImplicitRefs(LocalContext* env) { + CHECK_EQ(NULL, instance_); + instance_ = this; + for (int i = 0; i < kObjectsCount; i++) { + objects_[i] = v8::Persistent<v8::Object>::New(v8::Object::New()); + } + (*env)->Global()->Set(v8_str("root_object"), objects_[0]); + } + ~GraphWithImplicitRefs() { + instance_ = NULL; + } + + static void gcPrologue() { + instance_->AddImplicitReferences(); + } + + private: + void AddImplicitReferences() { + // 0 -> 1 + v8::V8::AddImplicitReferences( + v8::Persistent<v8::Object>::Cast(objects_[0]), &objects_[1], 1); + // Adding two more references(note length=2 in params): 1 -> 2, 1 -> 3 + v8::V8::AddImplicitReferences( + v8::Persistent<v8::Object>::Cast(objects_[1]), &objects_[2], 2); + } + + v8::Persistent<v8::Value> objects_[kObjectsCount]; + static GraphWithImplicitRefs* instance_; +}; + +GraphWithImplicitRefs* GraphWithImplicitRefs::instance_ = NULL; + + +TEST(HeapSnapshotImplicitReferences) { + v8::HandleScope scope; + LocalContext env; + + GraphWithImplicitRefs graph(&env); + v8::V8::SetGlobalGCPrologueCallback(&GraphWithImplicitRefs::gcPrologue); + + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8_str("implicit_refs")); + + const v8::HeapGraphNode* global_object = GetGlobalObject(snapshot); + // Use kShortcut type to skip intermediate JSGlobalPropertyCell + const v8::HeapGraphNode* obj0 = GetProperty( + global_object, v8::HeapGraphEdge::kShortcut, "root_object"); + CHECK(obj0); + CHECK_EQ(v8::HeapGraphNode::kObject, obj0->GetType()); + const v8::HeapGraphNode* obj1 = GetProperty( + obj0, v8::HeapGraphEdge::kInternal, "native"); + CHECK(obj1); + int implicit_targets_count = 0; + for (int i = 0, count = obj1->GetChildrenCount(); i < count; ++i) { + const v8::HeapGraphEdge* prop = obj1->GetChild(i); + v8::String::AsciiValue prop_name(prop->GetName()); + if (prop->GetType() == v8::HeapGraphEdge::kInternal && + strcmp("native", *prop_name) == 0) { + ++implicit_targets_count; + } + } + CHECK_EQ(2, implicit_targets_count); + v8::V8::SetGlobalGCPrologueCallback(NULL); +} + + TEST(DeleteAllHeapSnapshots) { v8::HandleScope scope; LocalContext env; @@ -873,6 +1083,20 @@ TEST(DocumentURLWithException) { } +TEST(NoHandleLeaks) { + v8::HandleScope scope; + LocalContext env; + + CompileRun("document = { URL:\"abcdefgh\" };"); + + v8::Handle<v8::String> name(v8_str("leakz")); + int count_before = i::HandleScope::NumberOfHandles(); + v8::HeapProfiler::TakeSnapshot(name); + int count_after = i::HandleScope::NumberOfHandles(); + CHECK_EQ(count_before, count_after); +} + + TEST(NodesIteration) { v8::HandleScope scope; LocalContext env; @@ -1001,3 +1225,144 @@ TEST(GetConstructorName) { CHECK_EQ(0, StringCmp( "Object", i::V8HeapExplorer::GetConstructorName(*js_obj6))); } + + +TEST(FastCaseGetter) { + v8::HandleScope scope; + LocalContext env; + + CompileRun("var obj1 = {};\n" + "obj1.__defineGetter__('propWithGetter', function Y() {\n" + " return 42;\n" + "});\n" + "obj1.__defineSetter__('propWithSetter', function Z(value) {\n" + " return this.value_ = value;\n" + "});\n"); + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8_str("fastCaseGetter")); + + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + CHECK_NE(NULL, global); + const v8::HeapGraphNode* obj1 = + GetProperty(global, v8::HeapGraphEdge::kShortcut, "obj1"); + CHECK_NE(NULL, obj1); + const v8::HeapGraphNode* getterFunction = + GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get-propWithGetter"); + CHECK_NE(NULL, getterFunction); + const v8::HeapGraphNode* setterFunction = + GetProperty(obj1, v8::HeapGraphEdge::kProperty, "set-propWithSetter"); + CHECK_NE(NULL, setterFunction); +} + + +bool HasWeakEdge(const v8::HeapGraphNode* node) { + for (int i = 0; i < node->GetChildrenCount(); ++i) { + const v8::HeapGraphEdge* handle_edge = node->GetChild(i); + if (handle_edge->GetType() == v8::HeapGraphEdge::kWeak) return true; + } + return false; +} + + +bool HasWeakGlobalHandle() { + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8_str("weaks")); + const v8::HeapGraphNode* gc_roots = GetNode( + snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(GC roots)"); + CHECK_NE(NULL, gc_roots); + const v8::HeapGraphNode* global_handles = GetNode( + gc_roots, v8::HeapGraphNode::kObject, "(Global handles)"); + CHECK_NE(NULL, global_handles); + return HasWeakEdge(global_handles); +} + + +static void PersistentHandleCallback(v8::Persistent<v8::Value> handle, void*) { + handle.Dispose(); +} + + +TEST(WeakGlobalHandle) { + v8::HandleScope scope; + LocalContext env; + + CHECK(!HasWeakGlobalHandle()); + + v8::Persistent<v8::Object> handle = + v8::Persistent<v8::Object>::New(v8::Object::New()); + handle.MakeWeak(NULL, PersistentHandleCallback); + + CHECK(HasWeakGlobalHandle()); +} + + +TEST(WeakGlobalContextRefs) { + v8::HandleScope scope; + LocalContext env; + + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8_str("weaks")); + const v8::HeapGraphNode* gc_roots = GetNode( + snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(GC roots)"); + CHECK_NE(NULL, gc_roots); + const v8::HeapGraphNode* global_handles = GetNode( + gc_roots, v8::HeapGraphNode::kObject, "(Global handles)"); + CHECK_NE(NULL, global_handles); + const v8::HeapGraphNode* global_context = GetNode( + global_handles, v8::HeapGraphNode::kHidden, "system / GlobalContext"); + CHECK_NE(NULL, global_context); + CHECK(HasWeakEdge(global_context)); +} + + +TEST(SfiAndJsFunctionWeakRefs) { + v8::HandleScope scope; + LocalContext env; + + CompileRun( + "fun = (function (x) { return function () { return x + 1; } })(1);"); + const v8::HeapSnapshot* snapshot = + v8::HeapProfiler::TakeSnapshot(v8_str("fun")); + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + CHECK_NE(NULL, global); + const v8::HeapGraphNode* fun = + GetProperty(global, v8::HeapGraphEdge::kShortcut, "fun"); + CHECK(HasWeakEdge(fun)); + const v8::HeapGraphNode* shared = + GetProperty(fun, v8::HeapGraphEdge::kInternal, "shared"); + CHECK(HasWeakEdge(shared)); +} + + +TEST(PersistentHandleCount) { + v8::HandleScope scope; + LocalContext env; + + // V8 also uses global handles internally, so we can't test for an absolute + // number. + int global_handle_count = v8::HeapProfiler::GetPersistentHandleCount(); + + // Create some persistent handles. + v8::Persistent<v8::String> p_AAA = + v8::Persistent<v8::String>::New(v8_str("AAA")); + CHECK_EQ(global_handle_count + 1, + v8::HeapProfiler::GetPersistentHandleCount()); + v8::Persistent<v8::String> p_BBB = + v8::Persistent<v8::String>::New(v8_str("BBB")); + CHECK_EQ(global_handle_count + 2, + v8::HeapProfiler::GetPersistentHandleCount()); + v8::Persistent<v8::String> p_CCC = + v8::Persistent<v8::String>::New(v8_str("CCC")); + CHECK_EQ(global_handle_count + 3, + v8::HeapProfiler::GetPersistentHandleCount()); + + // Dipose the persistent handles in a different order. + p_AAA.Dispose(); + CHECK_EQ(global_handle_count + 2, + v8::HeapProfiler::GetPersistentHandleCount()); + p_CCC.Dispose(); + CHECK_EQ(global_handle_count + 1, + v8::HeapProfiler::GetPersistentHandleCount()); + p_BBB.Dispose(); + CHECK_EQ(global_handle_count, v8::HeapProfiler::GetPersistentHandleCount()); +} diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index 11b88130..999e2c66 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. #include <stdlib.h> @@ -612,7 +612,7 @@ TEST(ObjectProperties) { CHECK(!obj->HasLocalProperty(*second)); // check string and symbol match - static const char* string1 = "fisk"; + const char* string1 = "fisk"; Handle<String> s1 = FACTORY->NewStringFromAscii(CStrVector(string1)); obj->SetProperty( *s1, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); @@ -620,7 +620,7 @@ TEST(ObjectProperties) { CHECK(obj->HasLocalProperty(*s1_symbol)); // check symbol and string match - static const char* string2 = "fugl"; + const char* string2 = "fugl"; Handle<String> s2_symbol = FACTORY->LookupAsciiSymbol(string2); obj->SetProperty( *s2_symbol, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); @@ -667,22 +667,23 @@ TEST(JSArray) { Handle<JSObject> object = FACTORY->NewJSObject(function); Handle<JSArray> array = Handle<JSArray>::cast(object); // We just initialized the VM, no heap allocation failure yet. - Object* ok = array->Initialize(0)->ToObjectChecked(); + array->Initialize(0)->ToObjectChecked(); // Set array length to 0. - ok = array->SetElementsLength(Smi::FromInt(0))->ToObjectChecked(); + array->SetElementsLength(Smi::FromInt(0))->ToObjectChecked(); CHECK_EQ(Smi::FromInt(0), array->length()); - CHECK(array->HasFastElements()); // Must be in fast mode. + // Must be in fast mode. + CHECK(array->HasFastTypeElements()); // array[length] = name. - ok = array->SetElement(0, *name, kNonStrictMode, true)->ToObjectChecked(); + array->SetElement(0, *name, NONE, kNonStrictMode)->ToObjectChecked(); CHECK_EQ(Smi::FromInt(1), array->length()); CHECK_EQ(array->GetElement(0), *name); // Set array length with larger than smi value. Handle<Object> length = FACTORY->NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1); - ok = array->SetElementsLength(*length)->ToObjectChecked(); + array->SetElementsLength(*length)->ToObjectChecked(); uint32_t int_length = 0; CHECK(length->ToArrayIndex(&int_length)); @@ -690,8 +691,7 @@ TEST(JSArray) { CHECK(array->HasDictionaryElements()); // Must be in slow mode. // array[length] = name. - ok = array->SetElement( - int_length, *name, kNonStrictMode, true)->ToObjectChecked(); + array->SetElement(int_length, *name, NONE, kNonStrictMode)->ToObjectChecked(); uint32_t new_int_length = 0; CHECK(array->length()->ToArrayIndex(&new_int_length)); CHECK_EQ(static_cast<double>(int_length), new_int_length - 1); @@ -718,10 +718,8 @@ TEST(JSObjectCopy) { obj->SetProperty( *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked(); - Object* ok = - obj->SetElement(0, *first, kNonStrictMode, true)->ToObjectChecked(); - - ok = obj->SetElement(1, *second, kNonStrictMode, true)->ToObjectChecked(); + obj->SetElement(0, *first, NONE, kNonStrictMode)->ToObjectChecked(); + obj->SetElement(1, *second, NONE, kNonStrictMode)->ToObjectChecked(); // Make the clone. Handle<JSObject> clone = Copy(obj); @@ -739,8 +737,8 @@ TEST(JSObjectCopy) { clone->SetProperty( *second, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); - ok = clone->SetElement(0, *second, kNonStrictMode, true)->ToObjectChecked(); - ok = clone->SetElement(1, *first, kNonStrictMode, true)->ToObjectChecked(); + clone->SetElement(0, *second, NONE, kNonStrictMode)->ToObjectChecked(); + clone->SetElement(1, *first, NONE, kNonStrictMode)->ToObjectChecked(); CHECK_EQ(obj->GetElement(1), clone->GetElement(0)); CHECK_EQ(obj->GetElement(0), clone->GetElement(1)); @@ -813,7 +811,7 @@ TEST(Iteration) { // Allocate a JS array to OLD_POINTER_SPACE and NEW_SPACE objs[next_objs_index++] = FACTORY->NewJSArray(10); - objs[next_objs_index++] = FACTORY->NewJSArray(10, TENURED); + objs[next_objs_index++] = FACTORY->NewJSArray(10, FAST_ELEMENTS, TENURED); // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE objs[next_objs_index++] = @@ -822,7 +820,7 @@ TEST(Iteration) { FACTORY->NewStringFromAscii(CStrVector("abcdefghij"), TENURED); // Allocate a large string (for large object space). - int large_size = HEAP->MaxObjectSizeInPagedSpace() + 1; + int large_size = Page::kMaxNonCodeHeapObjectSize + 1; char* str = new char[large_size]; for (int i = 0; i < large_size - 1; ++i) str[i] = 'a'; str[large_size - 1] = '\0'; @@ -838,49 +836,6 @@ TEST(Iteration) { } -TEST(LargeObjectSpaceContains) { - InitializeVM(); - - HEAP->CollectGarbage(NEW_SPACE); - - Address current_top = HEAP->new_space()->top(); - Page* page = Page::FromAddress(current_top); - Address current_page = page->address(); - Address next_page = current_page + Page::kPageSize; - int bytes_to_page = static_cast<int>(next_page - current_top); - if (bytes_to_page <= FixedArray::kHeaderSize) { - // Alas, need to cross another page to be able to - // put desired value. - next_page += Page::kPageSize; - bytes_to_page = static_cast<int>(next_page - current_top); - } - CHECK(bytes_to_page > FixedArray::kHeaderSize); - - intptr_t* flags_ptr = &Page::FromAddress(next_page)->flags_; - Address flags_addr = reinterpret_cast<Address>(flags_ptr); - - int bytes_to_allocate = - static_cast<int>(flags_addr - current_top) + kPointerSize; - - int n_elements = (bytes_to_allocate - FixedArray::kHeaderSize) / - kPointerSize; - CHECK_EQ(bytes_to_allocate, FixedArray::SizeFor(n_elements)); - FixedArray* array = FixedArray::cast( - HEAP->AllocateFixedArray(n_elements)->ToObjectChecked()); - - int index = n_elements - 1; - CHECK_EQ(flags_ptr, - HeapObject::RawField(array, FixedArray::OffsetOfElementAt(index))); - array->set(index, Smi::FromInt(0)); - // This chould have turned next page into LargeObjectPage: - // CHECK(Page::FromAddress(next_page)->IsLargeObjectPage()); - - HeapObject* addr = HeapObject::FromAddress(next_page + 2 * kPointerSize); - CHECK(HEAP->new_space()->Contains(addr)); - CHECK(!HEAP->lo_space()->Contains(addr)); -} - - TEST(EmptyHandleEscapeFrom) { InitializeVM(); @@ -907,8 +862,7 @@ TEST(Regression39128) { InitializeVM(); // Increase the chance of 'bump-the-pointer' allocation in old space. - bool force_compaction = true; - HEAP->CollectAllGarbage(force_compaction); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); v8::HandleScope scope; @@ -975,12 +929,6 @@ TEST(Regression39128) { return; } CHECK(HEAP->old_pointer_space()->Contains(clone->address())); - - // Step 5: verify validity of region dirty marks. - Address clone_addr = clone->address(); - Page* page = Page::FromAddress(clone_addr); - // Check that region covering inobject property 1 is marked dirty. - CHECK(page->IsRegionDirty(clone_addr + (object_size - kPointerSize))); } @@ -1010,17 +958,18 @@ TEST(TestCodeFlushing) { Handle<JSFunction> function(JSFunction::cast(func_value)); CHECK(function->shared()->is_compiled()); - HEAP->CollectAllGarbage(true); - HEAP->CollectAllGarbage(true); + // TODO(1609) Currently incremental marker does not support code flushing. + HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); + HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); CHECK(function->shared()->is_compiled()); - HEAP->CollectAllGarbage(true); - HEAP->CollectAllGarbage(true); - HEAP->CollectAllGarbage(true); - HEAP->CollectAllGarbage(true); - HEAP->CollectAllGarbage(true); - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); + HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); + HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); + HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); + HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); + HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); // foo should no longer be in the compilation cache CHECK(!function->shared()->is_compiled() || function->IsOptimized()); @@ -1109,7 +1058,7 @@ TEST(TestInternalWeakLists) { } // Mark compact handles the weak references. - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); // Get rid of f3 and f5 in the same way. @@ -1118,21 +1067,21 @@ TEST(TestInternalWeakLists) { HEAP->PerformScavenge(); CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); } - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); CompileRun("f5=null"); for (int j = 0; j < 10; j++) { HEAP->PerformScavenge(); CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); } - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); ctx[i]->Exit(); } // Force compilation cache cleanup. - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); // Dispose the global contexts one by one. for (int i = 0; i < kNumTestContexts; i++) { @@ -1146,7 +1095,7 @@ TEST(TestInternalWeakLists) { } // Mark compact handles the weak references. - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); CHECK_EQ(kNumTestContexts - i - 1, CountGlobalContexts()); } @@ -1161,7 +1110,7 @@ static int CountGlobalContextsWithGC(int n) { Handle<Object> object(HEAP->global_contexts_list()); while (!object->IsUndefined()) { count++; - if (count == n) HEAP->CollectAllGarbage(true); + if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags); object = Handle<Object>(Context::cast(*object)->get(Context::NEXT_CONTEXT_LINK)); } @@ -1180,7 +1129,7 @@ static int CountOptimizedUserFunctionsWithGC(v8::Handle<v8::Context> context, while (object->IsJSFunction() && !Handle<JSFunction>::cast(object)->IsBuiltin()) { count++; - if (count == n) HEAP->CollectAllGarbage(true); + if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags); object = Handle<Object>( Object::cast(JSFunction::cast(*object)->next_function_link())); } @@ -1238,92 +1187,413 @@ TEST(TestInternalWeakListsTraverseWithGC) { } +TEST(TestSizeOfObjects) { + v8::V8::Initialize(); + + // Get initial heap size after several full GCs, which will stabilize + // the heap size and return with sweeping finished completely. + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + CHECK(HEAP->old_pointer_space()->IsSweepingComplete()); + int initial_size = static_cast<int>(HEAP->SizeOfObjects()); + + { + // Allocate objects on several different old-space pages so that + // lazy sweeping kicks in for subsequent GC runs. + AlwaysAllocateScope always_allocate; + int filler_size = static_cast<int>(FixedArray::SizeFor(8192)); + for (int i = 1; i <= 100; i++) { + HEAP->AllocateFixedArray(8192, TENURED)->ToObjectChecked(); + CHECK_EQ(initial_size + i * filler_size, + static_cast<int>(HEAP->SizeOfObjects())); + } + } + + // The heap size should go back to initial size after a full GC, even + // though sweeping didn't finish yet. + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + CHECK(!HEAP->old_pointer_space()->IsSweepingComplete()); + CHECK_EQ(initial_size, static_cast<int>(HEAP->SizeOfObjects())); + + // Advancing the sweeper step-wise should not change the heap size. + while (!HEAP->old_pointer_space()->IsSweepingComplete()) { + HEAP->old_pointer_space()->AdvanceSweeper(KB); + CHECK_EQ(initial_size, static_cast<int>(HEAP->SizeOfObjects())); + } +} + + TEST(TestSizeOfObjectsVsHeapIteratorPrecision) { InitializeVM(); + HEAP->EnsureHeapIsIterable(); intptr_t size_of_objects_1 = HEAP->SizeOfObjects(); - HeapIterator iterator(HeapIterator::kFilterFreeListNodes); + HeapIterator iterator; intptr_t size_of_objects_2 = 0; for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { size_of_objects_2 += obj->Size(); } - // Delta must be within 1% of the larger result. + // Delta must be within 5% of the larger result. + // TODO(gc): Tighten this up by distinguishing between byte + // arrays that are real and those that merely mark free space + // on the heap. if (size_of_objects_1 > size_of_objects_2) { intptr_t delta = size_of_objects_1 - size_of_objects_2; PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, " "Iterator: %" V8_PTR_PREFIX "d, " "delta: %" V8_PTR_PREFIX "d\n", size_of_objects_1, size_of_objects_2, delta); - CHECK_GT(size_of_objects_1 / 100, delta); + CHECK_GT(size_of_objects_1 / 20, delta); } else { intptr_t delta = size_of_objects_2 - size_of_objects_1; PrintF("Heap::SizeOfObjects: %" V8_PTR_PREFIX "d, " "Iterator: %" V8_PTR_PREFIX "d, " "delta: %" V8_PTR_PREFIX "d\n", size_of_objects_1, size_of_objects_2, delta); - CHECK_GT(size_of_objects_2 / 100, delta); + CHECK_GT(size_of_objects_2 / 20, delta); } } -class HeapIteratorTestHelper { - public: - HeapIteratorTestHelper(Object* a, Object* b) - : a_(a), b_(b), a_found_(false), b_found_(false) {} - bool a_found() { return a_found_; } - bool b_found() { return b_found_; } - void IterateHeap(HeapIterator::HeapObjectsFiltering mode) { - HeapIterator iterator(mode); - for (HeapObject* obj = iterator.next(); - obj != NULL; - obj = iterator.next()) { - if (obj == a_) - a_found_ = true; - else if (obj == b_) - b_found_ = true; - } +static void FillUpNewSpace(NewSpace* new_space) { + // Fill up new space to the point that it is completely full. Make sure + // that the scavenger does not undo the filling. + v8::HandleScope scope; + AlwaysAllocateScope always_allocate; + intptr_t available = new_space->EffectiveCapacity() - new_space->Size(); + intptr_t number_of_fillers = (available / FixedArray::SizeFor(1000)) - 10; + for (intptr_t i = 0; i < number_of_fillers; i++) { + CHECK(HEAP->InNewSpace(*FACTORY->NewFixedArray(1000, NOT_TENURED))); } - private: - Object* a_; - Object* b_; - bool a_found_; - bool b_found_; -}; +} -TEST(HeapIteratorFilterUnreachable) { + +TEST(GrowAndShrinkNewSpace) { + InitializeVM(); + NewSpace* new_space = HEAP->new_space(); + + // Explicitly growing should double the space capacity. + intptr_t old_capacity, new_capacity; + old_capacity = new_space->Capacity(); + new_space->Grow(); + new_capacity = new_space->Capacity(); + CHECK(2 * old_capacity == new_capacity); + + old_capacity = new_space->Capacity(); + FillUpNewSpace(new_space); + new_capacity = new_space->Capacity(); + CHECK(old_capacity == new_capacity); + + // Explicitly shrinking should not affect space capacity. + old_capacity = new_space->Capacity(); + new_space->Shrink(); + new_capacity = new_space->Capacity(); + CHECK(old_capacity == new_capacity); + + // Let the scavenger empty the new space. + HEAP->CollectGarbage(NEW_SPACE); + CHECK_LE(new_space->Size(), old_capacity); + + // Explicitly shrinking should halve the space capacity. + old_capacity = new_space->Capacity(); + new_space->Shrink(); + new_capacity = new_space->Capacity(); + CHECK(old_capacity == 2 * new_capacity); + + // Consecutive shrinking should not affect space capacity. + old_capacity = new_space->Capacity(); + new_space->Shrink(); + new_space->Shrink(); + new_space->Shrink(); + new_capacity = new_space->Capacity(); + CHECK(old_capacity == new_capacity); +} + + +TEST(CollectingAllAvailableGarbageShrinksNewSpace) { InitializeVM(); v8::HandleScope scope; - CompileRun("a = {}; b = {};"); - v8::Handle<Object> a(ISOLATE->context()->global()->GetProperty( - *FACTORY->LookupAsciiSymbol("a"))->ToObjectChecked()); - v8::Handle<Object> b(ISOLATE->context()->global()->GetProperty( - *FACTORY->LookupAsciiSymbol("b"))->ToObjectChecked()); - CHECK_NE(*a, *b); + NewSpace* new_space = HEAP->new_space(); + intptr_t old_capacity, new_capacity; + old_capacity = new_space->Capacity(); + new_space->Grow(); + new_capacity = new_space->Capacity(); + CHECK(2 * old_capacity == new_capacity); + FillUpNewSpace(new_space); + HEAP->CollectAllAvailableGarbage(); + new_capacity = new_space->Capacity(); + CHECK(old_capacity == new_capacity); +} + + +static int NumberOfGlobalObjects() { + int count = 0; + HeapIterator iterator; + for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { + if (obj->IsGlobalObject()) count++; + } + return count; +} + + +// Test that we don't embed maps from foreign contexts into +// optimized code. +TEST(LeakGlobalContextViaMap) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope outer_scope; + v8::Persistent<v8::Context> ctx1 = v8::Context::New(); + v8::Persistent<v8::Context> ctx2 = v8::Context::New(); + ctx1->Enter(); + + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(4, NumberOfGlobalObjects()); + { - HeapIteratorTestHelper helper(*a, *b); - helper.IterateHeap(HeapIterator::kFilterUnreachable); - CHECK(helper.a_found()); - CHECK(helper.b_found()); + v8::HandleScope inner_scope; + CompileRun("var v = {x: 42}"); + v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); + ctx2->Enter(); + ctx2->Global()->Set(v8_str("o"), v); + v8::Local<v8::Value> res = CompileRun( + "function f() { return o.x; }" + "for (var i = 0; i < 10; ++i) f();" + "%OptimizeFunctionOnNextCall(f);" + "f();"); + CHECK_EQ(42, res->Int32Value()); + ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); + ctx2->Exit(); + ctx1->Exit(); + ctx1.Dispose(); } - CHECK(ISOLATE->context()->global()->DeleteProperty( - *FACTORY->LookupAsciiSymbol("a"), JSObject::FORCE_DELETION)); - // We ensure that GC will not happen, so our raw pointer stays valid. - AssertNoAllocation no_alloc; - Object* a_saved = *a; - a.Clear(); - // Verify that "a" object still resides in the heap... + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(2, NumberOfGlobalObjects()); + ctx2.Dispose(); + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(0, NumberOfGlobalObjects()); +} + + +// Test that we don't embed functions from foreign contexts into +// optimized code. +TEST(LeakGlobalContextViaFunction) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope outer_scope; + v8::Persistent<v8::Context> ctx1 = v8::Context::New(); + v8::Persistent<v8::Context> ctx2 = v8::Context::New(); + ctx1->Enter(); + + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(4, NumberOfGlobalObjects()); + { - HeapIteratorTestHelper helper(a_saved, *b); - helper.IterateHeap(HeapIterator::kNoFiltering); - CHECK(helper.a_found()); - CHECK(helper.b_found()); + v8::HandleScope inner_scope; + CompileRun("var v = function() { return 42; }"); + v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); + ctx2->Enter(); + ctx2->Global()->Set(v8_str("o"), v); + v8::Local<v8::Value> res = CompileRun( + "function f(x) { return x(); }" + "for (var i = 0; i < 10; ++i) f(o);" + "%OptimizeFunctionOnNextCall(f);" + "f(o);"); + CHECK_EQ(42, res->Int32Value()); + ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); + ctx2->Exit(); + ctx1->Exit(); + ctx1.Dispose(); } - // ...but is now unreachable. + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(2, NumberOfGlobalObjects()); + ctx2.Dispose(); + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(0, NumberOfGlobalObjects()); +} + + +TEST(LeakGlobalContextViaMapKeyed) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope outer_scope; + v8::Persistent<v8::Context> ctx1 = v8::Context::New(); + v8::Persistent<v8::Context> ctx2 = v8::Context::New(); + ctx1->Enter(); + + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(4, NumberOfGlobalObjects()); + { - HeapIteratorTestHelper helper(a_saved, *b); - helper.IterateHeap(HeapIterator::kFilterUnreachable); - CHECK(!helper.a_found()); - CHECK(helper.b_found()); + v8::HandleScope inner_scope; + CompileRun("var v = [42, 43]"); + v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); + ctx2->Enter(); + ctx2->Global()->Set(v8_str("o"), v); + v8::Local<v8::Value> res = CompileRun( + "function f() { return o[0]; }" + "for (var i = 0; i < 10; ++i) f();" + "%OptimizeFunctionOnNextCall(f);" + "f();"); + CHECK_EQ(42, res->Int32Value()); + ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); + ctx2->Exit(); + ctx1->Exit(); + ctx1.Dispose(); } + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(2, NumberOfGlobalObjects()); + ctx2.Dispose(); + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(0, NumberOfGlobalObjects()); +} + + +TEST(LeakGlobalContextViaMapProto) { + i::FLAG_allow_natives_syntax = true; + v8::HandleScope outer_scope; + v8::Persistent<v8::Context> ctx1 = v8::Context::New(); + v8::Persistent<v8::Context> ctx2 = v8::Context::New(); + ctx1->Enter(); + + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(4, NumberOfGlobalObjects()); + + { + v8::HandleScope inner_scope; + CompileRun("var v = { y: 42}"); + v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); + ctx2->Enter(); + ctx2->Global()->Set(v8_str("o"), v); + v8::Local<v8::Value> res = CompileRun( + "function f() {" + " var p = {x: 42};" + " p.__proto__ = o;" + " return p.x;" + "}" + "for (var i = 0; i < 10; ++i) f();" + "%OptimizeFunctionOnNextCall(f);" + "f();"); + CHECK_EQ(42, res->Int32Value()); + ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); + ctx2->Exit(); + ctx1->Exit(); + ctx1.Dispose(); + } + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(2, NumberOfGlobalObjects()); + ctx2.Dispose(); + HEAP->CollectAllAvailableGarbage(); + CHECK_EQ(0, NumberOfGlobalObjects()); +} + + +TEST(InstanceOfStubWriteBarrier) { + i::FLAG_allow_natives_syntax = true; +#ifdef DEBUG + i::FLAG_verify_heap = true; +#endif + InitializeVM(); + if (!i::V8::UseCrankshaft()) return; + v8::HandleScope outer_scope; + + { + v8::HandleScope scope; + CompileRun( + "function foo () { }" + "function mkbar () { return new (new Function(\"\")) (); }" + "function f (x) { return (x instanceof foo); }" + "function g () { f(mkbar()); }" + "f(new foo()); f(new foo());" + "%OptimizeFunctionOnNextCall(f);" + "f(new foo()); g();"); + } + + IncrementalMarking* marking = HEAP->incremental_marking(); + marking->Abort(); + marking->Start(); + + Handle<JSFunction> f = + v8::Utils::OpenHandle( + *v8::Handle<v8::Function>::Cast( + v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); + + CHECK(f->IsOptimized()); + + while (!Marking::IsBlack(Marking::MarkBitFrom(f->code())) && + !marking->IsStopped()) { + marking->Step(MB); + } + + CHECK(marking->IsMarking()); + + // Discard any pending GC requests otherwise we will get GC when we enter + // code below. + if (ISOLATE->stack_guard()->IsGCRequest()) { + ISOLATE->stack_guard()->Continue(GC_REQUEST); + } + + { + v8::HandleScope scope; + v8::Handle<v8::Object> global = v8::Context::GetCurrent()->Global(); + v8::Handle<v8::Function> g = + v8::Handle<v8::Function>::Cast(global->Get(v8_str("g"))); + g->Call(global, 0, NULL); + } + + HEAP->incremental_marking()->set_should_hurry(true); + HEAP->CollectGarbage(OLD_POINTER_SPACE); +} + + +TEST(PrototypeTransitionClearing) { + InitializeVM(); + v8::HandleScope scope; + + CompileRun( + "var base = {};" + "var live = [];" + "for (var i = 0; i < 10; i++) {" + " var object = {};" + " var prototype = {};" + " object.__proto__ = prototype;" + " if (i >= 3) live.push(object, prototype);" + "}"); + + Handle<JSObject> baseObject = + v8::Utils::OpenHandle( + *v8::Handle<v8::Object>::Cast( + v8::Context::GetCurrent()->Global()->Get(v8_str("base")))); + + // Verify that only dead prototype transitions are cleared. + CHECK_EQ(10, baseObject->map()->NumberOfProtoTransitions()); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + CHECK_EQ(10 - 3, baseObject->map()->NumberOfProtoTransitions()); + + // Verify that prototype transitions array was compacted. + FixedArray* trans = baseObject->map()->prototype_transitions(); + for (int i = 0; i < 10 - 3; i++) { + int j = Map::kProtoTransitionHeaderSize + + i * Map::kProtoTransitionElementsPerEntry; + CHECK(trans->get(j + Map::kProtoTransitionMapOffset)->IsMap()); + CHECK(trans->get(j + Map::kProtoTransitionPrototypeOffset)->IsJSObject()); + } + + // Make sure next prototype is placed on an old-space evacuation candidate. + Handle<JSObject> prototype; + PagedSpace* space = HEAP->old_pointer_space(); + do { + prototype = FACTORY->NewJSArray(32 * KB, FAST_ELEMENTS, TENURED); + } while (space->FirstPage() == space->LastPage() || + !space->LastPage()->Contains(prototype->address())); + + // Add a prototype on an evacuation candidate and verify that transition + // clearing correctly records slots in prototype transition array. + i::FLAG_always_compact = true; + Handle<Map> map(baseObject->map()); + CHECK(!space->LastPage()->Contains(map->prototype_transitions()->address())); + CHECK(space->LastPage()->Contains(prototype->address())); + baseObject->SetPrototype(*prototype, false)->ToObjectChecked(); + CHECK(map->GetPrototypeTransition(*prototype)->IsMap()); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + CHECK(map->GetPrototypeTransition(*prototype)->IsMap()); } diff --git a/test/cctest/test-lockers.cc b/test/cctest/test-lockers.cc index 7360da52..5035f876 100644 --- a/test/cctest/test-lockers.cc +++ b/test/cctest/test-lockers.cc @@ -204,7 +204,11 @@ static void StartJoinAndDeleteThreads(const i::List<JoinableThread*>& threads) { // Run many threads all locking on the same isolate TEST(IsolateLockingStress) { +#ifdef V8_TARGET_ARCH_MIPS + const int kNThreads = 50; +#else const int kNThreads = 100; +#endif i::List<JoinableThread*> threads(kNThreads); v8::Isolate* isolate = v8::Isolate::New(); for (int i = 0; i < kNThreads; i++) { @@ -237,7 +241,7 @@ class IsolateNonlockingThread : public JoinableThread { // Run many threads each accessing its own isolate without locking TEST(MultithreadedParallelIsolates) { -#ifdef V8_TARGET_ARCH_ARM +#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) const int kNThreads = 10; #else const int kNThreads = 50; @@ -275,7 +279,11 @@ class IsolateNestedLockingThread : public JoinableThread { // Run many threads with nested locks TEST(IsolateNestedLocking) { +#ifdef V8_TARGET_ARCH_MIPS + const int kNThreads = 50; +#else const int kNThreads = 100; +#endif v8::Isolate* isolate = v8::Isolate::New(); i::List<JoinableThread*> threads(kNThreads); for (int i = 0; i < kNThreads; i++) { @@ -311,7 +319,7 @@ class SeparateIsolatesLocksNonexclusiveThread : public JoinableThread { // Run parallel threads that lock and access different isolates in parallel TEST(SeparateIsolatesLocksNonexclusive) { -#ifdef V8_TARGET_ARCH_ARM +#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) const int kNThreads = 50; #else const int kNThreads = 100; @@ -385,7 +393,7 @@ class LockerUnlockerThread : public JoinableThread { // Use unlocker inside of a Locker, multiple threads. TEST(LockerUnlocker) { -#ifdef V8_TARGET_ARCH_ARM +#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) const int kNThreads = 50; #else const int kNThreads = 100; @@ -438,7 +446,7 @@ class LockTwiceAndUnlockThread : public JoinableThread { // Use Unlocker inside two Lockers. TEST(LockTwiceAndUnlock) { -#ifdef V8_TARGET_ARCH_ARM +#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) const int kNThreads = 50; #else const int kNThreads = 100; @@ -559,7 +567,11 @@ class LockUnlockLockThread : public JoinableThread { // Locker inside an Unlocker inside a Locker. TEST(LockUnlockLockMultithreaded) { +#ifdef V8_TARGET_ARCH_MIPS + const int kNThreads = 50; +#else const int kNThreads = 100; +#endif v8::Isolate* isolate = v8::Isolate::New(); Persistent<v8::Context> context; { @@ -606,7 +618,11 @@ class LockUnlockLockDefaultIsolateThread : public JoinableThread { // Locker inside an Unlocker inside a Locker for default isolate. TEST(LockUnlockLockDefaultIsolateMultithreaded) { +#ifdef V8_TARGET_ARCH_MIPS + const int kNThreads = 50; +#else const int kNThreads = 100; +#endif Persistent<v8::Context> context; { v8::Locker locker_; @@ -639,3 +655,68 @@ TEST(Regress1433) { isolate->Dispose(); } } + + +static const char* kSimpleExtensionSource = + "(function Foo() {" + " return 4;" + "})() "; + +class IsolateGenesisThread : public JoinableThread { + public: + IsolateGenesisThread(int count, const char* extension_names[]) + : JoinableThread("IsolateGenesisThread"), + count_(count), + extension_names_(extension_names) + {} + + virtual void Run() { + v8::Isolate* isolate = v8::Isolate::New(); + { + v8::Isolate::Scope isolate_scope(isolate); + CHECK(!i::Isolate::Current()->has_installed_extensions()); + v8::ExtensionConfiguration extensions(count_, extension_names_); + v8::Persistent<v8::Context> context = v8::Context::New(&extensions); + CHECK(i::Isolate::Current()->has_installed_extensions()); + context.Dispose(); + } + isolate->Dispose(); + } + private: + int count_; + const char** extension_names_; +}; + +// Test installing extensions in separate isolates concurrently. +// http://code.google.com/p/v8/issues/detail?id=1821 +TEST(ExtensionsRegistration) { +#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) + const int kNThreads = 10; +#else + const int kNThreads = 40; +#endif + v8::RegisterExtension(new v8::Extension("test0", + kSimpleExtensionSource)); + v8::RegisterExtension(new v8::Extension("test1", + kSimpleExtensionSource)); + v8::RegisterExtension(new v8::Extension("test2", + kSimpleExtensionSource)); + v8::RegisterExtension(new v8::Extension("test3", + kSimpleExtensionSource)); + v8::RegisterExtension(new v8::Extension("test4", + kSimpleExtensionSource)); + v8::RegisterExtension(new v8::Extension("test5", + kSimpleExtensionSource)); + v8::RegisterExtension(new v8::Extension("test6", + kSimpleExtensionSource)); + v8::RegisterExtension(new v8::Extension("test7", + kSimpleExtensionSource)); + const char* extension_names[] = { "test0", "test1", + "test2", "test3", "test4", + "test5", "test6", "test7" }; + i::List<JoinableThread*> threads(kNThreads); + for (int i = 0; i < kNThreads; i++) { + threads.Add(new IsolateGenesisThread(8, extension_names)); + } + StartJoinAndDeleteThreads(threads); +} diff --git a/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc index f536e6b1..6847ef7e 100644 --- a/test/cctest/test-log-stack-tracer.cc +++ b/test/cctest/test-log-stack-tracer.cc @@ -307,6 +307,7 @@ TEST(CFromJSStackTrace) { // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace" int base = 0; CHECK_GT(sample.frames_count, base + 1); + CHECK(IsAddressWithinFuncCode("JSFuncDoTrace", sample.stack[base + 0])); CHECK(IsAddressWithinFuncCode("JSTrace", sample.stack[base + 1])); } diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc index 72e663c4..6f2324db 100644 --- a/test/cctest/test-log.cc +++ b/test/cctest/test-log.cc @@ -494,7 +494,7 @@ TEST(EquivalenceOfLoggingAndTraversal) { " (function a(j) { return function b() { return j; } })(100);\n" "})(this);"); v8::V8::PauseProfiler(); - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); LOGGER->StringEvent("test-logging-done", ""); // Iterate heap to find compiled functions, will write to log. diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc index dcb51a0b..973af196 100644 --- a/test/cctest/test-mark-compact.cc +++ b/test/cctest/test-mark-compact.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// 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: @@ -27,6 +27,14 @@ #include <stdlib.h> +#ifdef __linux__ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#endif + #include "v8.h" #include "global-handles.h" @@ -44,21 +52,21 @@ static void InitializeVM() { } -TEST(MarkingStack) { +TEST(MarkingDeque) { int mem_size = 20 * kPointerSize; byte* mem = NewArray<byte>(20*kPointerSize); Address low = reinterpret_cast<Address>(mem); Address high = low + mem_size; - MarkingStack s; + MarkingDeque s; s.Initialize(low, high); Address address = NULL; - while (!s.is_full()) { - s.Push(HeapObject::FromAddress(address)); + while (!s.IsFull()) { + s.PushBlack(HeapObject::FromAddress(address)); address += kPointerSize; } - while (!s.is_empty()) { + while (!s.IsEmpty()) { Address value = s.Pop()->address(); address -= kPointerSize; CHECK_EQ(address, value); @@ -78,7 +86,7 @@ TEST(Promotion) { // from new space. FLAG_gc_global = true; FLAG_always_compact = true; - HEAP->ConfigureHeap(2*256*KB, 4*MB, 4*MB); + HEAP->ConfigureHeap(2*256*KB, 8*MB, 8*MB); InitializeVM(); @@ -86,7 +94,7 @@ TEST(Promotion) { // Allocate a fixed array in the new space. int array_size = - (HEAP->MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / + (Page::kMaxNonCodeHeapObjectSize - FixedArray::kHeaderSize) / (kPointerSize * 4); Object* obj = HEAP->AllocateFixedArray(array_size)->ToObjectChecked(); @@ -104,7 +112,7 @@ TEST(Promotion) { TEST(NoPromotion) { - HEAP->ConfigureHeap(2*256*KB, 4*MB, 4*MB); + HEAP->ConfigureHeap(2*256*KB, 8*MB, 8*MB); // Test the situation that some objects in new space are promoted to // the old space @@ -116,9 +124,12 @@ TEST(NoPromotion) { HEAP->CollectGarbage(OLD_POINTER_SPACE); // Allocate a big Fixed array in the new space. - int size = (HEAP->MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / - kPointerSize; - Object* obj = HEAP->AllocateFixedArray(size)->ToObjectChecked(); + int max_size = + Min(Page::kMaxNonCodeHeapObjectSize, HEAP->MaxObjectSizeInNewSpace()); + + int length = (max_size - FixedArray::kHeaderSize) / (2*kPointerSize); + Object* obj = i::Isolate::Current()->heap()->AllocateFixedArray(length)-> + ToObjectChecked(); Handle<FixedArray> array(FixedArray::cast(obj)); @@ -139,9 +150,6 @@ TEST(NoPromotion) { // Call mark compact GC, and it should pass. HEAP->CollectGarbage(OLD_POINTER_SPACE); - - // array should not be promoted because the old space is full. - CHECK(HEAP->InSpace(*array, NEW_SPACE)); } @@ -228,6 +236,8 @@ TEST(MarkCompactCollector) { } +// TODO(1600): compaction of map space is temporary removed from GC. +#if 0 static Handle<Map> CreateMap() { return FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); } @@ -252,11 +262,11 @@ TEST(MapCompact) { // be able to trigger map compaction. // To give an additional chance to fail, try to force compaction which // should be impossible right now. - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kForceCompactionMask); // And now map pointers should be encodable again. CHECK(HEAP->map_space()->MapPointersEncodable()); } - +#endif static int gc_starts = 0; static int gc_ends = 0; @@ -442,3 +452,100 @@ TEST(EmptyObjectGroups) { global_handles->AddImplicitReferences( Handle<HeapObject>::cast(object).location(), NULL, 0); } + + +// Here is a memory use test that uses /proc, and is therefore Linux-only. We +// do not care how much memory the simulator uses, since it is only there for +// debugging purposes. +#if defined(__linux__) && !defined(USE_SIMULATOR) + + +static uintptr_t ReadLong(char* buffer, intptr_t* position, int base) { + char* end_address = buffer + *position; + uintptr_t result = strtoul(buffer + *position, &end_address, base); + CHECK(result != ULONG_MAX || errno != ERANGE); + CHECK(end_address > buffer + *position); + *position = end_address - buffer; + return result; +} + + +static intptr_t MemoryInUse() { + intptr_t memory_use = 0; + + int fd = open("/proc/self/maps", O_RDONLY); + if (fd < 0) return -1; + + const int kBufSize = 10000; + char buffer[kBufSize]; + int length = read(fd, buffer, kBufSize); + intptr_t line_start = 0; + CHECK_LT(length, kBufSize); // Make the buffer bigger. + CHECK_GT(length, 0); // We have to find some data in the file. + while (line_start < length) { + if (buffer[line_start] == '\n') { + line_start++; + continue; + } + intptr_t position = line_start; + uintptr_t start = ReadLong(buffer, &position, 16); + CHECK_EQ(buffer[position++], '-'); + uintptr_t end = ReadLong(buffer, &position, 16); + CHECK_EQ(buffer[position++], ' '); + CHECK(buffer[position] == '-' || buffer[position] == 'r'); + bool read_permission = (buffer[position++] == 'r'); + CHECK(buffer[position] == '-' || buffer[position] == 'w'); + bool write_permission = (buffer[position++] == 'w'); + CHECK(buffer[position] == '-' || buffer[position] == 'x'); + bool execute_permission = (buffer[position++] == 'x'); + CHECK(buffer[position] == '-' || buffer[position] == 'p'); + bool private_mapping = (buffer[position++] == 'p'); + CHECK_EQ(buffer[position++], ' '); + uintptr_t offset = ReadLong(buffer, &position, 16); + USE(offset); + CHECK_EQ(buffer[position++], ' '); + uintptr_t major = ReadLong(buffer, &position, 16); + USE(major); + CHECK_EQ(buffer[position++], ':'); + uintptr_t minor = ReadLong(buffer, &position, 16); + USE(minor); + CHECK_EQ(buffer[position++], ' '); + uintptr_t inode = ReadLong(buffer, &position, 10); + while (position < length && buffer[position] != '\n') position++; + if ((read_permission || write_permission || execute_permission) && + private_mapping && inode == 0) { + memory_use += (end - start); + } + + line_start = position; + } + close(fd); + return memory_use; +} + + +TEST(BootUpMemoryUse) { + intptr_t initial_memory = MemoryInUse(); + FLAG_crankshaft = false; // Avoid flakiness. + // Only Linux has the proc filesystem and only if it is mapped. If it's not + // there we just skip the test. + if (initial_memory >= 0) { + InitializeVM(); + intptr_t booted_memory = MemoryInUse(); + if (sizeof(initial_memory) == 8) { + if (v8::internal::Snapshot::IsEnabled()) { + CHECK_LE(booted_memory - initial_memory, 6686 * 1024); // 6476. + } else { + CHECK_LE(booted_memory - initial_memory, 6809 * 1024); // 6628. + } + } else { + if (v8::internal::Snapshot::IsEnabled()) { + CHECK_LE(booted_memory - initial_memory, 6532 * 1024); // 6388. + } else { + CHECK_LE(booted_memory - initial_memory, 6940 * 1024); // 6456 + } + } + } +} + +#endif // __linux__ and !USE_SIMULATOR diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc index d98b6753..6bcae7c3 100755 --- a/test/cctest/test-parsing.cc +++ b/test/cctest/test-parsing.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// 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: @@ -32,6 +32,7 @@ #include "v8.h" #include "cctest.h" +#include "compiler.h" #include "execution.h" #include "isolate.h" #include "parser.h" @@ -62,18 +63,19 @@ TEST(ScanKeywords) { int length = i::StrLength(key_token.keyword); CHECK(static_cast<int>(sizeof(buffer)) >= length); { - i::Utf8ToUC16CharacterStream stream(keyword, length); - i::JavaScriptScanner scanner(&unicode_cache); - // The scanner should parse 'let' as Token::LET for this test. - scanner.SetHarmonyBlockScoping(true); + i::Utf8ToUtf16CharacterStream stream(keyword, length); + i::Scanner scanner(&unicode_cache); + // The scanner should parse Harmony keywords for this test. + scanner.SetHarmonyScoping(true); + scanner.SetHarmonyModules(true); scanner.Initialize(&stream); CHECK_EQ(key_token.token, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next()); } // Removing characters will make keyword matching fail. { - i::Utf8ToUC16CharacterStream stream(keyword, length - 1); - i::JavaScriptScanner scanner(&unicode_cache); + i::Utf8ToUtf16CharacterStream stream(keyword, length - 1); + i::Scanner scanner(&unicode_cache); scanner.Initialize(&stream); CHECK_EQ(i::Token::IDENTIFIER, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next()); @@ -83,8 +85,8 @@ TEST(ScanKeywords) { for (int j = 0; j < static_cast<int>(ARRAY_SIZE(chars_to_append)); ++j) { memmove(buffer, keyword, length); buffer[length] = chars_to_append[j]; - i::Utf8ToUC16CharacterStream stream(buffer, length + 1); - i::JavaScriptScanner scanner(&unicode_cache); + i::Utf8ToUtf16CharacterStream stream(buffer, length + 1); + i::Scanner scanner(&unicode_cache); scanner.Initialize(&stream); CHECK_EQ(i::Token::IDENTIFIER, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next()); @@ -93,8 +95,8 @@ TEST(ScanKeywords) { { memmove(buffer, keyword, length); buffer[length - 1] = '_'; - i::Utf8ToUC16CharacterStream stream(buffer, length); - i::JavaScriptScanner scanner(&unicode_cache); + i::Utf8ToUtf16CharacterStream stream(buffer, length); + i::Scanner scanner(&unicode_cache); scanner.Initialize(&stream); CHECK_EQ(i::Token::IDENTIFIER, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next()); @@ -229,7 +231,7 @@ TEST(Preparsing) { CHECK_EQ(11, error_location.end_pos); // Should not crash. const char* message = pre_impl->BuildMessage(); - i::Vector<const char*> args = pre_impl->BuildArgs(); + pre_impl->BuildArgs(); CHECK_GT(strlen(message), 0); } @@ -253,17 +255,18 @@ TEST(StandAlonePreParser) { uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit(); for (int i = 0; programs[i]; i++) { const char* program = programs[i]; - i::Utf8ToUC16CharacterStream stream( + i::Utf8ToUtf16CharacterStream stream( reinterpret_cast<const i::byte*>(program), static_cast<unsigned>(strlen(program))); i::CompleteParserRecorder log; - i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); + i::Scanner scanner(i::Isolate::Current()->unicode_cache()); scanner.Initialize(&stream); + int flags = i::kAllowLazy | i::kAllowNativesSyntax; v8::preparser::PreParser::PreParseResult result = v8::preparser::PreParser::PreParseProgram(&scanner, &log, - true, + flags, stack_limit); CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result); i::ScriptDataImpl data(log.ExtractData()); @@ -272,6 +275,43 @@ TEST(StandAlonePreParser) { } +TEST(StandAlonePreParserNoNatives) { + v8::V8::Initialize(); + + int marker; + i::Isolate::Current()->stack_guard()->SetStackLimit( + reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); + + const char* programs[] = { + "%ArgleBargle(glop);", + "var x = %_IsSmi(42);", + NULL + }; + + uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit(); + for (int i = 0; programs[i]; i++) { + const char* program = programs[i]; + i::Utf8ToUtf16CharacterStream stream( + reinterpret_cast<const i::byte*>(program), + static_cast<unsigned>(strlen(program))); + i::CompleteParserRecorder log; + i::Scanner scanner(i::Isolate::Current()->unicode_cache()); + scanner.Initialize(&stream); + + // Flags don't allow natives syntax. + v8::preparser::PreParser::PreParseResult result = + v8::preparser::PreParser::PreParseProgram(&scanner, + &log, + i::kAllowLazy, + stack_limit); + CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result); + i::ScriptDataImpl data(log.ExtractData()); + // Data contains syntax error. + CHECK(data.has_error()); + } +} + + TEST(RegressChromium62639) { v8::V8::Initialize(); @@ -286,8 +326,9 @@ TEST(RegressChromium62639) { // and then used the invalid currently scanned literal. This always // failed in debug mode, and sometimes crashed in release mode. - i::Utf8ToUC16CharacterStream stream(reinterpret_cast<const i::byte*>(program), - static_cast<unsigned>(strlen(program))); + i::Utf8ToUtf16CharacterStream stream( + reinterpret_cast<const i::byte*>(program), + static_cast<unsigned>(strlen(program))); i::ScriptDataImpl* data = i::ParserApi::PreParse(&stream, NULL, false); CHECK(data->HasError()); @@ -310,17 +351,17 @@ TEST(Regress928) { "try { } catch (e) { var foo = function () { /* first */ } }" "var bar = function () { /* second */ }"; - i::Utf8ToUC16CharacterStream stream(reinterpret_cast<const i::byte*>(program), - static_cast<unsigned>(strlen(program))); - i::ScriptDataImpl* data = - i::ParserApi::PartialPreParse(&stream, NULL, false); + v8::HandleScope handles; + i::Handle<i::String> source( + FACTORY->NewStringFromAscii(i::CStrVector(program))); + i::ScriptDataImpl* data = i::ParserApi::PartialPreParse(source, NULL, false); CHECK(!data->HasError()); data->Initialize(); int first_function = static_cast<int>(strstr(program, "function") - program); - int first_lbrace = first_function + static_cast<int>(strlen("function () ")); + int first_lbrace = first_function + i::StrLength("function () "); CHECK_EQ('{', program[first_lbrace]); i::FunctionEntry entry1 = data->GetFunctionEntry(first_lbrace); CHECK(!entry1.is_valid()); @@ -328,7 +369,7 @@ TEST(Regress928) { int second_function = static_cast<int>(strstr(program + first_lbrace, "function") - program); int second_lbrace = - second_function + static_cast<int>(strlen("function () ")); + second_function + i::StrLength("function () "); CHECK_EQ('{', program[second_lbrace]); i::FunctionEntry entry2 = data->GetFunctionEntry(second_lbrace); CHECK(entry2.is_valid()); @@ -352,11 +393,11 @@ TEST(PreParseOverflow) { uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit(); - i::Utf8ToUC16CharacterStream stream( + i::Utf8ToUtf16CharacterStream stream( reinterpret_cast<const i::byte*>(*program), static_cast<unsigned>(kProgramSize)); i::CompleteParserRecorder log; - i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); + i::Scanner scanner(i::Isolate::Current()->unicode_cache()); scanner.Initialize(&stream); @@ -409,10 +450,10 @@ void TestCharacterStream(const char* ascii_source, i::Handle<i::String> uc16_string( FACTORY->NewExternalStringFromTwoByte(&resource)); - i::ExternalTwoByteStringUC16CharacterStream uc16_stream( + i::ExternalTwoByteStringUtf16CharacterStream uc16_stream( i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end); - i::GenericStringUC16CharacterStream string_stream(ascii_string, start, end); - i::Utf8ToUC16CharacterStream utf8_stream( + i::GenericStringUtf16CharacterStream string_stream(ascii_string, start, end); + i::Utf8ToUtf16CharacterStream utf8_stream( reinterpret_cast<const i::byte*>(ascii_source), end); utf8_stream.SeekForward(start); @@ -535,12 +576,14 @@ TEST(Utf8CharacterStream) { char buffer[kAllUtf8CharsSizeU]; unsigned cursor = 0; for (int i = 0; i <= kMaxUC16Char; i++) { - cursor += unibrow::Utf8::Encode(buffer + cursor, i); + cursor += unibrow::Utf8::Encode(buffer + cursor, + i, + unibrow::Utf16::kNoPreviousCharacter); } ASSERT(cursor == kAllUtf8CharsSizeU); - i::Utf8ToUC16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer), - kAllUtf8CharsSizeU); + i::Utf8ToUtf16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer), + kAllUtf8CharsSizeU); for (int i = 0; i <= kMaxUC16Char; i++) { CHECK_EQU(i, stream.pos()); int32_t c = stream.Advance(); @@ -570,11 +613,11 @@ TEST(Utf8CharacterStream) { #undef CHECK_EQU -void TestStreamScanner(i::UC16CharacterStream* stream, +void TestStreamScanner(i::Utf16CharacterStream* stream, i::Token::Value* expected_tokens, int skip_pos = 0, // Zero means not skipping. int skip_to = 0) { - i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); + i::Scanner scanner(i::Isolate::Current()->unicode_cache()); scanner.Initialize(stream); int i = 0; @@ -593,8 +636,8 @@ TEST(StreamScanner) { v8::V8::Initialize(); const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib"; - i::Utf8ToUC16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1), - static_cast<unsigned>(strlen(str1))); + i::Utf8ToUtf16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1), + static_cast<unsigned>(strlen(str1))); i::Token::Value expectations1[] = { i::Token::LBRACE, i::Token::IDENTIFIER, @@ -612,8 +655,8 @@ TEST(StreamScanner) { TestStreamScanner(&stream1, expectations1, 0, 0); const char* str2 = "case default const {THIS\nPART\nSKIPPED} do"; - i::Utf8ToUC16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2), - static_cast<unsigned>(strlen(str2))); + i::Utf8ToUtf16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2), + static_cast<unsigned>(strlen(str2))); i::Token::Value expectations2[] = { i::Token::CASE, i::Token::DEFAULT, @@ -643,7 +686,7 @@ TEST(StreamScanner) { for (int i = 0; i <= 4; i++) { expectations3[6 - i] = i::Token::ILLEGAL; expectations3[5 - i] = i::Token::EOS; - i::Utf8ToUC16CharacterStream stream3( + i::Utf8ToUtf16CharacterStream stream3( reinterpret_cast<const i::byte*>(str3), static_cast<unsigned>(strlen(str3))); TestStreamScanner(&stream3, expectations3, 1, 1 + i); @@ -652,10 +695,10 @@ TEST(StreamScanner) { void TestScanRegExp(const char* re_source, const char* expected) { - i::Utf8ToUC16CharacterStream stream( + i::Utf8ToUtf16CharacterStream stream( reinterpret_cast<const i::byte*>(re_source), static_cast<unsigned>(strlen(re_source))); - i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); + i::Scanner scanner(i::Isolate::Current()->unicode_cache()); scanner.Initialize(&stream); i::Token::Value start = scanner.peek(); @@ -708,25 +751,320 @@ TEST(RegExpScanning) { } -void TestParserSync(i::Handle<i::String> source, bool allow_lazy) { +static int Utf8LengthHelper(const char* s) { + int len = i::StrLength(s); + int character_length = len; + for (int i = 0; i < len; i++) { + unsigned char c = s[i]; + int input_offset = 0; + int output_adjust = 0; + if (c > 0x7f) { + if (c < 0xc0) continue; + if (c >= 0xf0) { + if (c >= 0xf8) { + // 5 and 6 byte UTF-8 sequences turn into a kBadChar for each UTF-8 + // byte. + continue; // Handle first UTF-8 byte. + } + if ((c & 7) == 0 && ((s[i + 1] & 0x30) == 0)) { + // This 4 byte sequence could have been coded as a 3 byte sequence. + // Record a single kBadChar for the first byte and continue. + continue; + } + input_offset = 3; + // 4 bytes of UTF-8 turn into 2 UTF-16 code units. + character_length -= 2; + } else if (c >= 0xe0) { + if ((c & 0xf) == 0 && ((s[i + 1] & 0x20) == 0)) { + // This 3 byte sequence could have been coded as a 2 byte sequence. + // Record a single kBadChar for the first byte and continue. + continue; + } + input_offset = 2; + // 3 bytes of UTF-8 turn into 1 UTF-16 code unit. + output_adjust = 2; + } else { + if ((c & 0x1e) == 0) { + // This 2 byte sequence could have been coded as a 1 byte sequence. + // Record a single kBadChar for the first byte and continue. + continue; + } + input_offset = 1; + // 2 bytes of UTF-8 turn into 1 UTF-16 code unit. + output_adjust = 1; + } + bool bad = false; + for (int j = 1; j <= input_offset; j++) { + if ((s[i + j] & 0xc0) != 0x80) { + // Bad UTF-8 sequence turns the first in the sequence into kBadChar, + // which is a single UTF-16 code unit. + bad = true; + break; + } + } + if (!bad) { + i += input_offset; + character_length -= output_adjust; + } + } + } + return character_length; +} + + +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 + // nested in the global scope of a program. 'inner source' is the + // source code that determines the part of the source belonging + // to the nested scope. 'outer_prefix' and 'outer_suffix' are + // parts of the source that belong to the global scope. + struct SourceData { + const char* outer_prefix; + const char* inner_source; + const char* outer_suffix; + i::ScopeType scope_type; + i::LanguageMode language_mode; + }; + + const SourceData source_data[] = { + { " with ({}) ", "{ block; }", " more;", i::WITH_SCOPE, i::CLASSIC_MODE }, + { " with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE, i::CLASSIC_MODE }, + { " with ({}) ", "{\n" + " block;\n" + " }", "\n" + " more;", i::WITH_SCOPE, i::CLASSIC_MODE }, + { " with ({}) ", "statement;", " more;", i::WITH_SCOPE, i::CLASSIC_MODE }, + { " with ({}) ", "statement", "\n" + " more;", i::WITH_SCOPE, i::CLASSIC_MODE }, + { " with ({})\n" + " ", "statement;", "\n" + " more;", i::WITH_SCOPE, i::CLASSIC_MODE }, + { " try {} catch ", "(e) { block; }", " more;", + i::CATCH_SCOPE, i::CLASSIC_MODE }, + { " try {} catch ", "(e) { block; }", "; more;", + i::CATCH_SCOPE, i::CLASSIC_MODE }, + { " try {} catch ", "(e) {\n" + " block;\n" + " }", "\n" + " more;", i::CATCH_SCOPE, i::CLASSIC_MODE }, + { " try {} catch ", "(e) { block; }", " finally { block; } more;", + i::CATCH_SCOPE, i::CLASSIC_MODE }, + { " start;\n" + " ", "{ let block; }", " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " start;\n" + " ", "{ let block; }", "; more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " start;\n" + " ", "{\n" + " let block;\n" + " }", "\n" + " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " start;\n" + " function fun", "(a,b) { infunction; }", " more;", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + { " start;\n" + " function fun", "(a,b) {\n" + " infunction;\n" + " }", "\n" + " more;", i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + { " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;", + i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;", + i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x = 1 ; x < 10; ++ x) {\n" + " block;\n" + " }", "\n" + " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;", + i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x = 1 ; x < 10; ++ x) statement", "\n" + " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x = 1 ; x < 10; ++ x)\n" + " statement;", "\n" + " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x in {}) { block; }", " more;", + i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x in {}) { block; }", "; more;", + i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x in {}) {\n" + " block;\n" + " }", "\n" + " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x in {}) statement;", " more;", + i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x in {}) statement", "\n" + " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + { " for ", "(let x in {})\n" + " statement;", "\n" + " more;", i::BLOCK_SCOPE, i::EXTENDED_MODE }, + // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw + // the preparser off in terms of byte offsets. + // 6 byte encoding. + { " 'foo\355\240\201\355\260\211';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // 4 byte encoding. + { " 'foo\360\220\220\212';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // 3 byte encoding of \u0fff. + { " 'foo\340\277\277';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Broken 6 byte encoding with missing last byte. + { " 'foo\355\240\201\355\211';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Broken 3 byte encoding of \u0fff with missing last byte. + { " 'foo\340\277';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Broken 3 byte encoding of \u0fff with missing 2 last bytes. + { " 'foo\340';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Broken 3 byte encoding of \u00ff should be a 2 byte encoding. + { " 'foo\340\203\277';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Broken 3 byte encoding of \u007f should be a 2 byte encoding. + { " 'foo\340\201\277';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Unpaired lead surrogate. + { " 'foo\355\240\201';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Unpaired lead surrogate where following code point is a 3 byte sequence. + { " 'foo\355\240\201\340\277\277';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Unpaired lead surrogate where following code point is a 4 byte encoding + // of a trail surrogate. + { " 'foo\355\240\201\360\215\260\211';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Unpaired trail surrogate. + { " 'foo\355\260\211';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // 2 byte encoding of \u00ff. + { " 'foo\303\277';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Broken 2 byte encoding of \u00ff with missing last byte. + { " 'foo\303';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Broken 2 byte encoding of \u007f should be a 1 byte encoding. + { " 'foo\301\277';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Illegal 5 byte encoding. + { " 'foo\370\277\277\277\277';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Illegal 6 byte encoding. + { " 'foo\374\277\277\277\277\277';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Illegal 0xfe byte + { " 'foo\376\277\277\277\277\277\277';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + // Illegal 0xff byte + { " 'foo\377\277\277\277\277\277\277\277';\n" + " (function fun", "(a,b) { infunction; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + { " 'foo';\n" + " (function fun", "(a,b) { 'bar\355\240\201\355\260\213'; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + { " 'foo';\n" + " (function fun", "(a,b) { 'bar\360\220\220\214'; }", ")();", + i::FUNCTION_SCOPE, i::CLASSIC_MODE }, + { NULL, NULL, NULL, i::EVAL_SCOPE, i::CLASSIC_MODE } + }; + + v8::HandleScope handles; + v8::Persistent<v8::Context> context = v8::Context::New(); + v8::Context::Scope context_scope(context); + + int marker; + i::Isolate::Current()->stack_guard()->SetStackLimit( + reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); + i::FLAG_harmony_scoping = true; + + for (int i = 0; source_data[i].outer_prefix; i++) { + int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix); + int kInnerLen = Utf8LengthHelper(source_data[i].inner_source); + int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix); + int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix); + int kInnerByteLen = i::StrLength(source_data[i].inner_source); + int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix); + int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen; + int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen; + i::Vector<char> program = i::Vector<char>::New(kProgramByteSize + 1); + i::OS::SNPrintF(program, "%s%s%s", + source_data[i].outer_prefix, + source_data[i].inner_source, + source_data[i].outer_suffix); + + // Parse program source. + i::Handle<i::String> source( + FACTORY->NewStringFromUtf8(i::CStrVector(program.start()))); + CHECK_EQ(source->length(), kProgramSize); + i::Handle<i::Script> script = FACTORY->NewScript(source); + i::Parser parser(script, i::kAllowLazy | i::EXTENDED_MODE, NULL, NULL); + i::CompilationInfo info(script); + info.MarkAsGlobal(); + info.SetLanguageMode(source_data[i].language_mode); + i::FunctionLiteral* function = parser.ParseProgram(&info); + CHECK(function != NULL); + + // Check scope types and positions. + i::Scope* scope = function->scope(); + CHECK(scope->is_global_scope()); + CHECK_EQ(scope->start_position(), 0); + CHECK_EQ(scope->end_position(), kProgramSize); + CHECK_EQ(scope->inner_scopes()->length(), 1); + + i::Scope* inner_scope = scope->inner_scopes()->at(0); + CHECK_EQ(inner_scope->type(), source_data[i].scope_type); + CHECK_EQ(inner_scope->start_position(), kPrefixLen); + // The end position of a token is one position after the last + // character belonging to that token. + CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen); + } +} + + +void TestParserSync(i::Handle<i::String> source, int flags) { uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit(); + bool harmony_scoping = ((i::kLanguageModeMask & flags) == i::EXTENDED_MODE); // Preparse the data. i::CompleteParserRecorder log; - i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache()); - i::GenericStringUC16CharacterStream stream(source, 0, source->length()); + i::Scanner scanner(i::Isolate::Current()->unicode_cache()); + i::GenericStringUtf16CharacterStream stream(source, 0, source->length()); + scanner.SetHarmonyScoping(harmony_scoping); scanner.Initialize(&stream); v8::preparser::PreParser::PreParseResult result = v8::preparser::PreParser::PreParseProgram( - &scanner, &log, allow_lazy, stack_limit); + &scanner, &log, flags, stack_limit); CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result); i::ScriptDataImpl data(log.ExtractData()); // Parse the data i::Handle<i::Script> script = FACTORY->NewScript(source); - i::Parser parser(script, false, NULL, NULL); - i::FunctionLiteral* function = - parser.ParseProgram(source, true, i::kNonStrictMode); + bool save_harmony_scoping = i::FLAG_harmony_scoping; + i::FLAG_harmony_scoping = harmony_scoping; + i::Parser parser(script, flags, NULL, NULL); + i::CompilationInfo info(script); + info.MarkAsGlobal(); + i::FunctionLiteral* function = parser.ParseProgram(&info); + i::FLAG_harmony_scoping = save_harmony_scoping; i::String* type_string = NULL; if (function == NULL) { @@ -779,6 +1117,23 @@ void TestParserSync(i::Handle<i::String> source, bool allow_lazy) { } +void TestParserSyncWithFlags(i::Handle<i::String> source) { + static const int kFlagsCount = 6; + const int flags[kFlagsCount] = { + i::kNoParsingFlags | i::CLASSIC_MODE, + i::kNoParsingFlags | i::STRICT_MODE, + i::kNoParsingFlags | i::EXTENDED_MODE, + i::kAllowLazy | i::CLASSIC_MODE, + i::kAllowLazy | i::STRICT_MODE, + i::kAllowLazy | i::EXTENDED_MODE + }; + + for (int k = 0; k < kFlagsCount; ++k) { + TestParserSync(source, flags[k]); + } +} + + TEST(ParserSync) { const char* context_data[][2] = { { "", "" }, @@ -876,8 +1231,7 @@ TEST(ParserSync) { CHECK(length == kProgramSize); i::Handle<i::String> source = FACTORY->NewStringFromAscii(i::CStrVector(program.start())); - TestParserSync(source, true); - TestParserSync(source, false); + TestParserSyncWithFlags(source); } } } diff --git a/test/cctest/test-platform-linux.cc b/test/cctest/test-platform-linux.cc index 756b9473..2a8d4978 100644 --- a/test/cctest/test-platform-linux.cc +++ b/test/cctest/test-platform-linux.cc @@ -67,7 +67,7 @@ TEST(BusyLock) { TEST(VirtualMemory) { - OS::Setup(); + OS::SetUp(); VirtualMemory* vm = new VirtualMemory(1 * MB); CHECK(vm->IsReserved()); void* block_addr = vm->address(); diff --git a/test/cctest/test-platform-win32.cc b/test/cctest/test-platform-win32.cc index 9bd0014c..36b30aac 100644 --- a/test/cctest/test-platform-win32.cc +++ b/test/cctest/test-platform-win32.cc @@ -13,7 +13,7 @@ using namespace ::v8::internal; TEST(VirtualMemory) { - OS::Setup(); + OS::SetUp(); VirtualMemory* vm = new VirtualMemory(1 * MB); CHECK(vm->IsReserved()); void* block_addr = vm->address(); diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc index 76fd244e..def829c2 100644 --- a/test/cctest/test-profile-generator.cc +++ b/test/cctest/test-profile-generator.cc @@ -52,7 +52,7 @@ TEST(TokenEnumerator) { CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1))); } CHECK(!i::TokenEnumeratorTester::token_removed(&te)->at(2)); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); CHECK(i::TokenEnumeratorTester::token_removed(&te)->at(2)); CHECK_EQ(1, te.GetTokenId(*v8::Utils::OpenHandle(*token2))); CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1))); diff --git a/test/cctest/test-random.cc b/test/cctest/test-random.cc new file mode 100644 index 00000000..a1f49318 --- /dev/null +++ b/test/cctest/test-random.cc @@ -0,0 +1,109 @@ +// 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. + + +#include "v8.h" + +#include "cctest.h" +#include "compiler.h" +#include "execution.h" +#include "isolate.h" + + +using namespace v8::internal; + +static v8::Persistent<v8::Context> env; + + +void SetSeeds(Handle<ByteArray> seeds, uint32_t state0, uint32_t state1) { + for (int i = 0; i < 4; i++) { + seeds->set(i, static_cast<byte>(state0 >> (i * kBitsPerByte))); + seeds->set(i + 4, static_cast<byte>(state1 >> (i * kBitsPerByte))); + } +} + + +void TestSeeds(Handle<JSFunction> fun, + Handle<Context> context, + uint32_t state0, + uint32_t state1) { + bool has_pending_exception; + Handle<JSObject> global(context->global()); + Handle<ByteArray> seeds(context->random_seed()); + + SetSeeds(seeds, state0, state1); + Handle<Object> value = + Execution::Call(fun, global, 0, NULL, &has_pending_exception); + CHECK(value->IsHeapNumber()); + CHECK(fun->IsOptimized()); + double crankshaft_value = HeapNumber::cast(*value)->value(); + + SetSeeds(seeds, state0, state1); + V8::FillHeapNumberWithRandom(*value, *context); + double runtime_value = HeapNumber::cast(*value)->value(); + CHECK_EQ(runtime_value, crankshaft_value); +} + + +TEST(CrankshaftRandom) { + if (env.IsEmpty()) env = v8::Context::New(); + // Skip test if crankshaft is disabled. + if (!V8::UseCrankshaft()) return; + v8::HandleScope scope; + env->Enter(); + + Handle<Context> context(Isolate::Current()->context()); + Handle<JSObject> global(context->global()); + Handle<ByteArray> seeds(context->random_seed()); + bool has_pending_exception; + + CompileRun("function f() { return Math.random(); }"); + + Object* symbol = FACTORY->LookupAsciiSymbol("f")->ToObjectChecked(); + MaybeObject* fun_object = + context->global()->GetProperty(String::cast(symbol)); + Handle<JSFunction> fun(JSFunction::cast(fun_object->ToObjectChecked())); + + // Optimize function. + Execution::Call(fun, global, 0, NULL, &has_pending_exception); + Execution::Call(fun, global, 0, NULL, &has_pending_exception); + if (!fun->IsOptimized()) fun->MarkForLazyRecompilation(); + + // Test with some random values. + TestSeeds(fun, context, 0xC0C0AFFE, 0x31415926); + TestSeeds(fun, context, 0x01020304, 0xFFFFFFFF); + TestSeeds(fun, context, 0x00000001, 0x00000000); + + // Test that we bail out to runtime when seeds are uninitialized (zeros). + SetSeeds(seeds, 0, 0); + Handle<Object> value = + Execution::Call(fun, global, 0, NULL, &has_pending_exception); + CHECK(value->IsHeapNumber()); + CHECK(fun->IsOptimized()); + double crankshaft_value = HeapNumber::cast(*value)->value(); + CHECK_NE(0.0, crankshaft_value); +} diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc index 89a91127..d941d0f7 100644 --- a/test/cctest/test-regexp.cc +++ b/test/cctest/test-regexp.cc @@ -449,6 +449,7 @@ static bool IsWhiteSpace(uc16 c) { case 0xA0: case 0x2028: case 0x2029: + case 0xFEFF: return true; default: return unibrow::Space::Is(c); @@ -530,7 +531,7 @@ class TestConfig { typedef int Key; typedef int Value; static const int kNoKey; - static const int kNoValue; + static int NoValue() { return 0; } static inline int Compare(int a, int b) { if (a < b) return -1; @@ -543,7 +544,6 @@ class TestConfig { const int TestConfig::kNoKey = 0; -const int TestConfig::kNoValue = 0; static unsigned PseudoRandom(int i, int j) { @@ -837,7 +837,8 @@ TEST(MacroAssemblerNativeSimpleUC16) { Handle<Code> code = Handle<Code>::cast(code_object); int captures[4] = {42, 37, 87, 117}; - const uc16 input_data[6] = {'f', 'o', 'o', 'f', 'o', '\xa0'}; + const uc16 input_data[6] = {'f', 'o', 'o', 'f', 'o', + static_cast<uc16>('\xa0')}; Handle<String> input = factory->NewStringFromTwoByte(Vector<const uc16>(input_data, 6)); Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input); @@ -857,7 +858,8 @@ TEST(MacroAssemblerNativeSimpleUC16) { CHECK_EQ(-1, captures[2]); CHECK_EQ(-1, captures[3]); - const uc16 input_data2[9] = {'b', 'a', 'r', 'b', 'a', 'r', 'b', 'a', '\xa0'}; + const uc16 input_data2[9] = {'b', 'a', 'r', 'b', 'a', 'r', 'b', 'a', + static_cast<uc16>('\xa0')}; input = factory->NewStringFromTwoByte(Vector<const uc16>(input_data2, 9)); seq_input = Handle<SeqTwoByteString>::cast(input); start_adr = seq_input->GetCharsAddress(); diff --git a/test/cctest/test-reloc-info.cc b/test/cctest/test-reloc-info.cc index 5bdc4c3e..e638201d 100644 --- a/test/cctest/test-reloc-info.cc +++ b/test/cctest/test-reloc-info.cc @@ -34,7 +34,7 @@ namespace internal { static void WriteRinfo(RelocInfoWriter* writer, byte* pc, RelocInfo::Mode mode, intptr_t data) { - RelocInfo rinfo(pc, mode, data); + RelocInfo rinfo(pc, mode, data, NULL); writer->Write(&rinfo); } diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc index 8e85444e..e426e7bd 100644 --- a/test/cctest/test-serialize.cc +++ b/test/cctest/test-serialize.cc @@ -114,10 +114,6 @@ TEST(ExternalReferenceEncoder) { ExternalReference(isolate->counters()->keyed_load_function_prototype()); CHECK_EQ(make_code(STATS_COUNTER, Counters::k_keyed_load_function_prototype), encoder.Encode(keyed_load_function_prototype.address())); - ExternalReference the_hole_value_location = - ExternalReference::the_hole_value_location(isolate); - CHECK_EQ(make_code(UNCLASSIFIED, 2), - encoder.Encode(the_hole_value_location.address())); ExternalReference stack_limit_address = ExternalReference::address_of_stack_limit(isolate); CHECK_EQ(make_code(UNCLASSIFIED, 4), @@ -127,14 +123,15 @@ TEST(ExternalReferenceEncoder) { CHECK_EQ(make_code(UNCLASSIFIED, 5), encoder.Encode(real_stack_limit_address.address())); #ifdef ENABLE_DEBUGGER_SUPPORT - CHECK_EQ(make_code(UNCLASSIFIED, 15), + CHECK_EQ(make_code(UNCLASSIFIED, 16), encoder.Encode(ExternalReference::debug_break(isolate).address())); #endif // ENABLE_DEBUGGER_SUPPORT CHECK_EQ(make_code(UNCLASSIFIED, 10), encoder.Encode( ExternalReference::new_space_start(isolate).address())); CHECK_EQ(make_code(UNCLASSIFIED, 3), - encoder.Encode(ExternalReference::roots_address(isolate).address())); + encoder.Encode( + ExternalReference::roots_array_start(isolate).address())); } @@ -157,15 +154,13 @@ TEST(ExternalReferenceDecoder) { decoder.Decode( make_code(STATS_COUNTER, Counters::k_keyed_load_function_prototype))); - CHECK_EQ(ExternalReference::the_hole_value_location(isolate).address(), - decoder.Decode(make_code(UNCLASSIFIED, 2))); CHECK_EQ(ExternalReference::address_of_stack_limit(isolate).address(), decoder.Decode(make_code(UNCLASSIFIED, 4))); CHECK_EQ(ExternalReference::address_of_real_stack_limit(isolate).address(), decoder.Decode(make_code(UNCLASSIFIED, 5))); #ifdef ENABLE_DEBUGGER_SUPPORT CHECK_EQ(ExternalReference::debug_break(isolate).address(), - decoder.Decode(make_code(UNCLASSIFIED, 15))); + decoder.Decode(make_code(UNCLASSIFIED, 16))); #endif // ENABLE_DEBUGGER_SUPPORT CHECK_EQ(ExternalReference::new_space_start(isolate).address(), decoder.Decode(make_code(UNCLASSIFIED, 10))); @@ -365,8 +360,8 @@ TEST(PartialSerialization) { Isolate::Current()->bootstrapper()->NativesSourceLookup(i); } } - HEAP->CollectAllGarbage(true); - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); Object* raw_foo; { @@ -490,7 +485,7 @@ TEST(ContextSerialization) { } // If we don't do this then we end up with a stray root pointing at the // context even after we have disposed of env. - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); int file_name_length = StrLength(FLAG_testing_serialization_file) + 10; Vector<char> startup_name = Vector<char>::New(file_name_length + 1); @@ -563,16 +558,20 @@ DEPENDENT_TEST(ContextDeserialization, ContextSerialization) { TEST(LinearAllocation) { v8::V8::Initialize(); int new_space_max = 512 * KB; + int paged_space_max = Page::kMaxNonCodeHeapObjectSize; + int code_space_max = HEAP->code_space()->AreaSize(); for (int size = 1000; size < 5 * MB; size += size >> 1) { + size &= ~8; // Round. int new_space_size = (size < new_space_max) ? size : new_space_max; + int paged_space_size = (size < paged_space_max) ? size : paged_space_max; HEAP->ReserveSpace( new_space_size, - size, // Old pointer space. - size, // Old data space. - size, // Code space. - size, // Map space. - size, // Cell space. + paged_space_size, // Old pointer space. + paged_space_size, // Old data space. + HEAP->code_space()->RoundSizeDownToObjectAlignment(code_space_max), + HEAP->map_space()->RoundSizeDownToObjectAlignment(paged_space_size), + HEAP->cell_space()->RoundSizeDownToObjectAlignment(paged_space_size), size); // Large object space. LinearAllocationScope linear_allocation_scope; const int kSmallFixedArrayLength = 4; @@ -599,14 +598,14 @@ TEST(LinearAllocation) { Object* pointer_last = NULL; for (int i = 0; - i + kSmallFixedArraySize <= size; + i + kSmallFixedArraySize <= paged_space_size; i += kSmallFixedArraySize) { Object* obj = HEAP->AllocateFixedArray(kSmallFixedArrayLength, TENURED)->ToObjectChecked(); int old_page_fullness = i % Page::kPageSize; int page_fullness = (i + kSmallFixedArraySize) % Page::kPageSize; if (page_fullness < old_page_fullness || - page_fullness > Page::kObjectAreaSize) { + page_fullness > HEAP->old_pointer_space()->AreaSize()) { i = RoundUp(i, Page::kPageSize); pointer_last = NULL; } @@ -618,13 +617,15 @@ TEST(LinearAllocation) { } Object* data_last = NULL; - for (int i = 0; i + kSmallStringSize <= size; i += kSmallStringSize) { + for (int i = 0; + i + kSmallStringSize <= paged_space_size; + i += kSmallStringSize) { Object* obj = HEAP->AllocateRawAsciiString(kSmallStringLength, TENURED)->ToObjectChecked(); int old_page_fullness = i % Page::kPageSize; int page_fullness = (i + kSmallStringSize) % Page::kPageSize; if (page_fullness < old_page_fullness || - page_fullness > Page::kObjectAreaSize) { + page_fullness > HEAP->old_data_space()->AreaSize()) { i = RoundUp(i, Page::kPageSize); data_last = NULL; } @@ -636,13 +637,13 @@ TEST(LinearAllocation) { } Object* map_last = NULL; - for (int i = 0; i + kMapSize <= size; i += kMapSize) { + for (int i = 0; i + kMapSize <= paged_space_size; i += kMapSize) { Object* obj = HEAP->AllocateMap(JS_OBJECT_TYPE, 42 * kPointerSize)->ToObjectChecked(); int old_page_fullness = i % Page::kPageSize; int page_fullness = (i + kMapSize) % Page::kPageSize; if (page_fullness < old_page_fullness || - page_fullness > Page::kObjectAreaSize) { + page_fullness > HEAP->map_space()->AreaSize()) { i = RoundUp(i, Page::kPageSize); map_last = NULL; } @@ -653,7 +654,7 @@ TEST(LinearAllocation) { map_last = obj; } - if (size > Page::kObjectAreaSize) { + if (size > Page::kMaxNonCodeHeapObjectSize) { // Support for reserving space in large object space is not there yet, // but using an always-allocate scope is fine for now. AlwaysAllocateScope always; diff --git a/test/cctest/test-sockets.cc b/test/cctest/test-sockets.cc index 4af55dbe..ad735400 100644 --- a/test/cctest/test-sockets.cc +++ b/test/cctest/test-sockets.cc @@ -129,7 +129,7 @@ TEST(Socket) { bool ok; // Initialize socket support. - ok = Socket::Setup(); + ok = Socket::SetUp(); CHECK(ok); // Send and receive some data. diff --git a/test/cctest/test-spaces.cc b/test/cctest/test-spaces.cc index 0f22ce1a..92de2a60 100644 --- a/test/cctest/test-spaces.cc +++ b/test/cctest/test-spaces.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -32,7 +32,9 @@ using namespace v8::internal; +#if 0 static void VerifyRegionMarking(Address page_start) { +#ifdef ENABLE_CARDMARKING_WRITE_BARRIER Page* p = Page::FromAddress(page_start); p->SetRegionMarks(Page::kAllRegionsCleanMarks); @@ -54,9 +56,13 @@ static void VerifyRegionMarking(Address page_start) { addr += kPointerSize) { CHECK(Page::FromAddress(addr)->IsRegionDirty(addr)); } +#endif } +#endif +// TODO(gc) you can no longer allocate pages like this. Details are hidden. +#if 0 TEST(Page) { byte* mem = NewArray<byte>(2*Page::kPageSize); CHECK(mem != NULL); @@ -89,6 +95,7 @@ TEST(Page) { DeleteArray(mem); } +#endif namespace v8 { @@ -118,95 +125,76 @@ class TestMemoryAllocatorScope { TEST(MemoryAllocator) { - OS::Setup(); + OS::SetUp(); Isolate* isolate = Isolate::Current(); isolate->InitializeLoggingAndCounters(); Heap* heap = isolate->heap(); - CHECK(heap->ConfigureHeapDefault()); + CHECK(isolate->heap()->ConfigureHeapDefault()); + MemoryAllocator* memory_allocator = new MemoryAllocator(isolate); - CHECK(memory_allocator->Setup(heap->MaxReserved(), + CHECK(memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize())); - TestMemoryAllocatorScope test_scope(isolate, memory_allocator); + int total_pages = 0; OldSpace faked_space(heap, heap->MaxReserved(), OLD_POINTER_SPACE, NOT_EXECUTABLE); - int total_pages = 0; - int requested = MemoryAllocator::kPagesPerChunk; - int allocated; - // If we request n pages, we should get n or n - 1. - Page* first_page = memory_allocator->AllocatePages( - requested, &allocated, &faked_space); + Page* first_page = + memory_allocator->AllocatePage(&faked_space, NOT_EXECUTABLE); + + first_page->InsertAfter(faked_space.anchor()->prev_page()); CHECK(first_page->is_valid()); - CHECK(allocated == requested || allocated == requested - 1); - total_pages += allocated; + CHECK(first_page->next_page() == faked_space.anchor()); + total_pages++; - Page* last_page = first_page; - for (Page* p = first_page; p->is_valid(); p = p->next_page()) { - CHECK(memory_allocator->IsPageInSpace(p, &faked_space)); - last_page = p; + for (Page* p = first_page; p != faked_space.anchor(); p = p->next_page()) { + CHECK(p->owner() == &faked_space); } // Again, we should get n or n - 1 pages. - Page* others = memory_allocator->AllocatePages( - requested, &allocated, &faked_space); - CHECK(others->is_valid()); - CHECK(allocated == requested || allocated == requested - 1); - total_pages += allocated; - - memory_allocator->SetNextPage(last_page, others); + Page* other = + memory_allocator->AllocatePage(&faked_space, NOT_EXECUTABLE); + CHECK(other->is_valid()); + total_pages++; + other->InsertAfter(first_page); int page_count = 0; - for (Page* p = first_page; p->is_valid(); p = p->next_page()) { - CHECK(memory_allocator->IsPageInSpace(p, &faked_space)); + for (Page* p = first_page; p != faked_space.anchor(); p = p->next_page()) { + CHECK(p->owner() == &faked_space); page_count++; } CHECK(total_pages == page_count); Page* second_page = first_page->next_page(); CHECK(second_page->is_valid()); - - // Freeing pages at the first chunk starting at or after the second page - // should free the entire second chunk. It will return the page it was passed - // (since the second page was in the first chunk). - Page* free_return = memory_allocator->FreePages(second_page); - CHECK(free_return == second_page); - memory_allocator->SetNextPage(first_page, free_return); - - // Freeing pages in the first chunk starting at the first page should free - // the first chunk and return an invalid page. - Page* invalid_page = memory_allocator->FreePages(first_page); - CHECK(!invalid_page->is_valid()); - + memory_allocator->Free(first_page); + memory_allocator->Free(second_page); memory_allocator->TearDown(); delete memory_allocator; } TEST(NewSpace) { - OS::Setup(); + OS::SetUp(); Isolate* isolate = Isolate::Current(); isolate->InitializeLoggingAndCounters(); Heap* heap = isolate->heap(); CHECK(heap->ConfigureHeapDefault()); MemoryAllocator* memory_allocator = new MemoryAllocator(isolate); - CHECK(memory_allocator->Setup(heap->MaxReserved(), + CHECK(memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize())); TestMemoryAllocatorScope test_scope(isolate, memory_allocator); NewSpace new_space(heap); - void* chunk = - memory_allocator->ReserveInitialChunk(4 * heap->ReservedSemiSpaceSize()); - CHECK(chunk != NULL); - Address start = RoundUp(static_cast<Address>(chunk), - 2 * heap->ReservedSemiSpaceSize()); - CHECK(new_space.Setup(start, 2 * heap->ReservedSemiSpaceSize())); - CHECK(new_space.HasBeenSetup()); + CHECK(new_space.SetUp(HEAP->ReservedSemiSpaceSize(), + HEAP->ReservedSemiSpaceSize())); + CHECK(new_space.HasBeenSetUp()); - while (new_space.Available() >= Page::kMaxHeapObjectSize) { + while (new_space.Available() >= Page::kMaxNonCodeHeapObjectSize) { Object* obj = - new_space.AllocateRaw(Page::kMaxHeapObjectSize)->ToObjectUnchecked(); + new_space.AllocateRaw(Page::kMaxNonCodeHeapObjectSize)-> + ToObjectUnchecked(); CHECK(new_space.Contains(HeapObject::cast(obj))); } @@ -217,13 +205,13 @@ TEST(NewSpace) { TEST(OldSpace) { - OS::Setup(); + OS::SetUp(); Isolate* isolate = Isolate::Current(); isolate->InitializeLoggingAndCounters(); Heap* heap = isolate->heap(); CHECK(heap->ConfigureHeapDefault()); MemoryAllocator* memory_allocator = new MemoryAllocator(isolate); - CHECK(memory_allocator->Setup(heap->MaxReserved(), + CHECK(memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize())); TestMemoryAllocatorScope test_scope(isolate, memory_allocator); @@ -233,16 +221,10 @@ TEST(OldSpace) { NOT_EXECUTABLE); CHECK(s != NULL); - void* chunk = memory_allocator->ReserveInitialChunk( - 4 * heap->ReservedSemiSpaceSize()); - CHECK(chunk != NULL); - Address start = static_cast<Address>(chunk); - size_t size = RoundUp(start, 2 * heap->ReservedSemiSpaceSize()) - start; - - CHECK(s->Setup(start, size)); + CHECK(s->SetUp()); while (s->Available() > 0) { - s->AllocateRaw(Page::kMaxHeapObjectSize)->ToObjectUnchecked(); + s->AllocateRaw(Page::kMaxNonCodeHeapObjectSize)->ToObjectUnchecked(); } s->TearDown(); @@ -258,14 +240,12 @@ TEST(LargeObjectSpace) { LargeObjectSpace* lo = HEAP->lo_space(); CHECK(lo != NULL); - Map* faked_map = reinterpret_cast<Map*>(HeapObject::FromAddress(0)); int lo_size = Page::kPageSize; - Object* obj = lo->AllocateRaw(lo_size)->ToObjectUnchecked(); + Object* obj = lo->AllocateRaw(lo_size, NOT_EXECUTABLE)->ToObjectUnchecked(); CHECK(obj->IsHeapObject()); HeapObject* ho = HeapObject::cast(obj); - ho->set_map(faked_map); CHECK(lo->Contains(HeapObject::cast(obj))); @@ -275,14 +255,13 @@ TEST(LargeObjectSpace) { while (true) { intptr_t available = lo->Available(); - { MaybeObject* maybe_obj = lo->AllocateRaw(lo_size); + { MaybeObject* maybe_obj = lo->AllocateRaw(lo_size, NOT_EXECUTABLE); if (!maybe_obj->ToObject(&obj)) break; } - HeapObject::cast(obj)->set_map(faked_map); CHECK(lo->Available() < available); }; CHECK(!lo->IsEmpty()); - CHECK(lo->AllocateRaw(lo_size)->IsFailure()); + CHECK(lo->AllocateRaw(lo_size, NOT_EXECUTABLE)->IsFailure()); } diff --git a/test/cctest/test-strings.cc b/test/cctest/test-strings.cc index 55c21417..e11349bc 100644 --- a/test/cctest/test-strings.cc +++ b/test/cctest/test-strings.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // Check that we can traverse very deep stacks of ConsStrings using // StringInputBuffer. Check that Get(int) works on very deep stacks @@ -355,7 +355,7 @@ TEST(ExternalShortStringAdd) { // Make sure we cover all always-flat lengths and at least one above. static const int kMaxLength = 20; - CHECK_GT(kMaxLength, i::String::kMinNonFlatLength); + CHECK_GT(kMaxLength, i::ConsString::kMinLength); // Allocate two JavaScript arrays for holding short strings. v8::Handle<v8::Array> ascii_external_strings = @@ -502,6 +502,35 @@ TEST(SliceFromCons) { } +class AsciiVectorResource : public v8::String::ExternalAsciiStringResource { + public: + explicit AsciiVectorResource(i::Vector<const char> vector) + : data_(vector) {} + virtual ~AsciiVectorResource() {} + virtual size_t length() const { return data_.length(); } + virtual const char* data() const { return data_.start(); } + private: + i::Vector<const char> data_; +}; + + +TEST(SliceFromExternal) { + FLAG_string_slices = true; + InitializeVM(); + v8::HandleScope scope; + AsciiVectorResource resource( + i::Vector<const char>("abcdefghijklmnopqrstuvwxyz", 26)); + Handle<String> string = FACTORY->NewExternalStringFromAscii(&resource); + CHECK(string->IsExternalString()); + Handle<String> slice = FACTORY->NewSubString(string, 1, 25); + CHECK(slice->IsSlicedString()); + CHECK(string->IsExternalString()); + CHECK_EQ(SlicedString::cast(*slice)->parent(), *string); + CHECK(SlicedString::cast(*slice)->parent()->IsExternalString()); + CHECK(slice->IsFlat()); +} + + TEST(TrivialSlice) { // This tests whether a slice that contains the entire parent string // actually creates a new string (it should not). diff --git a/test/cctest/test-threads.cc b/test/cctest/test-threads.cc index 985b9e5b..713d1e84 100644 --- a/test/cctest/test-threads.cc +++ b/test/cctest/test-threads.cc @@ -63,7 +63,7 @@ enum Turn { static Turn turn = FILL_CACHE; -class ThreadA: public v8::internal::Thread { +class ThreadA : public v8::internal::Thread { public: ThreadA() : Thread("ThreadA") { } void Run() { @@ -99,7 +99,7 @@ class ThreadA: public v8::internal::Thread { }; -class ThreadB: public v8::internal::Thread { +class ThreadB : public v8::internal::Thread { public: ThreadB() : Thread("ThreadB") { } void Run() { @@ -111,7 +111,7 @@ class ThreadB: public v8::internal::Thread { v8::Context::Scope context_scope(v8::Context::New()); // Clear the caches by forcing major GC. - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(v8::internal::Heap::kNoGCFlags); turn = SECOND_TIME_FILL_CACHE; break; } @@ -190,3 +190,19 @@ TEST(ThreadIdValidation) { delete threads[i]; } } + + +class ThreadC : public v8::internal::Thread { + public: + ThreadC() : Thread("ThreadC") { } + void Run() { + Join(); + } +}; + + +TEST(ThreadJoinSelf) { + ThreadC thread; + thread.Start(); + thread.Join(); +} diff --git a/test/cctest/test-utils.cc b/test/cctest/test-utils.cc index e4f70df4..df8ff72e 100644 --- a/test/cctest/test-utils.cc +++ b/test/cctest/test-utils.cc @@ -105,7 +105,7 @@ void TestMemCopy(Vector<byte> src, TEST(MemCopy) { v8::V8::Initialize(); - OS::Setup(); + OS::SetUp(); const int N = OS::kMinComplexMemCopy + 128; Vector<byte> buffer1 = Vector<byte>::New(N); Vector<byte> buffer2 = Vector<byte>::New(N); diff --git a/test/cctest/test-weakmaps.cc b/test/cctest/test-weakmaps.cc index db4db254..56d59362 100644 --- a/test/cctest/test-weakmaps.cc +++ b/test/cctest/test-weakmaps.cc @@ -50,7 +50,7 @@ static void PutIntoWeakMap(Handle<JSWeakMap> weakmap, Handle<JSObject> key, int value) { Handle<ObjectHashTable> table = PutIntoObjectHashTable( - Handle<ObjectHashTable>(weakmap->table()), + Handle<ObjectHashTable>(ObjectHashTable::cast(weakmap->table())), Handle<JSObject>(JSObject::cast(*key)), Handle<Smi>(Smi::FromInt(value))); weakmap->set_table(*table); @@ -85,13 +85,14 @@ TEST(Weakness) { v8::HandleScope scope; PutIntoWeakMap(weakmap, Handle<JSObject>(JSObject::cast(*key)), 23); } - CHECK_EQ(1, weakmap->table()->NumberOfElements()); + CHECK_EQ(1, ObjectHashTable::cast(weakmap->table())->NumberOfElements()); // Force a full GC. HEAP->CollectAllGarbage(false); CHECK_EQ(0, NumberOfWeakCalls); - CHECK_EQ(1, weakmap->table()->NumberOfElements()); - CHECK_EQ(0, weakmap->table()->NumberOfDeletedElements()); + CHECK_EQ(1, ObjectHashTable::cast(weakmap->table())->NumberOfElements()); + CHECK_EQ( + 0, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements()); // Make the global reference to the key weak. { @@ -107,12 +108,14 @@ TEST(Weakness) { // weak references whereas the second one will also clear weak maps. HEAP->CollectAllGarbage(false); CHECK_EQ(1, NumberOfWeakCalls); - CHECK_EQ(1, weakmap->table()->NumberOfElements()); - CHECK_EQ(0, weakmap->table()->NumberOfDeletedElements()); + CHECK_EQ(1, ObjectHashTable::cast(weakmap->table())->NumberOfElements()); + CHECK_EQ( + 0, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements()); HEAP->CollectAllGarbage(false); CHECK_EQ(1, NumberOfWeakCalls); - CHECK_EQ(0, weakmap->table()->NumberOfElements()); - CHECK_EQ(1, weakmap->table()->NumberOfDeletedElements()); + CHECK_EQ(0, ObjectHashTable::cast(weakmap->table())->NumberOfElements()); + CHECK_EQ( + 1, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements()); } @@ -122,7 +125,7 @@ TEST(Shrinking) { Handle<JSWeakMap> weakmap = AllocateJSWeakMap(); // Check initial capacity. - CHECK_EQ(32, weakmap->table()->Capacity()); + CHECK_EQ(32, ObjectHashTable::cast(weakmap->table())->Capacity()); // Fill up weak map to trigger capacity change. { @@ -135,15 +138,17 @@ TEST(Shrinking) { } // Check increased capacity. - CHECK_EQ(128, weakmap->table()->Capacity()); + CHECK_EQ(128, ObjectHashTable::cast(weakmap->table())->Capacity()); // Force a full GC. - CHECK_EQ(32, weakmap->table()->NumberOfElements()); - CHECK_EQ(0, weakmap->table()->NumberOfDeletedElements()); + CHECK_EQ(32, ObjectHashTable::cast(weakmap->table())->NumberOfElements()); + CHECK_EQ( + 0, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements()); HEAP->CollectAllGarbage(false); - CHECK_EQ(0, weakmap->table()->NumberOfElements()); - CHECK_EQ(32, weakmap->table()->NumberOfDeletedElements()); + CHECK_EQ(0, ObjectHashTable::cast(weakmap->table())->NumberOfElements()); + CHECK_EQ( + 32, ObjectHashTable::cast(weakmap->table())->NumberOfDeletedElements()); // Check shrunk capacity. - CHECK_EQ(32, weakmap->table()->Capacity()); + CHECK_EQ(32, ObjectHashTable::cast(weakmap->table())->Capacity()); } diff --git a/test/es5conform/es5conform.status b/test/es5conform/es5conform.status index d095a247..12ebf903 100644 --- a/test/es5conform/es5conform.status +++ b/test/es5conform/es5conform.status @@ -41,16 +41,6 @@ chapter10/10.4/10.4.2/10.4.2-2-c-1: FAIL_OK # We are compatible with Safari and Firefox. chapter11/11.1/11.1.5: UNIMPLEMENTED -# We do not have a global object called 'global' as required by tests. -chapter15/15.1: FAIL_OK - -# NaN is writable. We are compatible with JSC. -chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-178: FAIL_OK -# Infinity is writable. We are compatible with JSC. -chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-179: FAIL_OK -# undefined is writable. We are compatible with JSC. -chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-180: FAIL_OK - # Our Function object has an "arguments" property which is used as a # non-property in the test. chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-183: FAIL_OK @@ -106,9 +96,6 @@ chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-7: FAIL_OK # SUBSETFAIL chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-11: FAIL_OK -# We do not implement all methods on RegExp. -chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-13: FAIL - # SUBSETFAIL chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-14: FAIL_OK @@ -196,27 +183,6 @@ chapter15/15.4/15.4.4/15.4.4.22/15.4.4.22-9-c-ii-4-s: SKIP # have no effect on the actual array on which reduceRight is called. chapter15/15.4/15.4.4/15.4.4.22/15.4.4.22-9-7: FAIL_OK -# We do not correctly recognize \uFEFF as whitespace -chapter15/15.5/15.5.4/15.5.4.20/15.5.4.20-4-10: FAIL -chapter15/15.5/15.5.4/15.5.4.20/15.5.4.20-4-18: FAIL -chapter15/15.5/15.5.4/15.5.4.20/15.5.4.20-4-34: FAIL - -# RegExp.prototype is not of type RegExp - we are bug compatible with JSC. -chapter15/15.10/15.10.6/15.10.6: FAIL_OK - -# We do not have the properties of a RegExp instance on RegExp.prototype. -# The spec says we should - but we are currently bug compatible with JSC. -chapter15/15.10/15.10.7/15.10.7.1/15.10.7.1-1: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.1/15.10.7.1-2: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.2/15.10.7.2-1: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.2/15.10.7.2-2: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.3/15.10.7.3-1: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.3/15.10.7.3-2: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.4/15.10.7.4-1: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.4/15.10.7.4-2: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.5/15.10.7.5-1: FAIL_OK -chapter15/15.10/15.10.7/15.10.7.5/15.10.7.5-2: FAIL_OK - ############################################################################## # Unimplemented parts of strict mode # Setting expectations to fail only so that the tests trigger as soon as @@ -348,8 +314,3 @@ chapter15/15.3/15.3.2/15.3.2.1/15.3.2.1-11-6-s: FAIL # Array.prototype.reduce - null passed as thisValue to strict callbackfn # Invalid test case: http://es5conform.codeplex.com/workitem/29085 chapter15/15.4/15.4.4/15.4.4.21/15.4.4.21-9-c-ii-4-s: FAIL - -[ $arch == mips ] - -# Skip all tests on MIPS. -*: SKIP diff --git a/test/message/message.status b/test/message/message.status index 70354cee..fc2896b1 100644 --- a/test/message/message.status +++ b/test/message/message.status @@ -29,10 +29,3 @@ prefix message # All tests in the bug directory are expected to fail. bugs: FAIL - - -############################################################################## -[ $arch == mips ] - -# Skip all tests on MIPS. -*: SKIP diff --git a/test/mjsunit/apply.js b/test/mjsunit/apply.js index c166110d..413ee937 100644 --- a/test/mjsunit/apply.js +++ b/test/mjsunit/apply.js @@ -190,3 +190,10 @@ assertEquals("morseper", "moreseper-prime"); delete(Array.prototype["1"]); + +// Check correct handling of non-array argument lists. +assertSame(this, f0.apply(this, {}), "non-array-1"); +assertSame(this, f0.apply(this, { length:1 }), "non-array-2"); +assertEquals(void 0, f1.apply(this, { length:1 }), "non-array-3"); +assertEquals(void 0, f1.apply(this, { 0:"foo" }), "non-array-4"); +assertEquals("foo", f1.apply(this, { length:1, 0:"foo" }), "non-array-5"); diff --git a/test/mjsunit/array-construct-transition.js b/test/mjsunit/array-construct-transition.js new file mode 100644 index 00000000..577e321a --- /dev/null +++ b/test/mjsunit/array-construct-transition.js @@ -0,0 +1,39 @@ +// 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 --smi-only-arrays + +support_smi_only_arrays = %HasFastSmiOnlyElements(new Array(1,2,3,4,5,6,7,8)); + +if (support_smi_only_arrays) { + var a = new Array(0, 1, 2); + assertTrue(%HasFastSmiOnlyElements(a)); + var b = new Array(0.5, 1.2, 2.3); + assertTrue(%HasFastDoubleElements(b)); + var c = new Array(0.5, 1.2, new Object()); + assertTrue(%HasFastElements(c)); +} diff --git a/test/mjsunit/array-join.js b/test/mjsunit/array-join.js index 5c837a5c..c08c182f 100644 --- a/test/mjsunit/array-join.js +++ b/test/mjsunit/array-join.js @@ -75,10 +75,10 @@ if (Array.prototype.toString != oldToString) { Array.prototype.toString = oldToString; } -var a = new Array(123123123); -assertEquals(123123122, String(a).length); -assertEquals(123123122, a.join(",").length); -assertEquals(246246244, a.join("oo").length); +var a = new Array(123123); +assertEquals(123122, String(a).length); +assertEquals(123122, a.join(",").length); +assertEquals(246244, a.join("oo").length); a = new Array(Math.pow(2,32) - 1); // Max length. assertEquals("", a.join("")); @@ -90,4 +90,4 @@ a = new Array(100001); for (var i = 0; i < a.length; i++) a[i] = undefined; a[5] = "ab"; a[90000] = "cd"; -assertEquals("abcd", a.join("")); // Must not throw.
\ No newline at end of file +assertEquals("abcd", a.join("")); // Must not throw. diff --git a/test/mjsunit/array-literal-transitions.js b/test/mjsunit/array-literal-transitions.js new file mode 100644 index 00000000..f657525e --- /dev/null +++ b/test/mjsunit/array-literal-transitions.js @@ -0,0 +1,210 @@ +// Copyright 2011 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 --smi-only-arrays --expose-gc +// Test element kind of objects. +// Since --smi-only-arrays affects builtins, its default setting at compile +// time sticks if built with snapshot. If --smi-only-arrays is deactivated +// by default, only a no-snapshot build actually has smi-only arrays enabled +// in this test case. Depending on whether smi-only arrays are actually +// enabled, this test takes the appropriate code path to check smi-only arrays. + +support_smi_only_arrays = %HasFastSmiOnlyElements([1,2,3,4,5,6,7,8,9,10]); + +if (support_smi_only_arrays) { + print("Tests include smi-only arrays."); +} else { + print("Tests do NOT include smi-only arrays."); +} + +// IC and Crankshaft support for smi-only elements in dynamic array literals. +function get(foo) { return foo; } // Used to generate dynamic values. + +function array_literal_test() { + var a0 = [1, 2, 3]; + assertTrue(%HasFastSmiOnlyElements(a0)); + var a1 = [get(1), get(2), get(3)]; + assertTrue(%HasFastSmiOnlyElements(a1)); + + var b0 = [1, 2, get("three")]; + assertTrue(%HasFastElements(b0)); + var b1 = [get(1), get(2), get("three")]; + assertTrue(%HasFastElements(b1)); + + var c0 = [1, 2, get(3.5)]; + assertTrue(%HasFastDoubleElements(c0)); + assertEquals(3.5, c0[2]); + assertEquals(2, c0[1]); + assertEquals(1, c0[0]); + + var c1 = [1, 2, 3.5]; + assertTrue(%HasFastDoubleElements(c1)); + assertEquals(3.5, c1[2]); + assertEquals(2, c1[1]); + assertEquals(1, c1[0]); + + var c2 = [get(1), get(2), get(3.5)]; + assertTrue(%HasFastDoubleElements(c2)); + assertEquals(3.5, c2[2]); + assertEquals(2, c2[1]); + assertEquals(1, c2[0]); + + var object = new Object(); + var d0 = [1, 2, object]; + assertTrue(%HasFastElements(d0)); + assertEquals(object, d0[2]); + assertEquals(2, d0[1]); + assertEquals(1, d0[0]); + + var e0 = [1, 2, 3.5]; + assertTrue(%HasFastDoubleElements(e0)); + assertEquals(3.5, e0[2]); + assertEquals(2, e0[1]); + assertEquals(1, e0[0]); + + var f0 = [1, 2, [1, 2]]; + assertTrue(%HasFastElements(f0)); + assertEquals([1,2], f0[2]); + assertEquals(2, f0[1]); + assertEquals(1, f0[0]); +} + +if (support_smi_only_arrays) { + for (var i = 0; i < 3; i++) { + array_literal_test(); + } + %OptimizeFunctionOnNextCall(array_literal_test); + array_literal_test(); + + function test_large_literal() { + + function d() { + gc(); + return 2.5; + } + + function o() { + gc(); + return new Object(); + } + + large = + [ 0, 1, 2, 3, 4, 5, d(), d(), d(), d(), d(), d(), o(), o(), o(), o() ]; + assertFalse(%HasDictionaryElements(large)); + assertFalse(%HasFastSmiOnlyElements(large)); + assertFalse(%HasFastDoubleElements(large)); + assertTrue(%HasFastElements(large)); + assertEquals(large, + [0, 1, 2, 3, 4, 5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + new Object(), new Object(), new Object(), new Object()]); + } + + for (var i = 0; i < 3; i++) { + test_large_literal(); + } + %OptimizeFunctionOnNextCall(test_large_literal); + test_large_literal(); + + function deopt_array(use_literal) { + if (use_literal) { + return [.5, 3, 4]; + } else { + return new Array(); + } + } + + deopt_array(false); + deopt_array(false); + deopt_array(false); + %OptimizeFunctionOnNextCall(deopt_array); + var array = deopt_array(false); + assertTrue(2 != %GetOptimizationStatus(deopt_array)); + deopt_array(true); + assertTrue(2 != %GetOptimizationStatus(deopt_array)); + array = deopt_array(false); + assertTrue(2 != %GetOptimizationStatus(deopt_array)); + + // Check that unexpected changes in the objects stored into the boilerplate + // also force a deopt. + function deopt_array_literal_all_smis(a) { + return [0, 1, a]; + } + + deopt_array_literal_all_smis(2); + deopt_array_literal_all_smis(3); + deopt_array_literal_all_smis(4); + array = deopt_array_literal_all_smis(4); + assertEquals(0, array[0]); + assertEquals(1, array[1]); + assertEquals(4, array[2]); + %OptimizeFunctionOnNextCall(deopt_array_literal_all_smis); + array = deopt_array_literal_all_smis(5); + array = deopt_array_literal_all_smis(6); + assertTrue(2 != %GetOptimizationStatus(deopt_array_literal_all_smis)); + assertEquals(0, array[0]); + assertEquals(1, array[1]); + assertEquals(6, array[2]); + + array = deopt_array_literal_all_smis(.5); + assertTrue(1 != %GetOptimizationStatus(deopt_array_literal_all_smis)); + assertEquals(0, array[0]); + assertEquals(1, array[1]); + assertEquals(.5, array[2]); + + function deopt_array_literal_all_doubles(a) { + return [0.5, 1, a]; + } + + deopt_array_literal_all_doubles(.5); + deopt_array_literal_all_doubles(.5); + deopt_array_literal_all_doubles(.5); + array = deopt_array_literal_all_doubles(0.5); + assertEquals(0.5, array[0]); + assertEquals(1, array[1]); + assertEquals(0.5, array[2]); + %OptimizeFunctionOnNextCall(deopt_array_literal_all_doubles); + array = deopt_array_literal_all_doubles(5); + array = deopt_array_literal_all_doubles(6); + assertTrue(2 != %GetOptimizationStatus(deopt_array_literal_all_doubles)); + assertEquals(0.5, array[0]); + assertEquals(1, array[1]); + assertEquals(6, array[2]); + + var foo = new Object(); + array = deopt_array_literal_all_doubles(foo); + assertTrue(1 != %GetOptimizationStatus(deopt_array_literal_all_doubles)); + assertEquals(0.5, array[0]); + assertEquals(1, array[1]); + assertEquals(foo, array[2]); +} + +(function literals_after_osr() { + var color = [0]; + // Trigger OSR. + while (%GetOptimizationStatus(literals_after_osr) == 2) {} + return [color[0]]; +})(); diff --git a/test/mjsunit/array-store-and-grow.js b/test/mjsunit/array-store-and-grow.js new file mode 100644 index 00000000..131d4ebc --- /dev/null +++ b/test/mjsunit/array-store-and-grow.js @@ -0,0 +1,183 @@ +// 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. + +// Verifies that the KeyedStoreIC correctly handles out-of-bounds stores +// to an array that grow it by a single element. Test functions are +// called twice to make sure that the IC is used, first call is handled +// by the runtime in the miss stub. + +function array_store_1(a,b,c) { + return (a[b] = c); +} + +// Check handling of the empty array. +var a = []; +array_store_1(a, 0, 1); +a = []; +array_store_1(a, 0, 1); +assertEquals(1, a[0]); +assertEquals(1, array_store_1([], 0, 1)); + +a = []; +for (x=0;x<100000;++x) { + assertEquals(x, array_store_1(a, x, x)); +} + +for (x=0;x<100000;++x) { + assertEquals(x, array_store_1([], 0, x)); +} + +function array_store_2(a,b,c) { + return (a[b] = c); +} + +a = []; +array_store_2(a, 0, 0.5); +a = []; +array_store_2(a, 0, 0.5); +assertEquals(0.5, a[0]); +assertEquals(0.5, array_store_2([], 0, 0.5)); + +function array_store_3(a,b,c) { + return (a[b] = c); +} + +x = new Object(); +a = []; +array_store_3(a, 0, x); +a = []; +array_store_3(a, 0, x); +assertEquals(x, a[0]); +assertEquals(x, array_store_3([], 0, x)); + +// Check the handling of COW arrays +function makeCOW() { + return [1]; +} + +function array_store_4(a,b,c) { + return (a[b] = c); +} + +a = makeCOW(); +array_store_4(a, 1, 1); +a = makeCOW(); +array_store_4(a, 1, 1); +assertEquals(1, a[1]); +assertEquals(1, array_store_4([], 1, 1)); + +function array_store_5(a,b,c) { + return (a[b] = c); +} + +a = makeCOW(); +array_store_5(a, 1, 0.5); +a = makeCOW(); +array_store_5(a, 1, 0.5); +assertEquals(0.5, a[1]); +assertEquals(0.5, array_store_5([], 1, 0.5)); + +function array_store_6(a,b,c) { + return (a[b] = c); +} + +a = makeCOW(); +array_store_6(a, 1, x); +a = makeCOW(); +array_store_6(a, 1, x); +assertEquals(x, a[1]); +assertEquals(x, array_store_6([], 1, x)); + +// Check the handling of mutable arrays. +a = new Array(1,2,3); +array_store_4(a, 3, 1); +a = new Array(1,2,3); +array_store_4(a, 3, 1); +assertEquals(1, a[3]); +assertEquals(1, array_store_4([], 3, 1)); + +function array_store_5(a,b,c) { + return (a[b] = c); +} + +a = new Array(1,2,3); +array_store_5(a, 3, 0.5); +a = new Array(1,2,3); +array_store_5(a, 3, 0.5); +assertEquals(0.5, a[3]); +assertEquals(0.5, array_store_5([], 3, 0.5)); + +function array_store_6(a,b,c) { + return (a[b] = c); +} + +a = new Array(1,2,3); +array_store_6(a, 3, x); +a = new Array(1,2,3); +array_store_6(a, 3, x); +assertEquals(x, a[3]); +assertEquals(x, array_store_6([], 3, x)); + +function array_store_7(a,b,c) { + return (a[b] = c); +} + +// Check the handling of mutable arrays of doubles +var a = new Array(0.5, 1.5); +array_store_7(a, 2, .5); +a = new Array(0.5, 1.5); +array_store_7(a, 2, .5); +assertEquals(0.5, a[2]); +a = new Array(0.5, 1.5); +assertEquals(0.5, array_store_7(a, 2, 0.5)); + +for (x=0;x<100000;++x) { + a = new Array(0.5, 1.5); + assertEquals(x, array_store_7(a, 2, x)); +} + +function array_store_8(a,b,c) { + return (a[b] = c); +} + +var a = new Array(0.5, 1.5); +array_store_8(a, 2, .5); +a = new Array(0.5, 1.5); +array_store_8(a, 10, .5); +assertEquals(0.5, a[10]); + +// Grow the empty array with a double store. +function array_store_9(a,b,c) { + return (a[b] = c); +} + +var a = []; +array_store_9(a, 0, 0.5); +a = []; +array_store_1(a, 0, 0.5); +assertEquals(0.5, a[0]); +assertEquals(0.5, array_store_1([], 0, 0.5)); diff --git a/test/mjsunit/array-tostring.js b/test/mjsunit/array-tostring.js new file mode 100644 index 00000000..6708657e --- /dev/null +++ b/test/mjsunit/array-tostring.js @@ -0,0 +1,159 @@ +// Copyright 2011 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. + +// 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 success = "[test success]"; +var expectedThis; +function testJoin() { + assertEquals(0, arguments.length); + assertSame(expectedThis, this); + return success; +} + + +// On an Array object. + +// Default case. +var a1 = [1, 2, 3]; +assertEquals(a1.join(), a1.toString()); + +// Non-standard "join" function is called correctly. +var a2 = [1, 2, 3]; +a2.join = testJoin; +expectedThis = a2; +assertEquals(success, a2.toString()); + +// Non-callable join function is ignored and Object.prototype.toString is +// used instead. +var a3 = [1, 2, 3]; +a3.join = "not callable"; +assertEquals("[object Array]", a3.toString()); + +// Non-existing join function is treated same as non-callable. +var a4 = [1, 2, 3]; +a4.__proto__ = { toString: Array.prototype.toString }; +// No join on Array. +assertEquals("[object Array]", a4.toString()); + + +// On a non-Array object. + +// Default looks-like-an-array case. +var o1 = {length: 3, 0: 1, 1: 2, 2: 3, + toString: Array.prototype.toString, + join: Array.prototype.join}; +assertEquals(o1.join(), o1.toString()); + + +// Non-standard join is called correctly. +// Check that we don't read, e.g., length before calling join. +var o2 = {toString : Array.prototype.toString, + join: testJoin, + get length() { assertUnreachable(); }, + get 0() { assertUnreachable(); }}; +expectedThis = o2; +assertEquals(success, o2.toString()); + +// Non-standard join is called even if it looks like an array. +var o3 = {length: 3, 0: 1, 1: 2, 2: 3, + toString: Array.prototype.toString, + join: testJoin}; +expectedThis = o3; +assertEquals(success, o3.toString()); + +// Non-callable join works same as for Array. +var o4 = {length: 3, 0: 1, 1: 2, 2: 3, + toString: Array.prototype.toString, + join: "not callable"}; +assertEquals("[object Object]", o4.toString()); + + +// Non-existing join works same as for Array. +var o5 = {length: 3, 0: 1, 1: 2, 2: 3, + toString: Array.prototype.toString + /* no join */}; +assertEquals("[object Object]", o5.toString()); + + +// Test that ToObject is called before getting "join", so the instance +// that "join" is read from is the same one passed as receiver later. +var called_before = false; +expectedThis = null; +Object.defineProperty(Number.prototype, "join", {get: function() { + assertFalse(called_before); + called_before = true; + expectedThis = this; + return testJoin; + }}); +Number.prototype.arrayToString = Array.prototype.toString; +assertEquals(success, (42).arrayToString()); + +// ---------------------------------------------------------- +// Testing Array.prototype.toLocaleString + +// Ensure that it never uses Array.prototype.toString for anything. +Array.prototype.toString = function() { assertUnreachable(); }; + +// Default case. +var la1 = [1, [2, 3], 4]; +assertEquals("1,2,3,4", la1.toLocaleString()); + +// Used on a string (which looks like an array of characters). +String.prototype.toLocaleString = Array.prototype.toLocaleString; +assertEquals("1,2,3,4", "1234".toLocaleString()); + +// If toLocaleString of element is not callable, throw a TypeError. +var la2 = [1, {toLocaleString: "not callable"}, 3]; +assertThrows(function() { la2.toLocaleString(); }, TypeError); + +// If toLocaleString of element is callable, call it. +var la3 = [1, {toLocaleString: function() { return "XX";}}, 3]; +assertEquals("1,XX,3", la3.toLocaleString()); + +// Omitted elements, as well as undefined and null, become empty string. +var la4 = [1, null, 3, undefined, 5,, 7]; +assertEquals("1,,3,,5,,7", la4.toLocaleString()); + + +// ToObject is called first and the same object is being used for the +// rest of the operations. +Object.defineProperty(Number.prototype, "length", { + get: function() { + exptectedThis = this; + return 3; + }}); +for (var i = 0; i < 3; i++) { + Object.defineProperty(Number.prototype, i, { + get: function() { + assertEquals(expectedThis, this); + return +this; + }}); +} +Number.prototype.arrayToLocaleString = Array.prototype.toLocaleString; +assertEquals("42,42,42", (42).arrayToLocaleString());
\ No newline at end of file diff --git a/test/mjsunit/assert-opt-and-deopt.js b/test/mjsunit/assert-opt-and-deopt.js index c9adb5bb..51cb99ad 100644 --- a/test/mjsunit/assert-opt-and-deopt.js +++ b/test/mjsunit/assert-opt-and-deopt.js @@ -150,11 +150,6 @@ tracker.AssertDeoptCount(f, 0); f(1); -tracker.AssertOptCount(f, 0); -tracker.AssertIsOptimized(f, false); -tracker.AssertDeoptHappened(f, false); -tracker.AssertDeoptCount(f, 0); - %OptimizeFunctionOnNextCall(f); f(1); @@ -172,6 +167,7 @@ tracker.AssertDeoptCount(f, 1); // Let's trigger optimization for another type. for (var i = 0; i < 5; i++) f("a"); + %OptimizeFunctionOnNextCall(f); f("b"); diff --git a/test/mjsunit/bugs/bug-618.js b/test/mjsunit/bugs/bug-618.js index ae843267..0513f87f 100644 --- a/test/mjsunit/bugs/bug-618.js +++ b/test/mjsunit/bugs/bug-618.js @@ -42,4 +42,4 @@ function C() { assertEquals(23, new C().x); C.prototype.__defineSetter__('x', function(value) { this.y = 23; }); -assertEquals(void 0, new C().x)); +assertEquals(void 0, new C().x); diff --git a/test/mjsunit/bugs/harmony/debug-blockscopes.js b/test/mjsunit/bugs/harmony/debug-blockscopes.js index a407c531..fda32eb3 100644 --- a/test/mjsunit/bugs/harmony/debug-blockscopes.js +++ b/test/mjsunit/bugs/harmony/debug-blockscopes.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 --harmony-block-scoping +// Flags: --expose-debug-as debug --harmony-scoping // The functions used for testing backtraces. They are at the top to make the // testing of source line/column easier. diff --git a/test/mjsunit/builtins.js b/test/mjsunit/builtins.js index f2ad5446..e43b5891 100644 --- a/test/mjsunit/builtins.js +++ b/test/mjsunit/builtins.js @@ -27,8 +27,7 @@ // Flags: --expose-natives-as=builtins -// Checks that all function properties of the builtin object are neither -// writable nor configurable. Also, theose functions that are actually +// Checks that all function properties of the builtin object that are actually // constructors (recognized by having properties on their .prototype object), // have only unconfigurable properties on the prototype, and the methods // are also non-writable. @@ -75,8 +74,6 @@ for (var i = 0; i < names.length; i++) { assertTrue(desc.hasOwnProperty("value")); var value = desc.value; if (isFunction(value)) { - assertFalse(desc.writable, name); - assertFalse(desc.configurable, name); checkConstructor(value, name); } } diff --git a/test/mjsunit/comparison-ops-and-undefined.js b/test/mjsunit/comparison-ops-and-undefined.js new file mode 100644 index 00000000..06db0765 --- /dev/null +++ b/test/mjsunit/comparison-ops-and-undefined.js @@ -0,0 +1,128 @@ +// 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 + +function test_helper_for_ics(func, b1, b2, b3, b4) { + assertEquals(b1, func(.5, .5)); + assertEquals(b2, func(.5, undefined)); + assertEquals(b3, func(undefined, .5)); + assertEquals(b4, func(undefined, undefined)); +} + +function test_helper_for_crankshaft(func, b1, b2, b3, b4) { + assertEquals(b1, func(.5, .5)); + %OptimizeFunctionOnNextCall(func); + assertEquals(b1, func(.5, .5)); + assertEquals(b2, func(.5, undefined)); + assertEquals(b3, func(undefined, .5)); + assertEquals(b4, func(undefined, undefined)); +} + +function less_1(a, b) { + return a < b; +} + +test_helper_for_ics(less_1, false, false, false, false); + +function less_2(a, b) { + return a < b; +} + +test_helper_for_crankshaft(less_1, false, false, false, false); + +function greater_1(a, b) { + return a > b; +} + +test_helper_for_ics(greater_1, false, false, false, false); + +function greater_2(a, b) { + return a > b; +} + +test_helper_for_crankshaft(greater_1, false, false, false, false); + +function less_equal_1(a, b) { + return a <= b; +} + +test_helper_for_ics(less_equal_1, true, false, false, false); + +function less_equal_2(a, b) { + return a <= b; +} + +test_helper_for_crankshaft(less_equal_1, true, false, false, false); + +function greater_equal_1(a, b) { + return a >= b; +} + +test_helper_for_ics(greater_equal_1, true, false, false, false); + +function greater_equal_2(a, b) { + return a >= b; +} + +test_helper_for_crankshaft(greater_equal_1, true, false, false, false); + +function equal_1(a, b) { + return a == b; +} + +test_helper_for_ics(equal_1, true, false, false, true); + +function equal_2(a, b) { + return a == b; +} + +test_helper_for_crankshaft(equal_2, true, false, false, true); + +function strict_equal_1(a, b) { + return a === b; +} + +test_helper_for_ics(strict_equal_1, true, false, false, true); + +function strict_equal_2(a, b) { + return a === b; +} + +test_helper_for_crankshaft(strict_equal_2, true, false, false, true); + +function not_equal_1(a, b) { + return a != b; +} + +test_helper_for_ics(not_equal_1, false, true, true, false); + +function not_equal_2(a, b) { + return a != b; +} + +test_helper_for_crankshaft(not_equal_2, false, true, true, false); diff --git a/test/mjsunit/compiler/alloc-object-huge.js b/test/mjsunit/compiler/alloc-object-huge.js new file mode 100644 index 00000000..d6d9f1b7 --- /dev/null +++ b/test/mjsunit/compiler/alloc-object-huge.js @@ -0,0 +1,308 @@ +// 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 --inline-construct --nolimit-inlining + +// Test that huge constructors (more than 256 this assignments) are +// handled correctly. + +// Test huge constructor when being inlined into hydrogen. +function test() { + return new huge(); +} +test(); +test(); +%OptimizeFunctionOnNextCall(test); +var o = test(); +assertEquals(1, o.foo1); +assertEquals(257, o.foo257); + +// Test huge constructor with specialized constructor stub. +var o = new huge(); +assertEquals(1, o.foo1); +assertEquals(257, o.foo257); + +// The huge constructor, nothing interesting beyond this point. +function huge() { + this.foo1 = 1; + this.foo2 = 2; + this.foo3 = 3; + this.foo4 = 4; + this.foo5 = 5; + this.foo6 = 6; + this.foo7 = 7; + this.foo8 = 8; + this.foo9 = 9; + this.foo10 = 10; + this.foo11 = 11; + this.foo12 = 12; + this.foo13 = 13; + this.foo14 = 14; + this.foo15 = 15; + this.foo16 = 16; + this.foo17 = 17; + this.foo18 = 18; + this.foo19 = 19; + this.foo20 = 20; + this.foo21 = 21; + this.foo22 = 22; + this.foo23 = 23; + this.foo24 = 24; + this.foo25 = 25; + this.foo26 = 26; + this.foo27 = 27; + this.foo28 = 28; + this.foo29 = 29; + this.foo30 = 30; + this.foo31 = 31; + this.foo32 = 32; + this.foo33 = 33; + this.foo34 = 34; + this.foo35 = 35; + this.foo36 = 36; + this.foo37 = 37; + this.foo38 = 38; + this.foo39 = 39; + this.foo40 = 40; + this.foo41 = 41; + this.foo42 = 42; + this.foo43 = 43; + this.foo44 = 44; + this.foo45 = 45; + this.foo46 = 46; + this.foo47 = 47; + this.foo48 = 48; + this.foo49 = 49; + this.foo50 = 50; + this.foo51 = 51; + this.foo52 = 52; + this.foo53 = 53; + this.foo54 = 54; + this.foo55 = 55; + this.foo56 = 56; + this.foo57 = 57; + this.foo58 = 58; + this.foo59 = 59; + this.foo60 = 60; + this.foo61 = 61; + this.foo62 = 62; + this.foo63 = 63; + this.foo64 = 64; + this.foo65 = 65; + this.foo66 = 66; + this.foo67 = 67; + this.foo68 = 68; + this.foo69 = 69; + this.foo70 = 70; + this.foo71 = 71; + this.foo72 = 72; + this.foo73 = 73; + this.foo74 = 74; + this.foo75 = 75; + this.foo76 = 76; + this.foo77 = 77; + this.foo78 = 78; + this.foo79 = 79; + this.foo80 = 80; + this.foo81 = 81; + this.foo82 = 82; + this.foo83 = 83; + this.foo84 = 84; + this.foo85 = 85; + this.foo86 = 86; + this.foo87 = 87; + this.foo88 = 88; + this.foo89 = 89; + this.foo90 = 90; + this.foo91 = 91; + this.foo92 = 92; + this.foo93 = 93; + this.foo94 = 94; + this.foo95 = 95; + this.foo96 = 96; + this.foo97 = 97; + this.foo98 = 98; + this.foo99 = 99; + this.foo100 = 100; + this.foo101 = 101; + this.foo102 = 102; + this.foo103 = 103; + this.foo104 = 104; + this.foo105 = 105; + this.foo106 = 106; + this.foo107 = 107; + this.foo108 = 108; + this.foo109 = 109; + this.foo110 = 110; + this.foo111 = 111; + this.foo112 = 112; + this.foo113 = 113; + this.foo114 = 114; + this.foo115 = 115; + this.foo116 = 116; + this.foo117 = 117; + this.foo118 = 118; + this.foo119 = 119; + this.foo120 = 120; + this.foo121 = 121; + this.foo122 = 122; + this.foo123 = 123; + this.foo124 = 124; + this.foo125 = 125; + this.foo126 = 126; + this.foo127 = 127; + this.foo128 = 128; + this.foo129 = 129; + this.foo130 = 130; + this.foo131 = 131; + this.foo132 = 132; + this.foo133 = 133; + this.foo134 = 134; + this.foo135 = 135; + this.foo136 = 136; + this.foo137 = 137; + this.foo138 = 138; + this.foo139 = 139; + this.foo140 = 140; + this.foo141 = 141; + this.foo142 = 142; + this.foo143 = 143; + this.foo144 = 144; + this.foo145 = 145; + this.foo146 = 146; + this.foo147 = 147; + this.foo148 = 148; + this.foo149 = 149; + this.foo150 = 150; + this.foo151 = 151; + this.foo152 = 152; + this.foo153 = 153; + this.foo154 = 154; + this.foo155 = 155; + this.foo156 = 156; + this.foo157 = 157; + this.foo158 = 158; + this.foo159 = 159; + this.foo160 = 160; + this.foo161 = 161; + this.foo162 = 162; + this.foo163 = 163; + this.foo164 = 164; + this.foo165 = 165; + this.foo166 = 166; + this.foo167 = 167; + this.foo168 = 168; + this.foo169 = 169; + this.foo170 = 170; + this.foo171 = 171; + this.foo172 = 172; + this.foo173 = 173; + this.foo174 = 174; + this.foo175 = 175; + this.foo176 = 176; + this.foo177 = 177; + this.foo178 = 178; + this.foo179 = 179; + this.foo180 = 180; + this.foo181 = 181; + this.foo182 = 182; + this.foo183 = 183; + this.foo184 = 184; + this.foo185 = 185; + this.foo186 = 186; + this.foo187 = 187; + this.foo188 = 188; + this.foo189 = 189; + this.foo190 = 190; + this.foo191 = 191; + this.foo192 = 192; + this.foo193 = 193; + this.foo194 = 194; + this.foo195 = 195; + this.foo196 = 196; + this.foo197 = 197; + this.foo198 = 198; + this.foo199 = 199; + this.foo200 = 200; + this.foo201 = 201; + this.foo202 = 202; + this.foo203 = 203; + this.foo204 = 204; + this.foo205 = 205; + this.foo206 = 206; + this.foo207 = 207; + this.foo208 = 208; + this.foo209 = 209; + this.foo210 = 210; + this.foo211 = 211; + this.foo212 = 212; + this.foo213 = 213; + this.foo214 = 214; + this.foo215 = 215; + this.foo216 = 216; + this.foo217 = 217; + this.foo218 = 218; + this.foo219 = 219; + this.foo220 = 220; + this.foo221 = 221; + this.foo222 = 222; + this.foo223 = 223; + this.foo224 = 224; + this.foo225 = 225; + this.foo226 = 226; + this.foo227 = 227; + this.foo228 = 228; + this.foo229 = 229; + this.foo230 = 230; + this.foo231 = 231; + this.foo232 = 232; + this.foo233 = 233; + this.foo234 = 234; + this.foo235 = 235; + this.foo236 = 236; + this.foo237 = 237; + this.foo238 = 238; + this.foo239 = 239; + this.foo240 = 240; + this.foo241 = 241; + this.foo242 = 242; + this.foo243 = 243; + this.foo244 = 244; + this.foo245 = 245; + this.foo246 = 246; + this.foo247 = 247; + this.foo248 = 248; + this.foo249 = 249; + this.foo250 = 250; + this.foo251 = 251; + this.foo252 = 252; + this.foo253 = 253; + this.foo254 = 254; + this.foo255 = 255; + this.foo256 = 256; + this.foo257 = 257; +} diff --git a/test/mjsunit/compiler/alloc-object.js b/test/mjsunit/compiler/alloc-object.js new file mode 100644 index 00000000..1d44efb5 --- /dev/null +++ b/test/mjsunit/compiler/alloc-object.js @@ -0,0 +1,90 @@ +// 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 --expose-gc --inline-construct + +// Test that inlined object allocation works for different layouts of +// objects (e.g. in object properties, slack tracking in progress or +// changing of function prototypes) + +function test_helper(construct, a, b) { + return new construct(a, b); +} + +function test(construct) { + %DeoptimizeFunction(test); + test_helper(construct, 0, 0); + test_helper(construct, 0, 0); + %OptimizeFunctionOnNextCall(test_helper); + // Test adding a new property after allocation was inlined. + var o = test_helper(construct, 1, 2); + o.z = 3; + assertEquals(1, o.x); + assertEquals(2, o.y); + assertEquals(3, o.z); + // Test changing the prototype after allocation was inlined. + construct.prototype = { z:6 }; + var o = test_helper(construct, 4, 5); + assertEquals(4, o.x); + assertEquals(5, o.y); + assertEquals(6, o.z); + %DeoptimizeFunction(test_helper); + gc(); // Makes V8 forget about type information for test_helper. +} + +function finalize_slack_tracking(construct) { + // Value chosen based on kGenerousAllocationCount = 8. + for (var i = 0; i < 8; i++) { + new construct(0, 0); + } +} + + +// Both properties are pre-allocated in object properties. +function ConstructInObjectPreAllocated(a, b) { + this.x = a; + this.y = b; +} +finalize_slack_tracking(ConstructInObjectPreAllocated); +test(ConstructInObjectPreAllocated); + + +// Both properties are unused in object properties. +function ConstructInObjectUnused(a, b) { + this.x = a < 0 ? 0 : a; + this.y = b > 0 ? b : 0; +} +finalize_slack_tracking(ConstructInObjectUnused); +test(ConstructInObjectUnused); + + +// Test inlined allocation while slack tracking is still in progress. +function ConstructWhileSlackTracking(a, b) { + this.x = a; + this.y = b; +} +test(ConstructWhileSlackTracking); diff --git a/test/mjsunit/compiler/compare.js b/test/mjsunit/compiler/compare.js index 3f960870..460b0ab0 100644 --- a/test/mjsunit/compiler/compare.js +++ b/test/mjsunit/compiler/compare.js @@ -83,9 +83,9 @@ function TestNonPrimitive(order, f) { } TestNonPrimitive("xy", MaxLT); -TestNonPrimitive("yx", MaxLE); +TestNonPrimitive("xy", MaxLE); TestNonPrimitive("xy", MaxGE); -TestNonPrimitive("yx", MaxGT); +TestNonPrimitive("xy", MaxGT); // Test compare in case of aliased registers. function CmpX(x) { if (x == x) return 42; } diff --git a/test/mjsunit/compiler/inline-arguments.js b/test/mjsunit/compiler/inline-arguments.js index 532fc26a..b6adf7f6 100644 --- a/test/mjsunit/compiler/inline-arguments.js +++ b/test/mjsunit/compiler/inline-arguments.js @@ -27,11 +27,89 @@ // Flags: --allow-natives-syntax -// Test inlining functions that use arguments. -function f() { return g(1, 2, 3); } +function A() { +} -function g(x, y, z) { return %_ArgumentsLength(); } +A.prototype.X = function (a, b, c) { + assertTrue(this instanceof A); + assertEquals(1, a); + assertEquals(2, b); + assertEquals(3, c); +}; -for (var i = 0; i < 5; ++i) f(); -%OptimizeFunctionOnNextCall(f); -assertEquals(3, f()); +A.prototype.Y = function () { + this.X.apply(this, arguments); +}; + +A.prototype.Z = function () { + this.Y(1,2,3); +}; + +var a = new A(); +a.Z(4,5,6); +a.Z(4,5,6); +%OptimizeFunctionOnNextCall(a.Z); +a.Z(4,5,6); +A.prototype.X.apply = function (receiver, args) { + return Function.prototype.apply.call(this, receiver, args); +}; +a.Z(4,5,6); + + +// Ensure that HArgumentsObject is inserted in a correct place +// and dominates all uses. +function F1() { } +function F2() { F1.apply(this, arguments); } +function F3(x, y) { + if (x) { + F2(y); + } +} + +function F31() { + return F1.apply(this, arguments); +} + +function F4() { + F3(true, false); + return F31(1); +} + +F4(1); +F4(1); +F4(1); +%OptimizeFunctionOnNextCall(F4); +F4(1); + + +// Test correct adapation of arguments. +// Strict mode prevents arguments object from shadowing parameters. +(function () { + "use strict"; + + function G2() { + assertArrayEquals([1,2], arguments); + } + + function G4() { + assertArrayEquals([1,2,3,4], arguments); + } + + function adapt2to4(a, b, c, d) { + G2.apply(this, arguments); + } + + function adapt4to2(a, b) { + G4.apply(this, arguments); + } + + function test_adaptation() { + adapt2to4(1, 2); + adapt4to2(1, 2, 3, 4); + } + + test_adaptation(); + test_adaptation(); + %OptimizeFunctionOnNextCall(test_adaptation); + test_adaptation(); +})(); diff --git a/test/mjsunit/compiler/inline-arity-mismatch.js b/test/mjsunit/compiler/inline-arity-mismatch.js new file mode 100644 index 00000000..4a61fa3a --- /dev/null +++ b/test/mjsunit/compiler/inline-arity-mismatch.js @@ -0,0 +1,62 @@ +// 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 + +// Test inlining at call sites with mismatched arity. + +function f(a) { + return a.x; +} + +function g(a, b) { + return a.x; +} + +function h1(a, b) { + return f(a, a) * g(b); +} + +function h2(a, b) { + return f(a, a) * g(b); +} + + +var o = {x: 2}; + +assertEquals(4, h1(o, o)); +assertEquals(4, h1(o, o)); +assertEquals(4, h2(o, o)); +assertEquals(4, h2(o, o)); +%OptimizeFunctionOnNextCall(h1); +%OptimizeFunctionOnNextCall(h2); +assertEquals(4, h1(o, o)); +assertEquals(4, h2(o, o)); + +var u = {y:0, x:1}; +assertEquals(2, h1(u, o)); +assertEquals(2, h2(o, u)); diff --git a/test/mjsunit/compiler/inline-construct.js b/test/mjsunit/compiler/inline-construct.js new file mode 100644 index 00000000..af9e69c9 --- /dev/null +++ b/test/mjsunit/compiler/inline-construct.js @@ -0,0 +1,152 @@ +// 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 --expose-gc --inline-construct + +// Test inlining of constructor calls. + +function TestInlinedConstructor(closure) { + var result; + var counter = { value:0 }; + result = closure(11, 12, counter); + assertEquals(23, result); + assertEquals(1, counter.value); + result = closure(23, 19, counter); + assertEquals(42, result); + assertEquals(2, counter.value); + %OptimizeFunctionOnNextCall(closure); + result = closure(1, 42, counter) + assertEquals(43, result); + assertEquals(3, counter.value); + result = closure("foo", "bar", counter) + assertEquals("foobar", result) + assertEquals(4, counter.value); +} + +function TestInAllContexts(constructor) { + function value_context(a, b, counter) { + var obj = new constructor(a, b, counter); + return obj.x; + } + function test_context(a, b, counter) { + if (!new constructor(a, b, counter)) { + assertUnreachable("should not happen"); + } + return a + b; + } + function effect_context(a, b, counter) { + new constructor(a, b, counter); + return a + b; + } + TestInlinedConstructor(value_context); + TestInlinedConstructor(test_context); + TestInlinedConstructor(effect_context); + %DeoptimizeFunction(value_context); + %DeoptimizeFunction(test_context); + %DeoptimizeFunction(effect_context); + gc(); // Makes V8 forget about type information for *_context. +} + + +// Test constructor returning nothing in all contexts. +function c1(a, b, counter) { + this.x = a + b; + counter.value++; +} +TestInAllContexts(c1); + + +// Test constructor returning an object in all contexts. +function c2(a, b, counter) { + var obj = new Object(); + obj.x = a + b; + counter.value++; + return obj; +} +TestInAllContexts(c2); + + +// Test constructor returning a primitive value in all contexts. +function c3(a, b, counter) { + this.x = a + b; + counter.value++; + return "not an object"; +} +TestInAllContexts(c3); + + +// Test constructor called with too many arguments. +function c_too_many(a, b) { + this.x = a + b; +} +function f_too_many(a, b, c) { + var obj = new c_too_many(a, b, c); + return obj.x; +} +assertEquals(23, f_too_many(11, 12, 1)); +assertEquals(42, f_too_many(23, 19, 1)); +%OptimizeFunctionOnNextCall(f_too_many); +assertEquals(43, f_too_many(1, 42, 1)); +assertEquals("foobar", f_too_many("foo", "bar", "baz")) + + +// Test constructor called with too few arguments. +function c_too_few(a, b) { + assertSame(undefined, b); + this.x = a + 1; +} +function f_too_few(a) { + var obj = new c_too_few(a); + return obj.x; +} +assertEquals(12, f_too_few(11)); +assertEquals(24, f_too_few(23)); +%OptimizeFunctionOnNextCall(f_too_few); +assertEquals(2, f_too_few(1)); +assertEquals("foo1", f_too_few("foo")) + + +// Test constructor that cannot be inlined. +function c_unsupported_syntax(a, b, counter) { + try { + this.x = a + b; + counter.value++; + } catch(e) { + throw new Error(); + } +} +TestInAllContexts(c_unsupported_syntax); + + +// Regression test: Inlined constructors called as functions do not get their +// implicit receiver object set to undefined, even in strict mode. +function c_strict(a, b, counter) { + "use strict"; + this.x = a + b; + counter.value++; +} +TestInAllContexts(c_strict); diff --git a/test/mjsunit/compiler/inline-context-slots.js b/test/mjsunit/compiler/inline-context-slots.js new file mode 100644 index 00000000..d0e907b1 --- /dev/null +++ b/test/mjsunit/compiler/inline-context-slots.js @@ -0,0 +1,49 @@ +// Copyright 2011 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 inlining of functions with context slots. + +// Flags: --allow-natives-syntax + + +// Caller/callee without a local context. + +(function() { + var X = 5; + var Y = 10; + function F() {} + F.prototype.max = function() { + return X > Y ? X : Y; + } + F.prototype.run = function() { + return this.max(); + } + var f = new F(); + for (var i=0; i<5; i++) f.run(); + %OptimizeFunctionOnNextCall(f.run); + assertEquals(10, f.run()); +})(); diff --git a/test/mjsunit/compiler/inline-literals.js b/test/mjsunit/compiler/inline-literals.js new file mode 100644 index 00000000..f78abe82 --- /dev/null +++ b/test/mjsunit/compiler/inline-literals.js @@ -0,0 +1,50 @@ +// 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 + +// Test that we can inline functions containing materialized literals. + +function o2(b, c) { + return { 'b':b, 'c':c, 'y':b + c }; +} + +function o1(a, b, c) { + return { 'a':a, 'x':o2(b, c) }; +} + +function TestObjectLiteral(a, b, c) { + var expected = { 'a':a, 'x':{ 'b':b, 'c':c, 'y':b + c } }; + var result = o1(a, b, c); + assertEquals(expected, result, "TestObjectLiteral"); +} + +TestObjectLiteral(1, 2, 3); +TestObjectLiteral(1, 2, 3); +%OptimizeFunctionOnNextCall(TestObjectLiteral); +TestObjectLiteral(1, 2, 3); +TestObjectLiteral('a', 'b', 'c'); diff --git a/test/mjsunit/regress/regress-221.js b/test/mjsunit/compiler/lazy-const-lookup.js index d3f2e355..b4f15a1c 100644 --- a/test/mjsunit/regress/regress-221.js +++ b/test/mjsunit/compiler/lazy-const-lookup.js @@ -1,4 +1,4 @@ -// Copyright 2009 the V8 project authors. All rights reserved. +// Copyright 2011 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,10 +25,17 @@ // (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 that direct eval calls handle the case where eval has been -// deleted correctly. +// Flags: --allow-natives-syntax -// See http://code.google.com/p/v8/issues/detail?id=221 +function outer() { + const x = 1; + function inner() { + return x; + } + inner(); + %OptimizeFunctionOnNextCall(inner); + inner(); +} -assertThrows('eval(delete eval)'); +outer(); diff --git a/test/mjsunit/compiler/literals-optimized.js b/test/mjsunit/compiler/literals-optimized.js new file mode 100644 index 00000000..049e21a3 --- /dev/null +++ b/test/mjsunit/compiler/literals-optimized.js @@ -0,0 +1,121 @@ +// 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 + +// Test optimized versions of array and object literals. + +function TestOptimizedLiteral(create, verify) { + verify(create(1, 2, 3), 1, 2, 3); + verify(create(3, 5, 7), 3, 5, 7); + %OptimizeFunctionOnNextCall(create); + verify(create(11, 23, 42), 11, 23, 42); +} + + +// Test shallow array literal. +function create_arr_shallow(a, b, c) { + return [0, a, 0, b, 0, c]; +} +function verify_arr_shallow(array, a, b, c) { + assertSame(6, array.length); + assertSame(0, array[0]); + assertSame(a, array[1]); + assertSame(0, array[2]); + assertSame(b, array[3]); + assertSame(0, array[4]); + assertSame(c, array[5]); +} +TestOptimizedLiteral(create_arr_shallow, verify_arr_shallow); + + +// Test nested array literal. +function create_arr_nested(a, b, c) { + return [[0, a], [b, c], [1, 2], 3]; +} +function verify_arr_nested(array, a, b, c) { + assertSame(4, array.length); + assertSame(2, array[0].length); + assertSame(0, array[0][0]); + assertSame(a, array[0][1]); + assertSame(2, array[1].length); + assertSame(b, array[1][0]); + assertSame(c, array[1][1]); + assertSame(2, array[2].length); + assertSame(1, array[2][0]); + assertSame(2, array[2][1]); + assertSame(3, array[3]); +} +TestOptimizedLiteral(create_arr_nested, verify_arr_nested); + + +// Test shallow object literal. +function create_obj_shallow(a, b, c) { + return { x:a, y:b, z:c, v:'foo', 9:'bar' }; +} +function verify_obj_shallow(object, a, b, c) { + assertSame(a, object.x); + assertSame(b, object.y); + assertSame(c, object.z); + assertSame('foo', object.v); + assertSame('bar', object[9]); +} +TestOptimizedLiteral(create_obj_shallow, verify_obj_shallow); + + +// Test nested object literal. +function create_obj_nested(a, b, c) { + return { x:{ v:a, w:b }, y:{ v:1, w:2 }, z:c, v:'foo', 9:'bar' }; +} +function verify_obj_nested(object, a, b, c) { + assertSame(a, object.x.v); + assertSame(b, object.x.w); + assertSame(1, object.y.v); + assertSame(2, object.y.w); + assertSame(c, object.z); + assertSame('foo', object.v); + assertSame('bar', object[9]); +} +TestOptimizedLiteral(create_obj_nested, verify_obj_nested); + + +// Test mixed array and object literal. +function create_mixed_nested(a, b, c) { + return { x:[1, 2], y:[a, b], z:c, v:{ v:'foo' }, 9:'bar' }; +} +function verify_mixed_nested(object, a, b, c) { + assertSame(2, object.x.length); + assertSame(1, object.x[0]); + assertSame(2, object.x[1]); + assertSame(2, object.y.length); + assertSame(a, object.y[0]); + assertSame(b, object.y[1]); + assertSame(c, object.z); + assertSame('foo', object.v.v); + assertSame('bar', object[9]); +} +TestOptimizedLiteral(create_mixed_nested, verify_mixed_nested); diff --git a/test/mjsunit/compiler/math-floor-global.js b/test/mjsunit/compiler/math-floor-global.js new file mode 100644 index 00000000..9ec183fa --- /dev/null +++ b/test/mjsunit/compiler/math-floor-global.js @@ -0,0 +1,161 @@ +// 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: --max-new-space-size=256 --allow-natives-syntax + +// Test inlining of Math.floor when assigned to a global. +var flo = Math.floor; +var test_id = 0; + +function testFloor(expect, input) { + var test = new Function('n', + '"' + (test_id++) + '";return flo(n)'); + assertEquals(expect, test(input)); + assertEquals(expect, test(input)); + assertEquals(expect, test(input)); + %OptimizeFunctionOnNextCall(test); + assertEquals(expect, test(input)); +} + +function zero() { + var x = 0.5; + return (function() { return x - 0.5; })(); +} + +function test() { + testFloor(0, 0); + testFloor(0, zero()); + testFloor(-0, -0); + testFloor(Infinity, Infinity); + testFloor(-Infinity, -Infinity); + testFloor(NaN, NaN); + + // Ensure that a negative zero coming from Math.floor is properly handled + // by other operations. + function ifloor(x) { + return 1 / Math.floor(x); + } + assertEquals(-Infinity, ifloor(-0)); + assertEquals(-Infinity, ifloor(-0)); + assertEquals(-Infinity, ifloor(-0)); + %OptimizeFunctionOnNextCall(ifloor); + assertEquals(-Infinity, ifloor(-0)); + + testFloor(0, 0.1); + testFloor(0, 0.49999999999999994); + testFloor(0, 0.5); + testFloor(0, 0.7); + testFloor(-1, -0.1); + testFloor(-1, -0.49999999999999994); + testFloor(-1, -0.5); + testFloor(-1, -0.7); + testFloor(1, 1); + testFloor(1, 1.1); + testFloor(1, 1.5); + testFloor(1, 1.7); + testFloor(-1, -1); + testFloor(-2, -1.1); + testFloor(-2, -1.5); + testFloor(-2, -1.7); + + testFloor(0, Number.MIN_VALUE); + testFloor(-1, -Number.MIN_VALUE); + testFloor(Number.MAX_VALUE, Number.MAX_VALUE); + testFloor(-Number.MAX_VALUE, -Number.MAX_VALUE); + testFloor(Infinity, Infinity); + testFloor(-Infinity, -Infinity); + + // 2^30 is a smi boundary. + var two_30 = 1 << 30; + + testFloor(two_30, two_30); + testFloor(two_30, two_30 + 0.1); + testFloor(two_30, two_30 + 0.5); + testFloor(two_30, two_30 + 0.7); + + testFloor(two_30 - 1, two_30 - 1); + testFloor(two_30 - 1, two_30 - 1 + 0.1); + testFloor(two_30 - 1, two_30 - 1 + 0.5); + testFloor(two_30 - 1, two_30 - 1 + 0.7); + + testFloor(-two_30, -two_30); + testFloor(-two_30, -two_30 + 0.1); + testFloor(-two_30, -two_30 + 0.5); + testFloor(-two_30, -two_30 + 0.7); + + testFloor(-two_30 + 1, -two_30 + 1); + testFloor(-two_30 + 1, -two_30 + 1 + 0.1); + testFloor(-two_30 + 1, -two_30 + 1 + 0.5); + testFloor(-two_30 + 1, -two_30 + 1 + 0.7); + + // 2^52 is a precision boundary. + var two_52 = (1 << 30) * (1 << 22); + + testFloor(two_52, two_52); + testFloor(two_52, two_52 + 0.1); + assertEquals(two_52, two_52 + 0.5); + testFloor(two_52, two_52 + 0.5); + assertEquals(two_52 + 1, two_52 + 0.7); + testFloor(two_52 + 1, two_52 + 0.7); + + testFloor(two_52 - 1, two_52 - 1); + testFloor(two_52 - 1, two_52 - 1 + 0.1); + testFloor(two_52 - 1, two_52 - 1 + 0.5); + testFloor(two_52 - 1, two_52 - 1 + 0.7); + + testFloor(-two_52, -two_52); + testFloor(-two_52, -two_52 + 0.1); + testFloor(-two_52, -two_52 + 0.5); + testFloor(-two_52, -two_52 + 0.7); + + testFloor(-two_52 + 1, -two_52 + 1); + testFloor(-two_52 + 1, -two_52 + 1 + 0.1); + testFloor(-two_52 + 1, -two_52 + 1 + 0.5); + testFloor(-two_52 + 1, -two_52 + 1 + 0.7); +} + + +// Test in a loop to cover the custom IC and GC-related issues. +for (var i = 0; i < 50; i++) { + test(); +} + + +// Regression test for a bug where a negative zero coming from Math.floor +// was not properly handled by other operations. +function floorsum(i, n) { + var ret = Math.floor(n); + while (--i > 0) { + ret += Math.floor(n); + } + return ret; +} +assertEquals(-0, floorsum(1, -0)); +%OptimizeFunctionOnNextCall(floorsum); +// The optimized function will deopt. Run it with enough iterations to try +// to optimize via OSR (triggering the bug). +assertEquals(-0, floorsum(100000, -0)); diff --git a/test/mjsunit/compiler/math-floor-local.js b/test/mjsunit/compiler/math-floor-local.js new file mode 100644 index 00000000..e44b15c7 --- /dev/null +++ b/test/mjsunit/compiler/math-floor-local.js @@ -0,0 +1,161 @@ +// 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: --max-new-space-size=256 --allow-natives-syntax + +// Test inlining of Math.floor when assigned to a local. +var test_id = 0; + +function testFloor(expect, input) { + var test = new Function('n', + '"' + (test_id++) + + '";var f = Math.floor; return f(n)'); + assertEquals(expect, test(input)); + assertEquals(expect, test(input)); + assertEquals(expect, test(input)); + %OptimizeFunctionOnNextCall(test); + assertEquals(expect, test(input)); +} + +function zero() { + var x = 0.5; + return (function() { return x - 0.5; })(); +} + +function test() { + testFloor(0, 0); + testFloor(0, zero()); + testFloor(-0, -0); + testFloor(Infinity, Infinity); + testFloor(-Infinity, -Infinity); + testFloor(NaN, NaN); + + // Ensure that a negative zero coming from Math.floor is properly handled + // by other operations. + function ifloor(x) { + return 1 / Math.floor(x); + } + assertEquals(-Infinity, ifloor(-0)); + assertEquals(-Infinity, ifloor(-0)); + assertEquals(-Infinity, ifloor(-0)); + %OptimizeFunctionOnNextCall(ifloor); + assertEquals(-Infinity, ifloor(-0)); + + testFloor(0, 0.1); + testFloor(0, 0.49999999999999994); + testFloor(0, 0.5); + testFloor(0, 0.7); + testFloor(-1, -0.1); + testFloor(-1, -0.49999999999999994); + testFloor(-1, -0.5); + testFloor(-1, -0.7); + testFloor(1, 1); + testFloor(1, 1.1); + testFloor(1, 1.5); + testFloor(1, 1.7); + testFloor(-1, -1); + testFloor(-2, -1.1); + testFloor(-2, -1.5); + testFloor(-2, -1.7); + + testFloor(0, Number.MIN_VALUE); + testFloor(-1, -Number.MIN_VALUE); + testFloor(Number.MAX_VALUE, Number.MAX_VALUE); + testFloor(-Number.MAX_VALUE, -Number.MAX_VALUE); + testFloor(Infinity, Infinity); + testFloor(-Infinity, -Infinity); + + // 2^30 is a smi boundary. + var two_30 = 1 << 30; + + testFloor(two_30, two_30); + testFloor(two_30, two_30 + 0.1); + testFloor(two_30, two_30 + 0.5); + testFloor(two_30, two_30 + 0.7); + + testFloor(two_30 - 1, two_30 - 1); + testFloor(two_30 - 1, two_30 - 1 + 0.1); + testFloor(two_30 - 1, two_30 - 1 + 0.5); + testFloor(two_30 - 1, two_30 - 1 + 0.7); + + testFloor(-two_30, -two_30); + testFloor(-two_30, -two_30 + 0.1); + testFloor(-two_30, -two_30 + 0.5); + testFloor(-two_30, -two_30 + 0.7); + + testFloor(-two_30 + 1, -two_30 + 1); + testFloor(-two_30 + 1, -two_30 + 1 + 0.1); + testFloor(-two_30 + 1, -two_30 + 1 + 0.5); + testFloor(-two_30 + 1, -two_30 + 1 + 0.7); + + // 2^52 is a precision boundary. + var two_52 = (1 << 30) * (1 << 22); + + testFloor(two_52, two_52); + testFloor(two_52, two_52 + 0.1); + assertEquals(two_52, two_52 + 0.5); + testFloor(two_52, two_52 + 0.5); + assertEquals(two_52 + 1, two_52 + 0.7); + testFloor(two_52 + 1, two_52 + 0.7); + + testFloor(two_52 - 1, two_52 - 1); + testFloor(two_52 - 1, two_52 - 1 + 0.1); + testFloor(two_52 - 1, two_52 - 1 + 0.5); + testFloor(two_52 - 1, two_52 - 1 + 0.7); + + testFloor(-two_52, -two_52); + testFloor(-two_52, -two_52 + 0.1); + testFloor(-two_52, -two_52 + 0.5); + testFloor(-two_52, -two_52 + 0.7); + + testFloor(-two_52 + 1, -two_52 + 1); + testFloor(-two_52 + 1, -two_52 + 1 + 0.1); + testFloor(-two_52 + 1, -two_52 + 1 + 0.5); + testFloor(-two_52 + 1, -two_52 + 1 + 0.7); +} + + +// Test in a loop to cover the custom IC and GC-related issues. +for (var i = 0; i < 50; i++) { + test(); +} + + +// Regression test for a bug where a negative zero coming from Math.floor +// was not properly handled by other operations. +function floorsum(i, n) { + var ret = Math.floor(n); + while (--i > 0) { + ret += Math.floor(n); + } + return ret; +} +assertEquals(-0, floorsum(1, -0)); +%OptimizeFunctionOnNextCall(floorsum); +// The optimized function will deopt. Run it with enough iterations to try +// to optimize via OSR (triggering the bug). +assertEquals(-0, floorsum(100000, -0)); diff --git a/test/mjsunit/compiler/optimized-for-in.js b/test/mjsunit/compiler/optimized-for-in.js new file mode 100644 index 00000000..cb8c66df --- /dev/null +++ b/test/mjsunit/compiler/optimized-for-in.js @@ -0,0 +1,300 @@ +// 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: --optimize-for-in --allow-natives-syntax + +// Test for-in support in Crankshaft. For simplicity this tests assumes certain +// fixed iteration order for properties and will have to be adjusted if V8 +// stops following insertion order. + + +function a(t) { + var result = []; + for (var i in t) { + result.push(i + t[i]); + } + return result.join(''); +} + +// Check that we correctly deoptimize on map check. +function b(t) { + var result = []; + for (var i in t) { + result.push(i + t[i]); + delete t[i]; + } + return result.join(''); +} + +// Check that we correctly deoptimize during preparation step. +function c(t) { + var result = []; + for (var i in t) { + result.push(i + t[i]); + } + return result.join(''); +} + +// Check that we deoptimize to the place after side effect in the right state. +function d(t) { + var result = []; + var o; + for (var i in (o = t())) { + result.push(i + o[i]); + } + return result.join(''); +} + +// Check that we correctly deoptimize on map check inserted for fused load. +function e(t) { + var result = []; + for (var i in t) { + delete t[i]; + t[i] = i; + result.push(i + t[i]); + } + return result.join(''); +} + +// Nested for-in loops. +function f(t) { + var result = []; + for (var i in t) { + for (var j in t) { + result.push(i + j + t[i] + t[j]); + } + } + return result.join(''); +} + +// Deoptimization from the inner for-in loop. +function g(t) { + var result = []; + for (var i in t) { + for (var j in t) { + result.push(i + j + t[i] + t[j]); + var v = t[i]; + delete t[i]; + t[i] = v; + } + } + return result.join(''); +} + + +// Break from the inner for-in loop. +function h(t, deopt) { + var result = []; + for (var i in t) { + for (var j in t) { + result.push(i + j + t[i] + t[j]); + break; + } + } + deopt.deopt; + return result.join(''); +} + +// Continue in the inner loop. +function j(t, deopt) { + var result = []; + for (var i in t) { + for (var j in t) { + result.push(i + j + t[i] + t[j]); + continue; + } + } + deopt.deopt; + return result.join(''); +} + +// Continue of the outer loop. +function k(t, deopt) { + var result = []; + outer: for (var i in t) { + for (var j in t) { + result.push(i + j + t[i] + t[j]); + continue outer; + } + } + deopt.deopt; + return result.join(''); +} + +// Break of the outer loop. +function l(t, deopt) { + var result = []; + outer: for (var i in t) { + for (var j in t) { + result.push(i + j + t[i] + t[j]); + break outer; + } + } + deopt.deopt; + return result.join(''); +} + +// Test deoptimization from inlined frame (currently it is not inlined). +function m0(t, deopt) { + for (var i in t) { + for (var j in t) { + deopt.deopt; + return i + j + t[i] + t[j]; + } + } +} + +function m(t, deopt) { + return m0(t, deopt); +} + + +function tryFunction(s, mkT, f) { + var d = {deopt: false}; + assertEquals(s, f(mkT(), d)); + assertEquals(s, f(mkT(), d)); + assertEquals(s, f(mkT(), d)); + %OptimizeFunctionOnNextCall(f); + assertEquals(s, f(mkT(), d)); + assertEquals(s, f(mkT(), {})); +} + +var s = "a1b2c3d4"; +function mkTable() { return { a: "1", b: "2", c: "3", d: "4" }; } + + +tryFunction(s, mkTable, a); +tryFunction(s, mkTable, b); +tryFunction("0a1b2c3d", function () { return "abcd"; }, c); +tryFunction("0a1b2c3d", function () { + var cnt = false; + return function () { + cnt = true; + return "abcd"; + } +}, d); +tryFunction("aabbccdd", mkTable, e); + +function mkSmallTable() { return { a: "1", b: "2" }; } + +tryFunction("aa11ab12ba21bb22", mkSmallTable, f); +tryFunction("aa11ab12bb22ba21", mkSmallTable, g); +tryFunction("aa11ba21", mkSmallTable, h); +tryFunction("aa11ab12ba21bb22", mkSmallTable, j); +tryFunction("aa11ba21", mkSmallTable, h); +tryFunction("aa11ba21", mkSmallTable, k); +tryFunction("aa11", mkSmallTable, l); +tryFunction("aa11", mkSmallTable, m); + +// Test handling of null. +tryFunction("", function () { + return function () { return null; } +}, function (t) { + for (var i in t()) { return i; } + return ""; +}); + +// Test smis. +tryFunction("", function () { + return function () { return 11; } +}, function (t) { + for (var i in t()) { return i; } + return ""; +}); + +// Test LoadFieldByIndex for out of object properties. +function O() { this.a = 1; } +for (var i = 0; i < 10; i++) new O(); +tryFunction("a1b2c3d4e5f6", function () { + var o = new O(); + o.b = 2; + o.c = 3; + o.d = 4; + o.e = 5; + o.f = 6; + return o; +}, function (t) { + var r = []; + for (var i in t) r.push(i + t[i]); + return r.join(''); +}); + +// Test OSR inside for-in. +function osr_inner(t, limit) { + var r = 1; + for (var x in t) { + if (t.hasOwnProperty(x)) { + for (var i = 0; i < t[x].length; i++) { + r += t[x][i]; + if (i === limit) { + %OptimizeFunctionOnNextCall(osr_inner, "osr"); + } + } + r += x; + } + } + return r; +} + +function osr_outer(t, osr_after) { + var r = 1; + for (var x in t) { + for (var i = 0; i < t[x].length; i++) { + r += t[x][i]; + } + if (x === osr_after) { + %OptimizeFunctionOnNextCall(osr_outer, "osr"); + } + r += x; + } + return r; +} + +function osr_outer_and_deopt(t, osr_after) { + var r = 1; + for (var x in t) { + r += x; + if (x == osr_after) { + %OptimizeFunctionOnNextCall(osr_outer_and_deopt, "osr"); + } + } + return r; +} + +function test_osr() { + with ({}) {} // Disable optimizations of this function. + var arr = new Array(20); + for (var i = 0; i < arr.length; i++) { + arr[i] = i + 1; + } + arr.push(":"); // Force deopt at the end of the loop. + assertEquals("211:x1234567891011121314151617181920:y", osr_inner({x: arr, y: arr}, (arr.length / 2) | 0)); + assertEquals("7x456y", osr_outer({x: [1,2,3], y: [4,5,6]}, "x")); + assertEquals("101234567", osr_outer_and_deopt([1,2,3,4,5,6,7,8], "5")); +} + +test_osr(); diff --git a/test/mjsunit/cyclic-error-to-string.js b/test/mjsunit/compiler/regress-96989.js index 2502b534..aedeb243 100644 --- a/test/mjsunit/cyclic-error-to-string.js +++ b/test/mjsunit/compiler/regress-96989.js @@ -25,22 +25,19 @@ // (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 printing of cyclic errors which return the empty string for -// compatibility with Safari and Firefox. -var e = new Error(); -assertEquals('Error', e + ''); +// Flags: --allow-natives-syntax -e = new Error(); -e.name = e; -e.message = e; -e.stack = e; -e.arguments = e; -assertEquals(': ', e + ''); +// Test correct handling of uninitialized const. -e = new Error(); -e.name = [ e ]; -e.message = [ e ]; -e.stack = [ e ]; -e.arguments = [ e ]; -assertEquals(': ', e + ''); +function test() { + for (var i = 41; i < 42; i++) { + var c = t ^ i; + } + const t; + return c; +} + +for (var i=0; i<10; i++) test(); +%OptimizeFunctionOnNextCall(test); +assertEquals(41, test()); diff --git a/test/mjsunit/compiler/regress-deopt-call-as-function.js b/test/mjsunit/compiler/regress-deopt-call-as-function.js new file mode 100644 index 00000000..c4080969 --- /dev/null +++ b/test/mjsunit/compiler/regress-deopt-call-as-function.js @@ -0,0 +1,62 @@ +// Copyright 2011 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 deoptimization after inlined call. + +function bar(a, b) {try { return a; } finally { } } + +function test_context() { + function foo(x) { return 42; } + var s, t; + for (var i = 0x7fff0000; i < 0x80000000; i++) { + bar(t = foo(i) ? bar(42 + i - i) : bar(0), s = i + t); + } + return s; +} +assertEquals(0x7fffffff + 42, test_context()); + + +function value_context() { + function foo(x) { return 42; } + var s, t; + for (var i = 0x7fff0000; i < 0x80000000; i++) { + bar(t = foo(i), s = i + t); + } + return s; +} +assertEquals(0x7fffffff + 42, value_context()); + + +function effect_context() { + function foo(x) { return 42; } + var s, t; + for (var i = 0x7fff0000; i < 0x80000000; i++) { + bar(foo(i), s = i + 42); + } + return s; +} +assertEquals(0x7fffffff + 42, effect_context()); diff --git a/test/mjsunit/compiler/regress-funarguments.js b/test/mjsunit/compiler/regress-funarguments.js index cea40bc9..c913bd95 100644 --- a/test/mjsunit/compiler/regress-funarguments.js +++ b/test/mjsunit/compiler/regress-funarguments.js @@ -1,4 +1,4 @@ -// Copyright 2010 the V8 project authors. All rights reserved. +// 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: @@ -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 + // Test function.arguments. function A() {} @@ -60,13 +62,16 @@ function hej(x) { return o.g(x, "z"); } -function stress() { - for (var i=0; i<5000000; i++) o.g(i, "g"); - for (var j=0; j<5000000; j++) hej(j); +function opt() { + for (var k=0; k<2; k++) { + for (var i=0; i<5; i++) o.g(i, "g"); + for (var j=0; j<5; j++) hej(j); + } + %OptimizeFunctionOnNextCall(o.g); + %OptimizeFunctionOnNextCall(hej); } -stress(); - +opt(); assertArrayEquals([0, "g"], o.g(0, "g")); assertArrayEquals([1, "f"], o.g(1, "g")); assertArrayEquals([0, "h"], hej(0)); @@ -74,8 +79,7 @@ assertArrayEquals([1, "f"], hej(1)); o = new B(); -stress(); - +opt(); assertArrayEquals([0, "f"], o.g(0, "g")); assertArrayEquals([1, "g"], o.g(1, "g")); assertArrayEquals([0, "f"], hej(0)); diff --git a/test/mjsunit/compiler/regress-inline-callfunctionstub.js b/test/mjsunit/compiler/regress-inline-callfunctionstub.js new file mode 100644 index 00000000..a39d26df --- /dev/null +++ b/test/mjsunit/compiler/regress-inline-callfunctionstub.js @@ -0,0 +1,46 @@ +// Copyright 2011 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 + +// Test inlined of calls-as-function two levels deep. +function f() { return 42; } + +var o = {g : function () { return f(); } } +function main(func) { + var v=0; + for (var i=0; i<1; i++) { + if (func()) v = 42; + } +} + +main(o.g); +main(o.g); +main(o.g); +%OptimizeFunctionOnNextCall(main); +main(o.g); + diff --git a/test/mjsunit/compiler/regress-toint32.js b/test/mjsunit/compiler/regress-toint32.js new file mode 100644 index 00000000..54c2f76d --- /dev/null +++ b/test/mjsunit/compiler/regress-toint32.js @@ -0,0 +1,45 @@ +// 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-sse3 + +var a = new Int32Array(1); +var G = 0x80000000; + +function f(x) { + var v = x; + v = v + 1; + a[0] = v; + v = v - 1; + return v; +} + +assertEquals(G, f(G)); +assertEquals(G, f(G)); +%OptimizeFunctionOnNextCall(f); +assertEquals(G, f(G)); + diff --git a/test/mjsunit/compiler/strict-recompile.js b/test/mjsunit/compiler/strict-recompile.js new file mode 100644 index 00000000..96e8bcab --- /dev/null +++ b/test/mjsunit/compiler/strict-recompile.js @@ -0,0 +1,51 @@ +// Copyright 2011 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 + +function foo() { + try { + var o = {}; + Object.defineProperty(o, 'x', {value: 12, writable: false}); + o.x = 13; + } catch(e) { + return true; + } + return false; +} + +assertFalse(foo()); + +function do_eval(str) { + "use strict"; + return eval(str); +} + +var eval_foo = do_eval('(' + foo + ')'); +for (var i = 0; i < 5; i++) assertTrue(eval_foo()); +%OptimizeFunctionOnNextCall(eval_foo); +assertTrue(eval_foo()); diff --git a/test/mjsunit/const-redecl.js b/test/mjsunit/const-redecl.js index 94597089..c0b97e6c 100644 --- a/test/mjsunit/const-redecl.js +++ b/test/mjsunit/const-redecl.js @@ -98,7 +98,8 @@ function TestAll(expected,s,opt_e) { var msg = s; if (opt_e) { e = opt_e; msg += "; " + opt_e; } assertEquals(expected, TestLocal(s,e), "local:'" + msg + "'"); - assertEquals(expected, TestGlobal(s,e), "global:'" + msg + "'"); + // Redeclarations of global consts do not throw, they are silently ignored. + assertEquals(42, TestGlobal(s, 42), "global:'" + msg + "'"); assertEquals(expected, TestContext(s,e), "context:'" + msg + "'"); } @@ -218,3 +219,62 @@ TestAll(0, "var a,b,c,d,e,f,g,h; " + loop, "x"); // Test that const inside with behaves correctly. TestAll(87, "with ({x:42}) { const x = 87; }", "x"); TestAll(undefined, "with ({x:42}) { const x; }", "x"); + + +// Additional tests for how various combinations of re-declarations affect +// the values of the var/const in question. +try { + eval("var undefined;"); +} catch (ex) { + assertUnreachable("undefined (1) has thrown"); +} + +var original_undef = undefined; +var undefined = 1; // Should be silently ignored. +assertEquals(original_undef, undefined, "undefined got overwritten"); +undefined = original_undef; + +var a; const a; const a = 1; +assertEquals(1, a, "a has wrong value"); +a = 2; +assertEquals(2, a, "a should be writable"); + +var b = 1; const b = 2; +assertEquals(2, b, "b has wrong value"); + +var c = 1; const c = 2; const c = 3; +assertEquals(3, c, "c has wrong value"); + +const d = 1; const d = 2; +assertEquals(1, d, "d has wrong value"); + +const e = 1; var e = 2; +assertEquals(1, e, "e has wrong value"); + +const f = 1; const f; +assertEquals(1, f, "f has wrong value"); + +var g; const g = 1; +assertEquals(1, g, "g has wrong value"); +g = 2; +assertEquals(2, g, "g should be writable"); + +const h; var h = 1; +assertEquals(undefined,h, "h has wrong value"); + +eval("Object.defineProperty(this, 'i', { writable: true });" + + "const i = 7;" + + "assertEquals(7, i, \"i has wrong value\");"); + +var global = this; +assertThrows(function() { + Object.defineProperty(global, 'j', { writable: true }) +}, TypeError); +const j = 2; // This is what makes the function above throw, because the +// const declaration gets hoisted and makes the property non-configurable. +assertEquals(2, j, "j has wrong value"); + +var k = 1; const k; +// You could argue about the expected result here. For now, the winning +// argument is that "const k;" is equivalent to "const k = undefined;". +assertEquals(undefined, k, "k has wrong value"); diff --git a/test/mjsunit/count-based-osr.js b/test/mjsunit/count-based-osr.js new file mode 100644 index 00000000..125c4e26 --- /dev/null +++ b/test/mjsunit/count-based-osr.js @@ -0,0 +1,38 @@ +// 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: --count-based-interrupts --interrupt-budget=10 --weighted-back-edges --allow-natives-syntax + +// Test that OSR works properly when using count-based interrupting/profiling. + +function osr_this() { + var a = 1; + // Trigger OSR. + while (%GetOptimizationStatus(osr_this) == 2) {} + return a; +} +assertEquals(1, osr_this()); diff --git a/test/mjsunit/d8-os.js b/test/mjsunit/d8-os.js index 56403268..239938cd 100644 --- a/test/mjsunit/d8-os.js +++ b/test/mjsunit/d8-os.js @@ -54,6 +54,8 @@ function str_error(str) { if (this.os && os.system) { + // Ensure that we have a valid working directory. + os.chdir("/tmp"); try { // Delete the dir if it is lying around from last time. os.system("ls", [TEST_DIR]); @@ -61,52 +63,53 @@ if (this.os && os.system) { } catch (e) { } os.mkdirp(TEST_DIR); - os.chdir(TEST_DIR); try { // Check the chdir worked. os.system('ls', [TEST_DIR]); // Simple create dir. - os.mkdirp("dir"); + os.mkdirp(TEST_DIR + "/dir"); // Create dir in dir. - os.mkdirp("dir/foo"); + os.mkdirp(TEST_DIR + "/dir/foo"); // Check that they are there. - os.system('ls', ['dir/foo']); + os.system('ls', [TEST_DIR + '/dir/foo']); // Check that we can detect when something is not there. - assertThrows("os.system('ls', ['dir/bar']);", "dir not there"); + assertThrows("os.system('ls', [TEST_DIR + '/dir/bar']);", "dir not there"); // Check that mkdirp makes intermediate directories. - os.mkdirp("dir2/foo"); - os.system("ls", ["dir2/foo"]); + os.mkdirp(TEST_DIR + "/dir2/foo"); + os.system("ls", [TEST_DIR + "/dir2/foo"]); // Check that mkdirp doesn't mind if the dir is already there. - os.mkdirp("dir2/foo"); - os.mkdirp("dir2/foo/"); + os.mkdirp(TEST_DIR + "/dir2/foo"); + os.mkdirp(TEST_DIR + "/dir2/foo/"); // Check that mkdirp can cope with trailing / - os.mkdirp("dir3/"); - os.system("ls", ["dir3"]); + os.mkdirp(TEST_DIR + "/dir3/"); + os.system("ls", [TEST_DIR + "/dir3"]); // Check that we get an error if the name is taken by a file. - os.system("sh", ["-c", "echo foo > file1"]); - os.system("ls", ["file1"]); - assertThrows("os.mkdirp('file1');", "mkdir over file1"); - assertThrows("os.mkdirp('file1/foo');", "mkdir over file2"); - assertThrows("os.mkdirp('file1/');", "mkdir over file3"); - assertThrows("os.mkdirp('file1/foo/');", "mkdir over file4"); + os.system("sh", ["-c", "echo foo > " + TEST_DIR + "/file1"]); + os.system("ls", [TEST_DIR + "/file1"]); + assertThrows("os.mkdirp(TEST_DIR + '/file1');", "mkdir over file1"); + assertThrows("os.mkdirp(TEST_DIR + '/file1/foo');", "mkdir over file2"); + assertThrows("os.mkdirp(TEST_DIR + '/file1/');", "mkdir over file3"); + assertThrows("os.mkdirp(TEST_DIR + '/file1/foo/');", "mkdir over file4"); // Create a dir we cannot read. - os.mkdirp("dir4", 0); + os.mkdirp(TEST_DIR + "/dir4", 0); // This test fails if you are root since root can read any dir. - assertThrows("os.chdir('dir4');", "chdir dir4 I"); - os.rmdir("dir4"); - assertThrows("os.chdir('dir4');", "chdir dir4 II"); - // Set umask. + assertThrows("os.chdir(TEST_DIR + '/dir4');", "chdir dir4 I"); + os.rmdir(TEST_DIR + "/dir4"); + assertThrows("os.chdir(TEST_DIR + '/dir4');", "chdir dir4 II"); + + // Set umask. This changes the umask for the whole process and is + // the reason why the test cannot be run multi-threaded. var old_umask = os.umask(0777); // Create a dir we cannot read. - os.mkdirp("dir5"); + os.mkdirp(TEST_DIR + "/dir5"); // This test fails if you are root since root can read any dir. - assertThrows("os.chdir('dir5');", "cd dir5 I"); - os.rmdir("dir5"); - assertThrows("os.chdir('dir5');", "chdir dir5 II"); + assertThrows("os.chdir(TEST_DIR + '/dir5');", "cd dir5 I"); + os.rmdir(TEST_DIR + "/dir5"); + assertThrows("os.chdir(TEST_DIR + '/dir5');", "chdir dir5 II"); os.umask(old_umask); - os.mkdirp("hest/fisk/../fisk/ged"); - os.system("ls", ["hest/fisk/ged"]); + os.mkdirp(TEST_DIR + "/hest/fisk/../fisk/ged"); + os.system("ls", [TEST_DIR + "/hest/fisk/ged"]); os.setenv("FOO", "bar"); var environment = os.system("printenv"); @@ -143,42 +146,43 @@ if (this.os && os.system) { assertEquals("baz\n", os.system("echo", ["baz"])); //} } + + // Too few args. + arg_error("os.umask();"); + arg_error("os.system();"); + arg_error("os.mkdirp();"); + arg_error("os.chdir();"); + arg_error("os.setenv();"); + arg_error("os.rmdir();"); + + // Too many args. + arg_error("os.setenv('FOO=bar');"); + arg_error("os.umask(0, 0);"); + arg_error("os.system('ls', [], -1, -1, -1);"); + arg_error("os.mkdirp('foo', 0, 0)"); + arg_error("os.chdir('foo', 'bar')"); + arg_error("os.rmdir('foo', 'bar');"); + + // Wrong kind of args. + arg_error("os.umask([]);"); + arg_error("os.system('ls', 'foo');"); + arg_error("os.system('ls', 123);"); + arg_error("os.system('ls', [], 'foo');"); + arg_error("os.system('ls', [], -1, 'foo');"); + arg_error("os.mkdirp('foo', 'bar');"); + + // Test broken toString(). + str_error("os.system(e);"); + str_error("os.system('ls', [e]);"); + str_error("os.system('ls', ['.', e]);"); + str_error("os.system('ls', [e, '.']);"); + str_error("os.mkdirp(e);"); + str_error("os.setenv(e, 'goo');"); + str_error("os.setenv('goo', e);"); + str_error("os.chdir(e);"); + str_error("os.rmdir(e);"); + } finally { os.system("rm", ["-r", TEST_DIR]); } - - // Too few args. - arg_error("os.umask();"); - arg_error("os.system();"); - arg_error("os.mkdirp();"); - arg_error("os.chdir();"); - arg_error("os.setenv();"); - arg_error("os.rmdir();"); - - // Too many args. - arg_error("os.setenv('FOO=bar');"); - arg_error("os.umask(0, 0);"); - arg_error("os.system('ls', [], -1, -1, -1);"); - arg_error("os.mkdirp('foo', 0, 0)"); - arg_error("os.chdir('foo', 'bar')"); - arg_error("os.rmdir('foo', 'bar');"); - - // Wrong kind of args. - arg_error("os.umask([]);"); - arg_error("os.system('ls', 'foo');"); - arg_error("os.system('ls', 123);"); - arg_error("os.system('ls', [], 'foo');"); - arg_error("os.system('ls', [], -1, 'foo');"); - arg_error("os.mkdirp('foo', 'bar');"); - - // Test broken toString(). - str_error("os.system(e);"); - str_error("os.system('ls', [e]);"); - str_error("os.system('ls', ['.', e]);"); - str_error("os.system('ls', [e, '.']);"); - str_error("os.mkdirp(e);"); - str_error("os.setenv(e, 'goo');"); - str_error("os.setenv('goo', e);"); - str_error("os.chdir(e);"); - str_error("os.rmdir(e);"); } diff --git a/test/mjsunit/date.js b/test/mjsunit/date.js index a7f6cfa7..3e153aba 100644 --- a/test/mjsunit/date.js +++ b/test/mjsunit/date.js @@ -157,7 +157,7 @@ testToLocaleTimeString(); // Test that -0 is treated correctly in MakeDay. var d = new Date(); assertDoesNotThrow("d.setDate(-0)"); -assertDoesNotThrow("new Date(-0, -0, -0, -0, -0, -0. -0)"); +assertDoesNotThrow("new Date(-0, -0, -0, -0, -0, -0, -0)"); assertDoesNotThrow("new Date(0x40000000, 0x40000000, 0x40000000," + "0x40000000, 0x40000000, 0x40000000, 0x40000000)") assertDoesNotThrow("new Date(-0x40000001, -0x40000001, -0x40000001," + @@ -178,7 +178,7 @@ assertTrue(isNaN(Date.UTC(-271821, 3, 19, 23, 59, 59, 999))); assertTrue(isNaN(Date.UTC(-271821, 3, 19))); -// Test creation of large date values. +// Test creation with large date values. d = new Date(1969, 12, 1, 99999999999); assertTrue(isNaN(d.getTime())); d = new Date(1969, 12, 1, -99999999999); @@ -187,6 +187,18 @@ d = new Date(1969, 12, 1, Infinity); assertTrue(isNaN(d.getTime())); d = new Date(1969, 12, 1, -Infinity); assertTrue(isNaN(d.getTime())); +d = new Date(1969, 12, 1, 0); +d.setTime(Math.pow(2, 64)); +assertTrue(isNaN(d.getTime())); +d = new Date(1969, 12, 1, 0); +d.setTime(Math.pow(-2, 64)); +assertTrue(isNaN(d.getTime())); + + +// Test creation with obscure date values. +assertEquals(8640000000000000, Date.UTC(1970, 0, 1 + 100000001, -24)); +assertEquals(-8640000000000000, Date.UTC(1970, 0, 1 - 100000001, 24)); + // Parsing ES5 ISO-8601 dates. // When TZ is omitted, it defaults to 'Z' meaning UTC. diff --git a/test/mjsunit/debug-break-inline.js b/test/mjsunit/debug-break-inline.js new file mode 100644 index 00000000..4418fa8d --- /dev/null +++ b/test/mjsunit/debug-break-inline.js @@ -0,0 +1,100 @@ +// Copyright 2011 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: --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 +// debugger is attached. +// +//See http://code.google.com/p/chromium/issues/detail?id=105375 + +// Get the Debug object exposed from the debug context global object. +Debug = debug.Debug; + +var count = 0; +var break_count = 0; + +// Debug event listener which sets a breakpoint first time it is hit +// and otherwise counts break points hit and checks that the expected +// state is reached. +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + break_count++; + if (break_count == 1) { + Debug.setBreakPoint(g, 3); + + for (var i = 0; i < exec_state.frameCount(); i++) { + var frame = exec_state.frame(i); + // When function f is optimized (1 means YES, see runtime.cc) we + // expect an optimized frame for f and g. + if (%GetOptimizationStatus(f) == 1) { + if (i == 1) { + assertTrue(frame.isOptimizedFrame()); + assertTrue(frame.isInlinedFrame()); + assertEquals(4 - i, frame.inlinedFrameIndex()); + } else if (i == 2) { + assertTrue(frame.isOptimizedFrame()); + assertFalse(frame.isInlinedFrame()); + } else { + assertFalse(frame.isOptimizedFrame()); + assertFalse(frame.isInlinedFrame()); + } + } + } + } + } +} + +function f() { + g(); +} + +function g() { + count++; + h(); + var b = 1; // Break point is set here. +} + +function h() { + debugger; +} + +f();f();f(); +%OptimizeFunctionOnNextCall(f); +f(); + +// Add the debug event listener. +Debug.setListener(listener); + +f(); + +assertEquals(5, count); +assertEquals(2, break_count); + +// Get rid of the debug event listener. +Debug.setListener(null); diff --git a/test/mjsunit/debug-evaluate-locals-optimized-double.js b/test/mjsunit/debug-evaluate-locals-optimized-double.js index 8447df53..cf25c0c0 100644 --- a/test/mjsunit/debug-evaluate-locals-optimized-double.js +++ b/test/mjsunit/debug-evaluate-locals-optimized-double.js @@ -1,4 +1,4 @@ -// Copyright 2008 the V8 project authors. All rights reserved. +// 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: @@ -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 +// Flags: --expose-debug-as debug --expose-gc --allow-natives-syntax --inline-construct // Get the Debug object exposed from the debug context global object. Debug = debug.Debug @@ -34,6 +34,27 @@ var exception = false; var testingConstructCall = false; +var input = [ + {a: 1, b: 2}, + {a: 3, b: 4}, + {a: 5, b: 6}, + {a: 7, b: 8}, + {a: 9, b: 10} +]; + +var expected = [ + { locals: {a0: 1.01, b0: 2.02}, args: { names: ["i", "x0", "y0"], values: [0, 3.03, 4.04] } }, + { locals: {a1: 3.03, b1: 4.04}, args: { names: ["i", "x1", "y1"], values: [1, 5.05, 6.06] } }, + { locals: {a2: 5.05, b2: 6.06}, args: { names: ["i"], values: [2] } }, + { locals: {a3: 7.07, b3: 8.08}, args: { names: ["i", "x3", "y3", "z3"], + values: [3, 9.09, 10.10, undefined] } + }, + { locals: {a4: 9.09, b4: 10.10}, args: { names: ["i", "x4", "y4"], values: [4, 11.11, 12.12] } } +]; + +function arraySum(arr) { + return arr.reduce(function (a, b) { return a + b; }, 0); +} function listener(event, exec_state, event_data, data) { try { @@ -44,42 +65,63 @@ function listener(event, exec_state, event_data, data) { for (var i = 0; i < exec_state.frameCount(); i++) { var frame = exec_state.frame(i); if (i < exec_state.frameCount() - 1) { - var expected_a = i * 2 + 1 + (i * 2 + 1) / 100; - var expected_b = i * 2 + 2 + (i * 2 + 2) / 100; - var expected_x = (i + 1) * 2 + 1 + ((i + 1) * 2 + 1) / 100; - var expected_y = (i + 1) * 2 + 2 + ((i + 1) * 2 + 2) / 100; - - // All frames except the bottom one has normal variables a and b. - var a = ('a' === frame.localName(0)) ? 0 : 1; - var b = 1 - a; - assertEquals('a', frame.localName(a)); - assertEquals('b', frame.localName(b)); - assertEquals(expected_a, frame.localValue(a).value()); - assertEquals(expected_b, frame.localValue(b).value()); - - // All frames except the bottom one has arguments variables x and y. - assertEquals('x', frame.argumentName(0)); - assertEquals('y', frame.argumentName(1)); - assertEquals(expected_x, frame.argumentValue(0).value()); - assertEquals(expected_y, frame.argumentValue(1).value()); + var expected_args = expected[i].args; + var expected_locals = expected[i].locals; + + // All frames except the bottom one have expected locals. + var locals = {}; + for (var j = 0; j < frame.localCount(); j++) { + locals[frame.localName(j)] = frame.localValue(j).value(); + } + assertPropertiesEqual(expected_locals, locals); + + // All frames except the bottom one have expected arguments. + for (var j = 0; j < expected_args.names.length; j++) { + assertEquals(expected_args.names[j], frame.argumentName(j)); + assertEquals(expected_args.values[j], frame.argumentValue(j).value()); + } // All frames except the bottom one have two scopes. assertEquals(2, frame.scopeCount()); assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType()); assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType()); - assertEquals(expected_a, frame.scope(0).scopeObject().value()['a']); - assertEquals(expected_b, frame.scope(0).scopeObject().value()['b']); - assertEquals(expected_x, frame.scope(0).scopeObject().value()['x']); - assertEquals(expected_y, frame.scope(0).scopeObject().value()['y']); + + Object.keys(expected_locals).forEach(function (name) { + assertEquals(expected_locals[name], frame.scope(0).scopeObject().value()[name]); + }); + + for (var j = 0; j < expected_args.names.length; j++) { + var arg_name = expected_args.names[j]; + var arg_value = expected_args.values[j]; + assertEquals(arg_value, frame.scope(0).scopeObject().value()[arg_name]); + } // Evaluate in the inlined frame. - assertEquals(expected_a, frame.evaluate('a').value()); - assertEquals(expected_x, frame.evaluate('x').value()); - assertEquals(expected_x, frame.evaluate('arguments[0]').value()); - assertEquals(expected_a + expected_b + expected_x + expected_y, - frame.evaluate('a + b + x + y').value()); - assertEquals(expected_x + expected_y, - frame.evaluate('arguments[0] + arguments[1]').value()); + Object.keys(expected_locals).forEach(function (name) { + assertEquals(expected_locals[name], frame.evaluate(name).value()); + }); + + for (var j = 0; j < expected_args.names.length; j++) { + var arg_name = expected_args.names[j]; + var arg_value = expected_args.values[j]; + assertEquals(arg_value, frame.evaluate(arg_name).value()); + assertEquals(arg_value, frame.evaluate('arguments['+j+']').value()); + } + + var expected_args_sum = arraySum(expected_args.values); + var expected_locals_sum = + arraySum(Object.keys(expected_locals). + map(function (k) { return expected_locals[k]; })); + + assertEquals(expected_locals_sum + expected_args_sum, + frame.evaluate(Object.keys(expected_locals).join('+') + ' + ' + + expected_args.names.join('+')).value()); + + var arguments_sum = expected_args.names.map(function(_, idx) { + return "arguments[" + idx + "]"; + }).join('+'); + assertEquals(expected_args_sum, + frame.evaluate(arguments_sum).value()); } else { // The bottom frame only have the global scope. assertEquals(1, frame.scopeCount()); @@ -98,7 +140,13 @@ function listener(event, exec_state, event_data, data) { } // Check for construct call. - assertEquals(testingConstructCall && i == 4, frame.isConstructCall()); + if (i == 4) { + assertEquals(testingConstructCall, frame.isConstructCall()); + } else if (i == 2) { + assertTrue(frame.isConstructCall()); + } else { + assertFalse(frame.isConstructCall()); + } // When function f is optimized (1 means YES, see runtime.cc) we // expect an optimized frame for f with g1, g2 and g3 inlined. @@ -121,65 +169,70 @@ function listener(event, exec_state, event_data, data) { listenerComplete = true; } } catch (e) { - exception = e + exception = e.toString() + e.stack; }; }; -f();f();f(); +for (var i = 0; i < 4; i++) f(input.length - 1, 11.11, 12.12); %OptimizeFunctionOnNextCall(f); -f(); +f(input.length - 1, 11.11, 12.12); // Add the debug event listener. Debug.setListener(listener); -function h(x, y) { - var a = 1; - var b = 2; - a = a + a / 100; - b = b + b / 100; +function h(i, x0, y0) { + var a0 = input[i].a; + var b0 = input[i].b; + a0 = a0 + a0 / 100; + b0 = b0 + b0 / 100; debugger; // Breakpoint. }; -function g3(x, y) { - var a = 3; - var b = 4; - a = a + a / 100; - b = b + b / 100; - h(a, b); - return a+b; +function g3(i, x1, y1) { + var a1 = input[i].a; + var b1 = input[i].b; + a1 = a1 + a1 / 100; + b1 = b1 + b1 / 100; + h(i - 1, a1, b1); + return a1+b1; }; -function g2(x, y) { - var a = 5; - var b = 6; - a = a + a / 100; - b = b + b / 100; - g3(a, b); +function g2(i) { + var a2 = input[i].a; + var b2 = input[i].b; + a2 = a2 + a2 / 100; + b2 = b2 + b2 / 100; + g3(i - 1, a2, b2); }; -function g1(x, y) { - var a = 7; - var b = 8; - a = a + a / 100; - b = b + b / 100; - g2(a, b); +function g1(i, x3, y3, z3) { + var a3 = input[i].a; + var b3 = input[i].b; + a3 = a3 + a3 / 100; + b3 = b3 + b3 / 100; + new g2(i - 1, a3, b3); }; -function f(x, y) { - var a = 9; - var b = 10; - a = a + a / 100; - b = b + b / 100; - g1(a, b); +function f(i, x4, y4) { + var a4 = input[i].a; + var b4 = input[i].b; + a4 = a4 + a4 / 100; + b4 = b4 + b4 / 100; + g1(i - 1, a4, b4); }; // Test calling f normally and as a constructor. -f(11.11, 12.12); +f(input.length - 1, 11.11, 12.12); +f(input.length - 1, 11.11, 12.12, ""); testingConstructCall = true; -new f(11.11, 12.12); +new f(input.length - 1, 11.11, 12.12); +new f(input.length - 1, 11.11, 12.12, ""); -// Make sure that the debug event listener vas invoked. +// Make sure that the debug event listener was invoked. assertFalse(exception, "exception in listener " + exception) assertTrue(listenerComplete); +//Throw away type information for next run. +gc(); + Debug.setListener(null); diff --git a/test/mjsunit/debug-evaluate-locals-optimized.js b/test/mjsunit/debug-evaluate-locals-optimized.js index c3cd5eb2..c88a683a 100644 --- a/test/mjsunit/debug-evaluate-locals-optimized.js +++ b/test/mjsunit/debug-evaluate-locals-optimized.js @@ -1,4 +1,4 @@ -// Copyright 2008 the V8 project authors. All rights reserved. +// 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: @@ -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 +// Flags: --expose-debug-as debug --expose-gc --allow-natives-syntax --inline-construct // Get the Debug object exposed from the debug context global object. Debug = debug.Debug @@ -34,6 +34,17 @@ var exception = false; var testingConstructCall = false; +var expected = [ + { locals: {a0: 1, b0: 2}, args: { names: ["i", "x0", "y0"], values: [0, 3, 4] } }, + { locals: {a1: 3, b1: 4}, args: { names: ["i", "x1", "y1"], values: [1, 5, 6] } }, + { locals: {a2: 5, b2: 6}, args: { names: ["i"], values: [2] } }, + { locals: {a3: 7, b3: 8}, args: { names: ["i", "x3", "y3", "z3"], values: [3, 9, 10, undefined] } }, + { locals: {a4: 9, b4: 10}, args: { names: ["i", "x4", "y4"], values: [4, 11, 12] } } +]; + +function arraySum(arr) { + return arr.reduce(function (a, b) { return a + b; }, 0); +} function listener(event, exec_state, event_data, data) { try { @@ -44,42 +55,63 @@ function listener(event, exec_state, event_data, data) { for (var i = 0; i < exec_state.frameCount(); i++) { var frame = exec_state.frame(i); if (i < exec_state.frameCount() - 1) { - var expected_a = i * 2 + 1; - var expected_b = i * 2 + 2; - var expected_x = (i + 1) * 2 + 1; - var expected_y = (i + 1) * 2 + 2; - - // All frames except the bottom one has normal variables a and b. - var a = ('a' === frame.localName(0)) ? 0 : 1; - var b = 1 - a; - assertEquals('a', frame.localName(a)); - assertEquals('b', frame.localName(b)); - assertEquals(expected_a, frame.localValue(a).value()); - assertEquals(expected_b, frame.localValue(b).value()); - - // All frames except the bottom one has arguments variables x and y. - assertEquals('x', frame.argumentName(0)); - assertEquals('y', frame.argumentName(1)); - assertEquals(expected_x, frame.argumentValue(0).value()); - assertEquals(expected_y, frame.argumentValue(1).value()); + var expected_args = expected[i].args; + var expected_locals = expected[i].locals; + + // All frames except the bottom one have expected locals. + var locals = {}; + for (var j = 0; j < frame.localCount(); j++) { + locals[frame.localName(j)] = frame.localValue(j).value(); + } + assertPropertiesEqual(expected_locals, locals); + + // All frames except the bottom one have expected arguments. + for (var j = 0; j < expected_args.names.length; j++) { + assertEquals(expected_args.names[j], frame.argumentName(j)); + assertEquals(expected_args.values[j], frame.argumentValue(j).value()); + } // All frames except the bottom one have two scopes. assertEquals(2, frame.scopeCount()); assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType()); assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType()); - assertEquals(expected_a, frame.scope(0).scopeObject().value()['a']); - assertEquals(expected_b, frame.scope(0).scopeObject().value()['b']); - assertEquals(expected_x, frame.scope(0).scopeObject().value()['x']); - assertEquals(expected_y, frame.scope(0).scopeObject().value()['y']); + + Object.keys(expected_locals).forEach(function (name) { + assertEquals(expected_locals[name], frame.scope(0).scopeObject().value()[name]); + }); + + for (var j = 0; j < expected_args.names.length; j++) { + var arg_name = expected_args.names[j]; + var arg_value = expected_args.values[j]; + assertEquals(arg_value, frame.scope(0).scopeObject().value()[arg_name]); + } // Evaluate in the inlined frame. - assertEquals(expected_a, frame.evaluate('a').value()); - assertEquals(expected_x, frame.evaluate('x').value()); - assertEquals(expected_x, frame.evaluate('arguments[0]').value()); - assertEquals(expected_a + expected_b + expected_x + expected_y, - frame.evaluate('a + b + x + y').value()); - assertEquals(expected_x + expected_y, - frame.evaluate('arguments[0] + arguments[1]').value()); + Object.keys(expected_locals).forEach(function (name) { + assertEquals(expected_locals[name], frame.evaluate(name).value()); + }); + + for (var j = 0; j < expected_args.names.length; j++) { + var arg_name = expected_args.names[j]; + var arg_value = expected_args.values[j]; + assertEquals(arg_value, frame.evaluate(arg_name).value()); + assertEquals(arg_value, frame.evaluate('arguments['+j+']').value()); + } + + var expected_args_sum = arraySum(expected_args.values); + var expected_locals_sum = + arraySum(Object.keys(expected_locals). + map(function (k) { return expected_locals[k]; })); + + assertEquals(expected_locals_sum + expected_args_sum, + frame.evaluate(Object.keys(expected_locals).join('+') + ' + ' + + expected_args.names.join('+')).value()); + + var arguments_sum = expected_args.names.map(function(_, idx) { + return "arguments[" + idx + "]"; + }).join('+'); + assertEquals(expected_args_sum, + frame.evaluate(arguments_sum).value()); } else { // The bottom frame only have the global scope. assertEquals(1, frame.scopeCount()); @@ -98,7 +130,13 @@ function listener(event, exec_state, event_data, data) { } // Check for construct call. - assertEquals(testingConstructCall && i == 4, frame.isConstructCall()); + if (i == 4) { + assertEquals(testingConstructCall, frame.isConstructCall()); + } else if (i == 2) { + assertTrue(frame.isConstructCall()); + } else { + assertFalse(frame.isConstructCall()); + } // When function f is optimized (1 means YES, see runtime.cc) we // expect an optimized frame for f with g1, g2 and g3 inlined. @@ -121,54 +159,59 @@ function listener(event, exec_state, event_data, data) { listenerComplete = true; } } catch (e) { - exception = e.stack; + exception = e.toString() + e.stack; }; }; -f();f();f(); +for (var i = 0; i < 4; i++) f(expected.length - 1, 11, 12); %OptimizeFunctionOnNextCall(f); -f(); +f(expected.length - 1, 11, 12); // Add the debug event listener. Debug.setListener(listener); -function h(x, y) { - var a = 1; - var b = 2; +function h(i, x0, y0) { + var a0 = expected[i].locals.a0; + var b0 = expected[i].locals.b0; debugger; // Breakpoint. -}; - -function g3(x, y) { - var a = 3; - var b = 4; - h(a, b); -}; - -function g2(x, y) { - var a = 5; - var b = 6; - g3(a, b); -}; - -function g1(x, y) { - var a = 7; - var b = 8; - g2(a, b); -}; - -function f(x, y) { - var a = 9; - var b = 10; - g1(a, b); -}; +} + +function g3(i, x1, y1) { + var a1 = expected[i].locals.a1; + var b1 = expected[i].locals.b1; + h(i - 1, a1, b1); +} + +function g2(i) { + var a2 = expected[i].locals.a2; + var b2 = expected[i].locals.b2; + g3(i - 1, a2, b2); +} + +function g1(i, x3, y3, z3) { + var a3 = expected[i].locals.a3; + var b3 = expected[i].locals.b3; + new g2(i - 1, a3, b3); +} + +function f(i, x4, y4) { + var a4 = expected[i].locals.a4; + var b4 = expected[i].locals.b4; + g1(i - 1, a4, b4); +} // Test calling f normally and as a constructor. -f(11, 12); +f(expected.length - 1, 11, 12); +f(expected.length - 1, 11, 12, 0); testingConstructCall = true; -new f(11, 12); +new f(expected.length - 1, 11, 12); +new f(expected.length - 1, 11, 12, 0); -// Make sure that the debug event listener vas invoked. +// Make sure that the debug event listener was invoked. assertFalse(exception, "exception in listener " + exception) assertTrue(listenerComplete); +// Throw away type information for next run. +gc(); + Debug.setListener(null); diff --git a/test/mjsunit/debug-scopes.js b/test/mjsunit/debug-scopes.js index 1c23b0bf..942bd2bb 100644 --- a/test/mjsunit/debug-scopes.js +++ b/test/mjsunit/debug-scopes.js @@ -1,4 +1,4 @@ -// Copyright 2008 the V8 project authors. All rights reserved. +// Copyright 2011 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,13 +25,12 @@ // (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 +// 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. - // Get the Debug object exposed from the debug context global object. -Debug = debug.Debug; +var Debug = debug.Debug; var test_name; var listener_delegate; @@ -439,6 +438,26 @@ with(with_object) { EndTest(); +// With block in function that is marked for optimization while being executed. +BeginTest("With 7"); + +function with_7() { + with({}) { + %OptimizeFunctionOnNextCall(with_7); + debugger; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); +}; +with_7(); +EndTest(); + + // Simple closure formed by returning an inner function referering the outer // functions arguments. BeginTest("Closure 1"); @@ -950,6 +969,28 @@ try { EndTest(); +// Catch block in function that is marked for optimization while being executed. +BeginTest("Catch block 7"); +function catch_block_7() { + %OptimizeFunctionOnNextCall(catch_block_7); + try { + throw 'Exception'; + } catch (e) { + debugger; + } +}; + + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e:'Exception'}, 0, exec_state); +}; +catch_block_7(); +EndTest(); + + assertEquals(begin_test_count, break_count, 'one or more tests did not enter the debugger'); assertEquals(begin_test_count, end_test_count, diff --git a/test/mjsunit/debug-set-script-source.js b/test/mjsunit/debug-set-script-source.js new file mode 100644 index 00000000..34ae8488 --- /dev/null +++ b/test/mjsunit/debug-set-script-source.js @@ -0,0 +1,64 @@ +// 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: --expose-debug-as debug +// Get the Debug object exposed from the debug context global object. +Debug = debug.Debug + +var script_number = 0; +var script_names = []; +var exception = null; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.BeforeCompile) { + event_data.script().setSource(event_data.script().source() + + " //@ sourceURL=proper_location_" + (++script_number)); + } else if (event == Debug.DebugEvent.AfterCompile) { + try { + event_data.script().setSource("a=1 //@ sourceURL=wrong_location"); + } catch(e) { + exception = e; + } + script_names.push(event_data.script().name()); + } +}; + + +// Add the debug event listener. +Debug.setListener(listener); + +// Compile different sources. +eval('a=1'); +eval('(function(){})'); + +assertEquals(2, script_names.length); +assertEquals("proper_location_1", script_names[0]); +assertEquals("proper_location_2", script_names[1]); + +assertEquals("illegal access", exception); + +Debug.setListener(null); diff --git a/test/mjsunit/debug-step-3.js b/test/mjsunit/debug-step-3.js new file mode 100644 index 00000000..9cac0f56 --- /dev/null +++ b/test/mjsunit/debug-step-3.js @@ -0,0 +1,94 @@ +// Copyright 2011 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: --expose-debug-as debug + +// This test tests that full code compiled without debug break slots +// is recompiled with debug break slots when debugging is started. + +// Get the Debug object exposed from the debug context global object. +Debug = debug.Debug + +var bp; +var done = false; +var step_count = 0; +var set_bp = false + +// Debug event listener which steps until the global variable done is true. +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + if (!done) exec_state.prepareStep(Debug.StepAction.StepNext); + step_count++; + } +}; + +// Set the global variables state to prpare the stepping test. +function prepare_step_test() { + done = false; + step_count = 0; +} + +// Test function to step through. +function f() { + var a = 0; + if (set_bp) { bp = Debug.setBreakPoint(f, 3); } + var i = 1; + var j = 2; + done = true; +}; + +prepare_step_test(); +f(); + +// Add the debug event listener. +Debug.setListener(listener); + +// Make f set a breakpoint with an activation on the stack. +prepare_step_test(); +set_bp = true; +f(); +// TODO(1782): Fix issue to bring back this assert. +//assertEquals(4, step_count); +Debug.clearBreakPoint(bp); + +// Set a breakpoint on the first var statement (line 1). +set_bp = false; +bp = Debug.setBreakPoint(f, 3); + +// Step through the function ensuring that the var statements are hit as well. +prepare_step_test(); +f(); +assertEquals(4, step_count); + +// Clear the breakpoint and check that no stepping happens. +Debug.clearBreakPoint(bp); +prepare_step_test(); +f(); +assertEquals(0, step_count); + +// Get rid of the debug event listener. +Debug.setListener(null); diff --git a/test/mjsunit/debug-stepin-accessor.js b/test/mjsunit/debug-stepin-accessor.js index 2c9c8c32..70acd5ef 100644 --- a/test/mjsunit/debug-stepin-accessor.js +++ b/test/mjsunit/debug-stepin-accessor.js @@ -1,4 +1,4 @@ -// Copyright 2008 the V8 project authors. All rights reserved. +// 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: @@ -112,8 +112,8 @@ function testGetter1_2() { function testGetter1_3() { expected_function_name = 'getter1'; expected_source_line_text = ' return this.name; // getter 1'; - debugger; for (var i = 1; i < 2; i++) { + debugger; var x = c['getter' + i]; } } diff --git a/test/mjsunit/debug-stepin-function-call.js b/test/mjsunit/debug-stepin-function-call.js index 385fcb2f..3b5240c9 100644 --- a/test/mjsunit/debug-stepin-function-call.js +++ b/test/mjsunit/debug-stepin-function-call.js @@ -135,8 +135,15 @@ function apply4() { var yetAnotherLocal = 10; } +// Test step into bound function. +function bind1() { + var bound = g.bind(null, 3); + debugger; + bound(); +} + var testFunctions = - [call1, call2, call3, call4, apply1, apply2, apply3, apply4]; + [call1, call2, call3, call4, apply1, apply2, apply3, apply4, bind1]; for (var i = 0; i < testFunctions.length; i++) { state = 0; @@ -145,5 +152,13 @@ for (var i = 0; i < testFunctions.length; i++) { assertEquals(3, state); } +// Test global bound function. +state = 0; +var globalBound = g.bind(null, 3); +debugger; +globalBound(); +assertNull(exception); +assertEquals(3, state); + // Get rid of the debug event listener. Debug.setListener(null);
\ No newline at end of file diff --git a/test/mjsunit/debug-stepout-scope.js b/test/mjsunit/debug-stepout-scope.js new file mode 100644 index 00000000..9c040da9 --- /dev/null +++ b/test/mjsunit/debug-stepout-scope.js @@ -0,0 +1,423 @@ +// Copyright 2011 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: --expose-debug-as debug --expose-natives-as=builtins + +// Check that the ScopeIterator can properly recreate the scope at +// every point when stepping through functions. + +var Debug = debug.Debug; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + // Access scope details. + var scope_count = exec_state.frame().scopeCount(); + for (var i = 0; i < scope_count; i++) { + var scope = exec_state.frame().scope(i); + // assertTrue(scope.isScope()); + scope.scopeType(); + scope.scopeObject(); + } + + // Do steps until we reach the global scope again. + if (true) { + exec_state.prepareStep(Debug.StepAction.StepInMin, 1); + } + } +} + +Debug.setListener(listener); + + +function test1() { + debugger; + with ({x:1}) { + x = 2; + } +} +test1(); + + +function test2() { + if (true) { + with ({}) { + debugger; + } + } else { + with ({}) { + return 10; + } + } +} +test2(); + + +function test3() { + if (true) { + debugger; + } else { + with ({}) { + return 10; + } + } +} +test3(); + + +function test4() { + debugger; + with ({x:1}) x = 1 +} +test4(); + + +function test5() { + debugger; + var dummy = 1; + with ({}) { + with ({}) { + dummy = 2; + } + } + dummy = 3; +} +test5(); + + +function test6() { + debugger; + try { + throw 'stuff'; + } catch (e) { + e = 1; + } +} +test6(); + + +function test7() { + debugger; + function foo() {} +} +test7(); + + +function test8() { + debugger; + (function foo() {})(); +} +test8(); + + +var q = 42; +var prefixes = [ "debugger; ", + "if (false) { try { throw 0; } catch(x) { return x; } }; debugger; " ]; +var bodies = [ "1", + "1 ", + "1;", + "1; ", + "q", + "q ", + "q;", + "q; ", + "try { throw 'stuff' } catch (e) { e = 1; }", + "try { throw 'stuff' } catch (e) { e = 1; } ", + "try { throw 'stuff' } catch (e) { e = 1; };", + "try { throw 'stuff' } catch (e) { e = 1; }; " ]; +var with_bodies = [ "with ({}) {}", + "with ({x:1}) x", + "with ({x:1}) x = 1", + "with ({x:1}) x ", + "with ({x:1}) x = 1 ", + "with ({x:1}) x;", + "with ({x:1}) x = 1;", + "with ({x:1}) x; ", + "with ({x:1}) x = 1; " ]; + + +function test9() { + debugger; + for (var i = 0; i < prefixes.length; ++i) { + var pre = prefixes[i]; + for (var j = 0; j < bodies.length; ++j) { + var body = bodies[j]; + eval(pre + body); + eval("'use strict'; " + pre + body); + } + for (var j = 0; j < with_bodies.length; ++j) { + var body = with_bodies[j]; + eval(pre + body); + } + } +} +test9(); + + +function test10() { + debugger; + with ({}) { + return 10; + } +} +test10(); + + +function test11() { + debugger; + try { + throw 'stuff'; + } catch (e) { + return 10; + } +} +test11(); + + +// Test global eval and function constructor. +for (var i = 0; i < prefixes.length; ++i) { + var pre = prefixes[i]; + for (var j = 0; j < bodies.length; ++j) { + var body = bodies[j]; + eval(pre + body); + eval("'use strict'; " + pre + body); + Function(pre + body)(); + } + for (var j = 0; j < with_bodies.length; ++j) { + var body = with_bodies[j]; + eval(pre + body); + Function(pre + body)(); + } +} + + +try { + with({}) { + debugger; + eval("{}$%:^"); + } +} catch(e) { + nop(); +} + +// Return from function constructed with Function constructor. +var anon = 12; +for (var i = 0; i < prefixes.length; ++i) { + var pre = prefixes[i]; + Function(pre + "return 42")(); + Function(pre + "return 42 ")(); + Function(pre + "return 42;")(); + Function(pre + "return 42; ")(); + Function(pre + "return anon")(); + Function(pre + "return anon ")(); + Function(pre + "return anon;")(); + Function(pre + "return anon; ")(); +} + + +function nop() {} + + +function stress() { + debugger; + + L: with ({x:12}) { + break L; + } + + + with ({x: 'outer'}) { + label: { + with ({x: 'inner'}) { + break label; + } + } + } + + + with ({x: 'outer'}) { + label: { + with ({x: 'inner'}) { + break label; + } + } + nop(); + } + + + with ({x: 'outer'}) { + label: { + with ({x: 'middle'}) { + with ({x: 'inner'}) { + break label; + } + } + } + } + + + with ({x: 'outer'}) { + label: { + with ({x: 'middle'}) { + with ({x: 'inner'}) { + break label; + } + } + } + nop(); + } + + + with ({x: 'outer'}) { + for (var i = 0; i < 3; ++i) { + with ({x: 'inner' + i}) { + continue; + } + } + } + + + with ({x: 'outer'}) { + label: for (var i = 0; i < 3; ++i) { + with ({x: 'middle' + i}) { + for (var j = 0; j < 3; ++j) { + with ({x: 'inner' + j}) { + continue label; + } + } + } + } + } + + + with ({x: 'outer'}) { + try { + with ({x: 'inner'}) { + throw 0; + } + } catch (e) { + } + } + + + with ({x: 'outer'}) { + try { + with ({x: 'inner'}) { + throw 0; + } + } catch (e) { + nop(); + } + } + + + with ({x: 'outer'}) { + try { + with ({x: 'middle'}) { + with ({x: 'inner'}) { + throw 0; + } + } + } catch (e) { + } + } + + + try { + with ({x: 'outer'}) { + try { + with ({x: 'inner'}) { + throw 0; + } + } finally { + } + } + } catch (e) { + } + + + try { + with ({x: 'outer'}) { + try { + with ({x: 'inner'}) { + throw 0; + } + } finally { + nop(); + } + } + } catch (e) { + } + + + function stress1() { + with ({x:12}) { + return x; + } + } + stress1(); + + + function stress2() { + with ({x: 'outer'}) { + with ({x: 'inner'}) { + return x; + } + } + } + stress2(); + + function stress3() { + try { + with ({x: 'inner'}) { + throw 0; + } + } catch (e) { + return e; + } + } + stress3(); + + + function stress4() { + try { + with ({x: 'inner'}) { + throw 0; + } + } catch (e) { + with ({x: 'inner'}) { + return e; + } + } + } + stress4(); + +} +stress(); + + +// With block as the last(!) statement in global code. +with ({}) { debugger; }
\ No newline at end of file diff --git a/test/mjsunit/element-kind.js b/test/mjsunit/element-kind.js deleted file mode 100644 index 48a029f2..00000000 --- a/test/mjsunit/element-kind.js +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2011 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 -// Test element kind of objects - -var element_kind = { - fast_elements : 1, - fast_double_elements : 2, - dictionary_elements : 3, - external_byte_elements : 4, - external_unsigned_byte_elements : 5, - external_short_elements : 6, - external_unsigned_short_elements : 7, - external_int_elements : 8, - external_unsigned_int_elements : 9, - external_float_elements : 10, - external_double_elements : 11, - external_pixel_elements : 12 -} - -// We expect an object to only be of one element kind. -function assertKind(expected, obj){ - assertEquals(expected == element_kind.fast_elements, - %HasFastElements(obj)); - assertEquals(expected == element_kind.fast_double_elements, - %HasFastDoubleElements(obj)); - assertEquals(expected == element_kind.dictionary_elements, - %HasDictionaryElements(obj)); - assertEquals(expected == element_kind.external_byte_elements, - %HasExternalByteElements(obj)); - assertEquals(expected == element_kind.external_unsigned_byte_elements, - %HasExternalUnsignedByteElements(obj)); - assertEquals(expected == element_kind.external_short_elements, - %HasExternalShortElements(obj)); - assertEquals(expected == element_kind.external_unsigned_short_elements, - %HasExternalUnsignedShortElements(obj)); - assertEquals(expected == element_kind.external_int_elements, - %HasExternalIntElements(obj)); - assertEquals(expected == element_kind.external_unsigned_int_elements, - %HasExternalUnsignedIntElements(obj)); - assertEquals(expected == element_kind.external_float_elements, - %HasExternalFloatElements(obj)); - assertEquals(expected == element_kind.external_double_elements, - %HasExternalDoubleElements(obj)); - assertEquals(expected == element_kind.external_pixel_elements, - %HasExternalPixelElements(obj)); - // every external kind is also an external array - assertEquals(expected >= element_kind.external_byte_elements, - %HasExternalArrayElements(obj)); -} - -var me = {}; -assertKind(element_kind.fast_elements, me); -me.dance = 0xD15C0; -me.drink = 0xC0C0A; -assertKind(element_kind.fast_elements, me); - -var you = new Array(); -for(i = 0; i < 1337; i++) { - you[i] = i; -} -assertKind(element_kind.fast_elements, you); - -assertKind(element_kind.dictionary_elements, new Array(0xC0C0A)); - -// fast_double_elements not yet available - - -assertKind(element_kind.external_byte_elements, new Int8Array(9001)); -assertKind(element_kind.external_unsigned_byte_elements, new Uint8Array(007)); -assertKind(element_kind.external_short_elements, new Int16Array(666)); -assertKind(element_kind.external_unsigned_short_elements, new Uint16Array(42)); -assertKind(element_kind.external_int_elements, new Int32Array(0xF)); -assertKind(element_kind.external_unsigned_int_elements, new Uint32Array(23)); -assertKind(element_kind.external_float_elements, new Float32Array(7)); -assertKind(element_kind.external_double_elements, new Float64Array(0)); -assertKind(element_kind.external_pixel_elements, new PixelArray(512)); diff --git a/test/mjsunit/elements-kind-depends.js b/test/mjsunit/elements-kind-depends.js new file mode 100644 index 00000000..82f188b7 --- /dev/null +++ b/test/mjsunit/elements-kind-depends.js @@ -0,0 +1,74 @@ +// Copyright 2011 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 --smi-only-arrays + +function burn() { + var a = new Array(3); + a[0] = 10; + a[1] = 15.5; + a[2] = 20; + return a; +} + +function check(a) { + assertEquals(10, a[0]); + assertEquals(15.5, a[1]); + assertEquals(20, a[2]); +} + +var b; +for (var i = 0; i < 3; ++i) { + b = burn(); + check(b); // all OK +} +%OptimizeFunctionOnNextCall(burn); +b = burn(); +check(b); // fails + + +function loop_test(x) { + for (i=0;i<3;i++) { + x[i] = (i+1) * 0.5; + } +} + +function check2(b) { + assertEquals(0.5, b[0]); + assertEquals(1.0, b[1]); + assertEquals(1.5, b[2]); +} + +for (var i = 0; i < 3; ++i) { + b = [0,1,2]; + loop_test(b); + check2(b); +} +%OptimizeFunctionOnNextCall(loop_test); +b = [0,1,2]; +loop_test(b); +check2(b); diff --git a/test/mjsunit/elements-kind.js b/test/mjsunit/elements-kind.js new file mode 100644 index 00000000..4aa79de6 --- /dev/null +++ b/test/mjsunit/elements-kind.js @@ -0,0 +1,346 @@ +// 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 --smi-only-arrays --expose-gc + +// Test element kind of objects. +// Since --smi-only-arrays affects builtins, its default setting at compile +// time sticks if built with snapshot. If --smi-only-arrays is deactivated +// by default, only a no-snapshot build actually has smi-only arrays enabled +// in this test case. Depending on whether smi-only arrays are actually +// enabled, this test takes the appropriate code path to check smi-only arrays. + +support_smi_only_arrays = %HasFastSmiOnlyElements(new Array(1,2,3,4,5,6,7,8)); + +if (support_smi_only_arrays) { + print("Tests include smi-only arrays."); +} else { + print("Tests do NOT include smi-only arrays."); +} + +var elements_kind = { + fast_smi_only : 'fast smi only elements', + fast : 'fast elements', + fast_double : 'fast double elements', + dictionary : 'dictionary elements', + external_byte : 'external byte elements', + external_unsigned_byte : 'external unsigned byte elements', + external_short : 'external short elements', + external_unsigned_short : 'external unsigned short elements', + external_int : 'external int elements', + external_unsigned_int : 'external unsigned int elements', + external_float : 'external float elements', + external_double : 'external double elements', + external_pixel : 'external pixel elements' +} + +function getKind(obj) { + if (%HasFastSmiOnlyElements(obj)) return elements_kind.fast_smi_only; + if (%HasFastElements(obj)) return elements_kind.fast; + if (%HasFastDoubleElements(obj)) return elements_kind.fast_double; + if (%HasDictionaryElements(obj)) return elements_kind.dictionary; + // Every external kind is also an external array. + assertTrue(%HasExternalArrayElements(obj)); + if (%HasExternalByteElements(obj)) { + return elements_kind.external_byte; + } + if (%HasExternalUnsignedByteElements(obj)) { + return elements_kind.external_unsigned_byte; + } + if (%HasExternalShortElements(obj)) { + return elements_kind.external_short; + } + if (%HasExternalUnsignedShortElements(obj)) { + return elements_kind.external_unsigned_short; + } + if (%HasExternalIntElements(obj)) { + return elements_kind.external_int; + } + if (%HasExternalUnsignedIntElements(obj)) { + return elements_kind.external_unsigned_int; + } + if (%HasExternalFloatElements(obj)) { + return elements_kind.external_float; + } + if (%HasExternalDoubleElements(obj)) { + return elements_kind.external_double; + } + if (%HasExternalPixelElements(obj)) { + return elements_kind.external_pixel; + } +} + +function assertKind(expected, obj, name_opt) { + if (!support_smi_only_arrays && + expected == elements_kind.fast_smi_only) { + expected = elements_kind.fast; + } + assertEquals(expected, getKind(obj), name_opt); +} + +var me = {}; +assertKind(elements_kind.fast, me); +me.dance = 0xD15C0; +me.drink = 0xC0C0A; +assertKind(elements_kind.fast, me); + +if (support_smi_only_arrays) { + var too = [1,2,3]; + assertKind(elements_kind.fast_smi_only, too); + too.dance = 0xD15C0; + too.drink = 0xC0C0A; + assertKind(elements_kind.fast_smi_only, too); +} + +// Make sure the element kind transitions from smionly when a non-smi is stored. +var you = new Array(); +assertKind(elements_kind.fast_smi_only, you); +for (var i = 0; i < 1337; i++) { + var val = i; + if (i == 1336) { + assertKind(elements_kind.fast_smi_only, you); + val = new Object(); + } + you[i] = val; +} +assertKind(elements_kind.fast, you); + +assertKind(elements_kind.dictionary, new Array(0xDECAF)); + +var fast_double_array = new Array(0xDECAF); +for (var i = 0; i < 0xDECAF; i++) fast_double_array[i] = i / 2; +assertKind(elements_kind.fast_double, fast_double_array); + +assertKind(elements_kind.external_byte, new Int8Array(9001)); +assertKind(elements_kind.external_unsigned_byte, new Uint8Array(007)); +assertKind(elements_kind.external_short, new Int16Array(666)); +assertKind(elements_kind.external_unsigned_short, new Uint16Array(42)); +assertKind(elements_kind.external_int, new Int32Array(0xF)); +assertKind(elements_kind.external_unsigned_int, new Uint32Array(23)); +assertKind(elements_kind.external_float, new Float32Array(7)); +assertKind(elements_kind.external_double, new Float64Array(0)); +assertKind(elements_kind.external_pixel, new PixelArray(512)); + +// Crankshaft support for smi-only array elements. +function monomorphic(array) { + assertKind(elements_kind.fast_smi_only, array); + for (var i = 0; i < 3; i++) { + array[i] = i + 10; + } + assertKind(elements_kind.fast_smi_only, array); + for (var i = 0; i < 3; i++) { + var a = array[i]; + assertEquals(i + 10, a); + } +} +var smi_only = new Array(1, 2, 3); +assertKind(elements_kind.fast_smi_only, smi_only); +for (var i = 0; i < 3; i++) monomorphic(smi_only); +%OptimizeFunctionOnNextCall(monomorphic); +monomorphic(smi_only); + +if (support_smi_only_arrays) { + function construct_smis() { + var a = [0, 0, 0]; + a[0] = 0; // Send the COW array map to the steak house. + assertKind(elements_kind.fast_smi_only, a); + return a; + } + function construct_doubles() { + var a = construct_smis(); + a[0] = 1.5; + assertKind(elements_kind.fast_double, a); + return a; + } + function construct_objects() { + var a = construct_smis(); + a[0] = "one"; + assertKind(elements_kind.fast, a); + return a; + } + + // Test crankshafted transition SMI->DOUBLE. + function convert_to_double(array) { + array[1] = 2.5; + assertKind(elements_kind.fast_double, array); + assertEquals(2.5, array[1]); + } + var smis = construct_smis(); + for (var i = 0; i < 3; i++) convert_to_double(smis); + %OptimizeFunctionOnNextCall(convert_to_double); + smis = construct_smis(); + convert_to_double(smis); + // Test crankshafted transitions SMI->FAST and DOUBLE->FAST. + function convert_to_fast(array) { + array[1] = "two"; + assertKind(elements_kind.fast, array); + assertEquals("two", array[1]); + } + smis = construct_smis(); + for (var i = 0; i < 3; i++) convert_to_fast(smis); + var doubles = construct_doubles(); + for (var i = 0; i < 3; i++) convert_to_fast(doubles); + smis = construct_smis(); + doubles = construct_doubles(); + %OptimizeFunctionOnNextCall(convert_to_fast); + convert_to_fast(smis); + convert_to_fast(doubles); + // Test transition chain SMI->DOUBLE->FAST (crankshafted function will + // transition to FAST directly). + function convert_mixed(array, value, kind) { + array[1] = value; + assertKind(kind, array); + assertEquals(value, array[1]); + } + smis = construct_smis(); + for (var i = 0; i < 3; i++) { + convert_mixed(smis, 1.5, elements_kind.fast_double); + } + doubles = construct_doubles(); + for (var i = 0; i < 3; i++) { + convert_mixed(doubles, "three", elements_kind.fast); + } + smis = construct_smis(); + doubles = construct_doubles(); + %OptimizeFunctionOnNextCall(convert_mixed); + convert_mixed(smis, 1, elements_kind.fast); + convert_mixed(doubles, 1, elements_kind.fast); + assertTrue(%HaveSameMap(smis, doubles)); +} + +// Crankshaft support for smi-only elements in dynamic array literals. +function get(foo) { return foo; } // Used to generate dynamic values. + +function crankshaft_test() { + if (support_smi_only_arrays) { + var a1 = [get(1), get(2), get(3)]; + assertKind(elements_kind.fast_smi_only, a1); + } + var a2 = new Array(get(1), get(2), get(3)); + assertKind(elements_kind.fast_smi_only, a2); + var b = [get(1), get(2), get("three")]; + assertKind(elements_kind.fast, b); + var c = [get(1), get(2), get(3.5)]; + if (support_smi_only_arrays) { + assertKind(elements_kind.fast_double, c); + } +} +for (var i = 0; i < 3; i++) { + crankshaft_test(); +} +%OptimizeFunctionOnNextCall(crankshaft_test); +crankshaft_test(); + +// Elements_kind transitions for arrays. + +// A map can have three different elements_kind transitions: SMI->DOUBLE, +// DOUBLE->OBJECT, and SMI->OBJECT. No matter in which order these three are +// created, they must always end up with the same FAST map. + +// This test is meaningless without FAST_SMI_ONLY_ELEMENTS. +if (support_smi_only_arrays) { + // Preparation: create one pair of identical objects for each case. + var a = [1, 2, 3]; + var b = [1, 2, 3]; + assertTrue(%HaveSameMap(a, b)); + assertKind(elements_kind.fast_smi_only, a); + var c = [1, 2, 3]; + c["case2"] = true; + var d = [1, 2, 3]; + d["case2"] = true; + assertTrue(%HaveSameMap(c, d)); + assertFalse(%HaveSameMap(a, c)); + assertKind(elements_kind.fast_smi_only, c); + var e = [1, 2, 3]; + e["case3"] = true; + var f = [1, 2, 3]; + f["case3"] = true; + assertTrue(%HaveSameMap(e, f)); + assertFalse(%HaveSameMap(a, e)); + assertFalse(%HaveSameMap(c, e)); + assertKind(elements_kind.fast_smi_only, e); + // Case 1: SMI->DOUBLE, DOUBLE->OBJECT, SMI->OBJECT. + a[0] = 1.5; + assertKind(elements_kind.fast_double, a); + a[0] = "foo"; + assertKind(elements_kind.fast, a); + b[0] = "bar"; + assertTrue(%HaveSameMap(a, b)); + // Case 2: SMI->DOUBLE, SMI->OBJECT, DOUBLE->OBJECT. + c[0] = 1.5; + assertKind(elements_kind.fast_double, c); + assertFalse(%HaveSameMap(c, d)); + d[0] = "foo"; + assertKind(elements_kind.fast, d); + assertFalse(%HaveSameMap(c, d)); + c[0] = "bar"; + assertTrue(%HaveSameMap(c, d)); + // Case 3: SMI->OBJECT, SMI->DOUBLE, DOUBLE->OBJECT. + e[0] = "foo"; + assertKind(elements_kind.fast, e); + assertFalse(%HaveSameMap(e, f)); + f[0] = 1.5; + assertKind(elements_kind.fast_double, f); + assertFalse(%HaveSameMap(e, f)); + f[0] = "bar"; + assertKind(elements_kind.fast, f); + assertTrue(%HaveSameMap(e, f)); +} + +// Test if Array.concat() works correctly with DOUBLE elements. +if (support_smi_only_arrays) { + var a = [1, 2]; + assertKind(elements_kind.fast_smi_only, a); + var b = [4.5, 5.5]; + assertKind(elements_kind.fast_double, b); + var c = a.concat(b); + assertEquals([1, 2, 4.5, 5.5], c); + // TODO(1810): Change implementation so that we get DOUBLE elements here? + assertKind(elements_kind.fast, c); +} + +// Test that Array.push() correctly handles SMI elements. +if (support_smi_only_arrays) { + var a = [1, 2]; + assertKind(elements_kind.fast_smi_only, a); + a.push(3, 4, 5); + assertKind(elements_kind.fast_smi_only, a); + assertEquals([1, 2, 3, 4, 5], a); +} + +// Test that Array.splice() and Array.slice() return correct ElementsKinds. +if (support_smi_only_arrays) { + var a = ["foo", "bar"]; + assertKind(elements_kind.fast, a); + var b = a.splice(0, 1); + assertKind(elements_kind.fast, b); + var c = a.slice(0, 1); + assertKind(elements_kind.fast, c); +} + +// Throw away type information in the ICs for next stress run. +gc(); diff --git a/test/mjsunit/elements-transition-hoisting.js b/test/mjsunit/elements-transition-hoisting.js new file mode 100644 index 00000000..5e78f10a --- /dev/null +++ b/test/mjsunit/elements-transition-hoisting.js @@ -0,0 +1,211 @@ +// Copyright 2011 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 --smi-only-arrays --expose-gc + +// Ensure that ElementsKind transitions in various situations are hoisted (or +// not hoisted) correctly, don't change the semantics programs and don't trigger +// deopt through hoisting in important situations. + +support_smi_only_arrays = %HasFastSmiOnlyElements(new Array(1,2,3,4,5,6)); + +if (support_smi_only_arrays) { + print("Tests include smi-only arrays."); +} else { + print("Tests do NOT include smi-only arrays."); +} + +// Force existing ICs from previous stress runs to be flushed, otherwise the +// assumptions in this test about when deoptimizations get triggered are not +// valid. +gc(); + +if (support_smi_only_arrays) { + // Make sure that a simple elements array transitions inside a loop before + // stores to an array gets hoisted in a way that doesn't generate a deopt in + // simple cases.} + function testDoubleConversion4(a) { + var object = new Object(); + a[0] = 0; + var count = 3; + do { + a[0] = object; + } while (--count > 0); + } + + testDoubleConversion4(new Array(5)); + %OptimizeFunctionOnNextCall(testDoubleConversion4); + testDoubleConversion4(new Array(5)); + testDoubleConversion4(new Array(5)); + assertTrue(2 != %GetOptimizationStatus(testDoubleConversion4)); + + // Make sure that non-element related map checks that are not preceded by + // transitions in a loop still get hoisted in a way that doesn't generate a + // deopt in simple cases. + function testExactMapHoisting(a) { + var object = new Object(); + a.foo = 0; + a[0] = 0; + a[1] = 1; + var count = 3; + do { + a.foo = object; // This map check should be hoistable + a[1] = object; + result = a.foo == object && a[1] == object; + } while (--count > 0); + } + + testExactMapHoisting(new Array(5)); + %OptimizeFunctionOnNextCall(testExactMapHoisting); + testExactMapHoisting(new Array(5)); + testExactMapHoisting(new Array(5)); + assertTrue(2 != %GetOptimizationStatus(testExactMapHoisting)); + + // Make sure that non-element related map checks do NOT get hoisted if they + // depend on an elements transition before them and it's not possible to hoist + // that transition. + function testExactMapHoisting2(a) { + var object = new Object(); + a.foo = 0; + a[0] = 0; + a[1] = 1; + var count = 3; + do { + if (a.bar === undefined) { + a[1] = 2.5; + } + a.foo = object; // This map check should NOT be hoistable because it + // includes a check for the FAST_ELEMENTS map as well as + // the FAST_DOUBLE_ELEMENTS map, which depends on the + // double transition above in the if, which cannot be + // hoisted. + } while (--count > 0); + } + + testExactMapHoisting2(new Array(5)); + %OptimizeFunctionOnNextCall(testExactMapHoisting2); + testExactMapHoisting2(new Array(5)); + testExactMapHoisting2(new Array(5)); + assertTrue(2 != %GetOptimizationStatus(testExactMapHoisting2)); + + // Make sure that non-element related map checks do get hoisted if they use + // the transitioned map for the check and all transitions that they depend + // upon can hoisted, too. + function testExactMapHoisting3(a) { + var object = new Object(); + a.foo = 0; + a[0] = 0; + a[1] = 1; + var count = 3; + do { + a[1] = 2.5; + a.foo = object; // This map check should be hoistable because all elements + // transitions in the loop can also be hoisted. + } while (--count > 0); + } + + var add_transition = new Array(5); + add_transition.foo = 0; + add_transition[0] = new Object(); // For FAST_ELEMENT transition to be created + testExactMapHoisting3(new Array(5)); + %OptimizeFunctionOnNextCall(testExactMapHoisting3); + testExactMapHoisting3(new Array(5)); + testExactMapHoisting3(new Array(5)); + assertTrue(2 != %GetOptimizationStatus(testExactMapHoisting3)); + + function testDominatingTransitionHoisting1(a) { + var object = new Object(); + a[0] = 0; + var count = 3; + do { + if (a.baz != true) { + a[1] = 2.5; + } + a[0] = object; + } while (--count > 3); + } + + testDominatingTransitionHoisting1(new Array(5)); + %OptimizeFunctionOnNextCall(testDominatingTransitionHoisting1); + testDominatingTransitionHoisting1(new Array(5)); + testDominatingTransitionHoisting1(new Array(5)); + assertTrue(2 != %GetOptimizationStatus(testDominatingTransitionHoisting1)); + + function testHoistingWithSideEffect(a) { + var object = new Object(); + a[0] = 0; + var count = 3; + do { + assertTrue(true); + a[0] = object; + } while (--count > 3); + } + + testHoistingWithSideEffect(new Array(5)); + %OptimizeFunctionOnNextCall(testHoistingWithSideEffect); + testHoistingWithSideEffect(new Array(5)); + testHoistingWithSideEffect(new Array(5)); + assertTrue(2 != %GetOptimizationStatus(testHoistingWithSideEffect)); + + function testStraightLineDupeElinination(a,b,c,d,e,f) { + var count = 3; + do { + assertTrue(true); + a[0] = b; + a[1] = c; + a[2] = d; + assertTrue(true); + a[3] = e; // TransitionElementsKind should be eliminated despite call. + a[4] = f; + } while (--count > 3); + } + + testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,0,0,0,.5); + testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,0,0,.5,0); + testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,0,.5,0,0); + testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,.5,0,0,0); + testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),.5,0,0,0,0); + testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,0,0,0,.5); + testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,0,0,.5,0); + testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,0,.5,0,0); + testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,.5,0,0,0); + testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),.5,0,0,0,0); + testStraightLineDupeElinination(new Array(5),.5,0,0,0,0); + testStraightLineDupeElinination(new Array(5),0,.5,0,0,0); + testStraightLineDupeElinination(new Array(5),0,0,.5,0,0); + testStraightLineDupeElinination(new Array(5),0,0,0,.5,0); + testStraightLineDupeElinination(new Array(5),0,0,0,0,.5); + testStraightLineDupeElinination(new Array(5),.5,0,0,0,0); + testStraightLineDupeElinination(new Array(5),0,.5,0,0,0); + testStraightLineDupeElinination(new Array(5),0,0,.5,0,0); + testStraightLineDupeElinination(new Array(5),0,0,0,.5,0); + testStraightLineDupeElinination(new Array(5),0,0,0,0,.5); + %OptimizeFunctionOnNextCall(testStraightLineDupeElinination); + testStraightLineDupeElinination(new Array(5)); + testStraightLineDupeElinination(new Array(5)); + assertTrue(2 != %GetOptimizationStatus(testStraightLineDupeElinination)); +} diff --git a/test/mjsunit/elements-transition.js b/test/mjsunit/elements-transition.js new file mode 100644 index 00000000..60e051b3 --- /dev/null +++ b/test/mjsunit/elements-transition.js @@ -0,0 +1,113 @@ +// 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 --smi-only-arrays + +support_smi_only_arrays = %HasFastSmiOnlyElements(new Array(1,2,3,4,5,6,7,8)); + +if (support_smi_only_arrays) { + print("Tests include smi-only arrays."); +} else { + print("Tests do NOT include smi-only arrays."); +} + +if (support_smi_only_arrays) { + function test(test_double, test_object, set, length) { + // We apply the same operations to two identical arrays. The first array + // triggers an IC miss, upon which the conversion stub is generated, but the + // actual conversion is done in runtime. The second array, arriving at + // the previously patched IC, is then converted using the conversion stub. + var array_1 = new Array(length); + var array_2 = new Array(length); + + assertTrue(%HasFastSmiOnlyElements(array_1)); + assertTrue(%HasFastSmiOnlyElements(array_2)); + for (var i = 0; i < length; i++) { + if (i == length - 5 && test_double) { + // Trigger conversion to fast double elements at length-5. + set(array_1, i, 0.5); + set(array_2, i, 0.5); + assertTrue(%HasFastDoubleElements(array_1)); + assertTrue(%HasFastDoubleElements(array_2)); + } else if (i == length - 3 && test_object) { + // Trigger conversion to fast object elements at length-3. + set(array_1, i, 'object'); + set(array_2, i, 'object'); + assertTrue(%HasFastElements(array_1)); + assertTrue(%HasFastElements(array_2)); + } else if (i != length - 7) { + // Set the element to an integer but leave a hole at length-7. + set(array_1, i, 2*i+1); + set(array_2, i, 2*i+1); + } + } + + for (var i = 0; i < length; i++) { + if (i == length - 5 && test_double) { + assertEquals(0.5, array_1[i]); + assertEquals(0.5, array_2[i]); + } else if (i == length - 3 && test_object) { + assertEquals('object', array_1[i]); + assertEquals('object', array_2[i]); + } else if (i != length - 7) { + assertEquals(2*i+1, array_1[i]); + assertEquals(2*i+1, array_2[i]); + } else { + assertEquals(undefined, array_1[i]); + assertEquals(undefined, array_2[i]); + } + } + + assertEquals(length, array_1.length); + assertEquals(length, array_2.length); + } + + test(false, false, function(a,i,v){ a[i] = v; }, 20); + test(true, false, function(a,i,v){ a[i] = v; }, 20); + test(false, true, function(a,i,v){ a[i] = v; }, 20); + test(true, true, function(a,i,v){ a[i] = v; }, 20); + + test(false, false, function(a,i,v){ a[i] = v; }, 10000); + test(true, false, function(a,i,v){ a[i] = v; }, 10000); + test(false, true, function(a,i,v){ a[i] = v; }, 10000); + test(true, true, function(a,i,v){ a[i] = v; }, 10000); + + // Check COW arrays + function get_cow() { return [1, 2, 3]; } + + function transition(x) { x[0] = 1.5; } + + var ignore = get_cow(); + transition(ignore); // Handled by runtime. + var a = get_cow(); + var b = get_cow(); + transition(a); // Handled by IC. + assertEquals(1.5, a[0]); + assertEquals(1, b[0]); +} else { + print("Test skipped because smi only arrays are not supported."); +} diff --git a/test/mjsunit/error-tostring.js b/test/mjsunit/error-tostring.js new file mode 100644 index 00000000..a2856414 --- /dev/null +++ b/test/mjsunit/error-tostring.js @@ -0,0 +1,85 @@ +// Copyright 2011 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 default string representation of an Error object. + +var e = new Error(); +assertEquals('Error', e.toString()); + + +// Test printing of cyclic errors which return the empty string for +// compatibility with Safari and Firefox. + +e = new Error(); +e.name = e; +e.message = e; +e.stack = "Does not occur in output"; +e.arguments = "Does not occur in output"; +e.type = "Does not occur in output"; +assertEquals('', e.toString()); + +e = new Error(); +e.name = [ e ]; +e.message = [ e ]; +e.stack = "Does not occur in output"; +e.arguments = "Does not occur in output"; +e.type = "Does not occur in output"; +assertEquals('', e.toString()); + + +// Test the sequence in which getters and toString operations are called +// on a given Error object. Verify the produced string representation. + +function testErrorToString(nameValue, messageValue) { + var seq = []; + var e = { + get name() { + seq.push(1); + return (nameValue === undefined) ? nameValue : { + toString: function() { seq.push(2); return nameValue; } + }; + }, + get message() { + seq.push(3); + return (messageValue === undefined) ? messageValue : { + toString: function() { seq.push(4); return messageValue; } + }; + } + }; + var string = Error.prototype.toString.call(e); + return [string,seq]; +} + +assertEquals(["Error",[1,3]], testErrorToString(undefined, undefined)); +assertEquals(["e1",[1,2,3]], testErrorToString("e1", undefined)); +assertEquals(["e1: null",[1,2,3,4]], testErrorToString("e1", null)); +assertEquals(["e1",[1,2,3,4]], testErrorToString("e1", "")); +assertEquals(["Error: e2",[1,3,4]], testErrorToString(undefined, "e2")); +assertEquals(["null: e2",[1,2,3,4]], testErrorToString(null, "e2")); +assertEquals(["e2",[1,2,3,4]], testErrorToString("", "e2")); +assertEquals(["e1: e2",[1,2,3,4]], testErrorToString("e1", "e2")); diff --git a/test/mjsunit/eval.js b/test/mjsunit/eval.js index b6284ba9..100f2165 100644 --- a/test/mjsunit/eval.js +++ b/test/mjsunit/eval.js @@ -39,7 +39,7 @@ assertEquals(1, count); try { eval('hest 7 &*^*&^'); - assertTrue(false, 'Did not throw on syntax error.'); + assertUnreachable('Did not throw on syntax error.'); } catch (e) { assertEquals('SyntaxError', e.name); } @@ -108,6 +108,7 @@ foo = 0; result = (function() { var foo = 2; + // Should be non-direct call. return x.eval('foo'); })(); assertEquals(0, result); @@ -115,12 +116,33 @@ assertEquals(0, result); foo = 0; result = (function() { + var foo = 2; + // Should be non-direct call. + return (1,eval)('foo'); + })(); +assertEquals(0, result); + +foo = 0; +result = + (function() { var eval = function(x) { return x; }; var foo = eval(2); + // Should be non-direct call. return e('foo'); })(); assertEquals(0, result); +foo = 0; +result = + (function() { + var foo = 2; + // Should be direct call. + with ({ eval : e }) { + return eval('foo'); + } + })(); +assertEquals(2, result); + result = (function() { var eval = function(x) { return 2 * x; }; @@ -135,19 +157,17 @@ result = })(); assertEquals(this, result); -result = - (function() { - var obj = { f: function(eval) { return eval("this"); } }; - return obj.f(eval); - })(); -assertEquals(this, result); +(function() { + var obj = { f: function(eval) { return eval("this"); } }; + result = obj.f(eval); + assertEquals(obj, result); +})(); -result = - (function() { - var obj = { f: function(eval) { arguments; return eval("this"); } }; - return obj.f(eval); - })(); -assertEquals(this, result); +(function() { + var obj = { f: function(eval) { arguments; return eval("this"); } }; + result = obj.f(eval); + assertEquals(obj, result); +})(); eval = function(x) { return 2 * x; }; result = @@ -156,6 +176,9 @@ result = })(); assertEquals(4, result); + + + // Regression test: calling a function named eval found in a context that is // not the global context should get the global object as receiver. result = diff --git a/test/mjsunit/external-array.js b/test/mjsunit/external-array.js index 81c6cfe8..32f78a72 100644 --- a/test/mjsunit/external-array.js +++ b/test/mjsunit/external-array.js @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// 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: @@ -43,6 +43,50 @@ f(a); assertEquals(0, a[0]); assertEquals(0, a[1]); +// No-parameter constructor should fail right now. +function abfunc1() { + return new ArrayBuffer(); +} +assertThrows(abfunc1); + +// Test derivation from an ArrayBuffer +var ab = new ArrayBuffer(12); +var derived_uint8 = new Uint8Array(ab); +assertEquals(12, derived_uint8.length); +var derived_uint32 = new Uint32Array(ab); +assertEquals(3, derived_uint32.length); +var derived_uint32_2 = new Uint32Array(ab,4); +assertEquals(2, derived_uint32_2.length); +var derived_uint32_3 = new Uint32Array(ab,4,1); +assertEquals(1, derived_uint32_3.length); + +// 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 the correct behavior of the |BYTES_PER_ELEMENT| property (which is // "constant", but not read-only). a = new Int32Array(2); @@ -273,3 +317,37 @@ for (var t = 0; t < types.length; t++) { %DeoptimizeFunction(array_load_set_smi_check2); gc(); // Makes V8 forget about type information for array_load_set_smi_check. } + +// 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])); diff --git a/test/mjsunit/function-bind.js b/test/mjsunit/function-bind.js index e9d02213..4a8f2d2a 100644 --- a/test/mjsunit/function-bind.js +++ b/test/mjsunit/function-bind.js @@ -29,29 +29,31 @@ // Simple tests. function foo(x, y, z) { - return x + y + z; + return [this, arguments.length, x]; } +assertEquals(3, foo.length); + var f = foo.bind(foo); -assertEquals(3, f(1, 1, 1)); +assertEquals([foo, 3, 1], f(1, 2, 3)); assertEquals(3, f.length); -f = foo.bind(foo, 2); -assertEquals(4, f(1, 1)); +f = foo.bind(foo, 1); +assertEquals([foo, 3, 1], f(2, 3)); assertEquals(2, f.length); -f = foo.bind(foo, 2, 2); -assertEquals(5, f(1)); +f = foo.bind(foo, 1, 2); +assertEquals([foo, 3, 1], f(3)); assertEquals(1, f.length); -f = foo.bind(foo, 2, 2, 2); -assertEquals(6, f()); +f = foo.bind(foo, 1, 2, 3); +assertEquals([foo, 3, 1], f()); assertEquals(0, f.length); // Test that length works correctly even if more than the actual number // of arguments are given when binding. f = foo.bind(foo, 1, 2, 3, 4, 5, 6, 7, 8, 9); -assertEquals(6, f()); +assertEquals([foo, 9, 1], f()); assertEquals(0, f.length); // Use a different bound object. @@ -78,64 +80,97 @@ assertEquals(0, f.length); // When only giving the thisArg, any number of binds should have // the same effect. f = foo.bind(foo); -assertEquals(3, f(1, 1, 1)); -f = foo.bind(foo).bind(foo).bind(foo).bind(foo); -assertEquals(3, f(1, 1, 1)); +assertEquals([foo, 3, 1], f(1, 2, 3)); + +var not_foo = {}; +f = foo.bind(foo).bind(not_foo).bind(not_foo).bind(not_foo); +assertEquals([foo, 3, 1], f(1, 2, 3)); assertEquals(3, f.length); // Giving bound parameters should work at any place in the chain. -f = foo.bind(foo, 1).bind(foo).bind(foo).bind(foo); -assertEquals(3, f(1, 1)); +f = foo.bind(foo, 1).bind(not_foo).bind(not_foo).bind(not_foo); +assertEquals([foo, 3, 1], f(2, 3)); assertEquals(2, f.length); -f = foo.bind(foo).bind(foo, 1).bind(foo).bind(foo); -assertEquals(3, f(1, 1)); +f = foo.bind(foo).bind(not_foo, 1).bind(not_foo).bind(not_foo); +assertEquals([foo, 3, 1], f(2, 3)); assertEquals(2, f.length); -f = foo.bind(foo).bind(foo).bind(foo,1 ).bind(foo); -assertEquals(3, f(1, 1)); +f = foo.bind(foo).bind(not_foo).bind(not_foo,1 ).bind(not_foo); +assertEquals([foo, 3, 1], f(2, 3)); assertEquals(2, f.length); -f = foo.bind(foo).bind(foo).bind(foo).bind(foo, 1); -assertEquals(3, f(1, 1)); +f = foo.bind(foo).bind(not_foo).bind(not_foo).bind(not_foo, 1); +assertEquals([foo, 3, 1], f(2, 3)); assertEquals(2, f.length); -// Several parameters can be given, and given in different bind invokations. -f = foo.bind(foo, 1, 1).bind(foo).bind(foo).bind(foo); -assertEquals(3, f(1)); +// Several parameters can be given, and given in different bind invocations. +f = foo.bind(foo, 1, 2).bind(not_foo).bind(not_foo).bind(not_foo); +assertEquals([foo, 3, 1], f(3)); +assertEquals(1, f.length); + +f = foo.bind(foo).bind(not_foo, 1, 2).bind(not_foo).bind(not_foo); +assertEquals([foo, 3, 1], f(1)); assertEquals(1, f.length); -f = foo.bind(foo).bind(foo, 1, 1).bind(foo).bind(foo); -assertEquals(3, f(1)); +f = foo.bind(foo).bind(not_foo, 1, 2).bind(not_foo).bind(not_foo); +assertEquals([foo, 3, 1], f(3)); assertEquals(1, f.length); -f = foo.bind(foo).bind(foo, 1, 1).bind(foo).bind(foo); -assertEquals(3, f(1)); +f = foo.bind(foo).bind(not_foo).bind(not_foo, 1, 2).bind(not_foo); +assertEquals([foo, 3, 1], f(1)); assertEquals(1, f.length); -f = foo.bind(foo).bind(foo).bind(foo, 1, 1).bind(foo); -assertEquals(3, f(1)); +f = foo.bind(foo).bind(not_foo).bind(not_foo).bind(not_foo, 1, 2); +assertEquals([foo, 3, 1], f(3)); assertEquals(1, f.length); -f = foo.bind(foo).bind(foo).bind(foo).bind(foo, 1, 1); -assertEquals(3, f(1)); +f = foo.bind(foo, 1).bind(not_foo, 2).bind(not_foo).bind(not_foo); +assertEquals([foo, 3, 1], f(3)); assertEquals(1, f.length); -f = foo.bind(foo, 1).bind(foo, 1).bind(foo).bind(foo); -assertEquals(3, f(1)); +f = foo.bind(foo, 1).bind(not_foo).bind(not_foo, 2).bind(not_foo); +assertEquals([foo, 3, 1], f(3)); assertEquals(1, f.length); -f = foo.bind(foo, 1).bind(foo).bind(foo, 1).bind(foo); -assertEquals(3, f(1)); +f = foo.bind(foo, 1).bind(not_foo).bind(not_foo).bind(not_foo, 2); +assertEquals([foo, 3, 1], f(3)); assertEquals(1, f.length); -f = foo.bind(foo, 1).bind(foo).bind(foo).bind(foo, 1); -assertEquals(3, f(1)); +f = foo.bind(foo).bind(not_foo, 1).bind(not_foo).bind(not_foo, 2); +assertEquals([foo, 3, 1], f(3)); assertEquals(1, f.length); -f = foo.bind(foo).bind(foo, 1).bind(foo).bind(foo, 1); -assertEquals(3, f(1)); +// The wrong number of arguments can be given to bound functions too. +f = foo.bind(foo); +assertEquals(3, f.length); +assertEquals([foo, 0, undefined], f()); +assertEquals([foo, 1, 1], f(1)); +assertEquals([foo, 2, 1], f(1, 2)); +assertEquals([foo, 3, 1], f(1, 2, 3)); +assertEquals([foo, 4, 1], f(1, 2, 3, 4)); + +f = foo.bind(foo, 1); +assertEquals(2, f.length); +assertEquals([foo, 1, 1], f()); +assertEquals([foo, 2, 1], f(2)); +assertEquals([foo, 3, 1], f(2, 3)); +assertEquals([foo, 4, 1], f(2, 3, 4)); + +f = foo.bind(foo, 1, 2); assertEquals(1, f.length); +assertEquals([foo, 2, 1], f()); +assertEquals([foo, 3, 1], f(3)); +assertEquals([foo, 4, 1], f(3, 4)); + +f = foo.bind(foo, 1, 2, 3); +assertEquals(0, f.length); +assertEquals([foo, 3, 1], f()); +assertEquals([foo, 4, 1], f(4)); + +f = foo.bind(foo, 1, 2, 3, 4); +assertEquals(0, f.length); +assertEquals([foo, 4, 1], f()); // Test constructor calls. @@ -171,13 +206,91 @@ assertEquals(3, obj2.z); // Test bind chains when used as a constructor. - f = bar.bind(bar, 1).bind(bar, 2).bind(bar, 3); obj2 = new f(); assertEquals(1, obj2.x); assertEquals(2, obj2.y); assertEquals(3, obj2.z); -// Test instanceof obj2 is bar, not f. +// Test obj2 is instanceof both bar and f. assertTrue(obj2 instanceof bar); -assertFalse(obj2 instanceof f); +assertTrue(obj2 instanceof f); + +// This-args are not relevant to instanceof. +f = bar.bind(foo.prototype, 1). + bind(String.prototype, 2). + bind(Function.prototype, 3); +var obj3 = new f(); +assertTrue(obj3 instanceof bar); +assertTrue(obj3 instanceof f); +assertFalse(obj3 instanceof foo); +assertFalse(obj3 instanceof Function); +assertFalse(obj3 instanceof String); + +// thisArg is converted to object. +f = foo.bind(undefined); +assertEquals([this, 0, undefined], f()); + +f = foo.bind(null); +assertEquals([this, 0, undefined], f()); + +f = foo.bind(42); +assertEquals([Object(42), 0, undefined], f()); + +f = foo.bind("foo"); +assertEquals([Object("foo"), 0, undefined], f()); + +f = foo.bind(true); +assertEquals([Object(true), 0, undefined], f()); + +// Strict functions don't convert thisArg. +function soo(x, y, z) { + "use strict"; + return [this, arguments.length, x]; +} + +var s = soo.bind(undefined); +assertEquals([undefined, 0, undefined], s()); + +s = soo.bind(null); +assertEquals([null, 0, undefined], s()); + +s = soo.bind(42); +assertEquals([42, 0, undefined], s()); + +s = soo.bind("foo"); +assertEquals(["foo", 0, undefined], s()); + +s = soo.bind(true); +assertEquals([true, 0, undefined], s()); + +// Test that .arguments and .caller are poisoned according to the ES5 spec. + +// Check that property descriptors are correct (unconfigurable, unenumerable, +// and both get and set is the ThrowTypeError function). +var cdesc = Object.getOwnPropertyDescriptor(f, "caller"); +var adesc = Object.getOwnPropertyDescriptor(f, "arguments"); + +assertFalse(cdesc.enumerable); +assertFalse(cdesc.configurable); + +assertFalse(adesc.enumerable); +assertFalse(adesc.configurable); + +assertSame(cdesc.get, cdesc.set); +assertSame(cdesc.get, adesc.get); +assertSame(cdesc.get, adesc.set); + +assertTrue(cdesc.get instanceof Function); +assertEquals(0, cdesc.get.length); +assertThrows(cdesc.get, TypeError); + +assertThrows(function() { return f.caller; }, TypeError); +assertThrows(function() { f.caller = 42; }, TypeError); +assertThrows(function() { return f.arguments; }, TypeError); +assertThrows(function() { f.arguments = 42; }, TypeError); + +// Shouldn't throw. Accessing the functions caller must throw if +// the caller is strict and the callee isn't. A bound function is built-in, +// but not considered strict. +(function foo() { return foo.caller; }).bind()(); diff --git a/test/mjsunit/function-call.js b/test/mjsunit/function-call.js index 06479ad4..26890ed1 100644 --- a/test/mjsunit/function-call.js +++ b/test/mjsunit/function-call.js @@ -68,8 +68,7 @@ var should_throw_on_null_and_undefined = String.prototype.toUpperCase, String.prototype.toLocaleUpperCase, String.prototype.trim, - Number.prototype.toLocaleString, - Error.prototype.toString]; + Number.prototype.toLocaleString]; // Non generic natives do not work on any input other than the specific // type, but since this change will allow call to be invoked with undefined @@ -134,7 +133,8 @@ var non_generic = Date.prototype.toJSON, RegExp.prototype.exec, RegExp.prototype.test, - RegExp.prototype.toString]; + RegExp.prototype.toString, + Error.prototype.toString]; // Mapping functions. diff --git a/test/mjsunit/function-named-self-reference.js b/test/mjsunit/function-named-self-reference.js new file mode 100644 index 00000000..5b03b094 --- /dev/null +++ b/test/mjsunit/function-named-self-reference.js @@ -0,0 +1,45 @@ +// Copyright 2011 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 + +var fn = function fn(val) { + if (val) return val; + + %OptimizeFunctionOnNextCall(fn); + + function run(val) { + var res = fn((val + 1) << 1); + + return res; + } + + return run(0); +} + +var res = fn(); +assertEquals(res, 2); diff --git a/test/mjsunit/fuzz-natives.js b/test/mjsunit/fuzz-natives.js index ff6677e6..2965e745 100644 --- a/test/mjsunit/fuzz-natives.js +++ b/test/mjsunit/fuzz-natives.js @@ -163,6 +163,9 @@ var knownProblems = { "PromoteScheduledException": true, "DeleteHandleScopeExtensions": true, + // Vararg with minimum number > 0. + "Call": true, + // Requires integer arguments to be non-negative. "Apply": true, @@ -181,8 +184,9 @@ var knownProblems = { "RegExpConstructResult": true, "_RegExpConstructResult": true, - // This function performs some checks compile time (it requires its first - // argument to be a compile time smi). + // This functions perform some checks compile time (they require one of their + // arguments to be a compile time smi). + "_DateField": true, "_GetFromCache": true, // This function expects its first argument to be a non-smi. diff --git a/test/mjsunit/get-own-property-descriptor.js b/test/mjsunit/get-own-property-descriptor.js index abb24200..159c63bc 100644 --- a/test/mjsunit/get-own-property-descriptor.js +++ b/test/mjsunit/get-own-property-descriptor.js @@ -73,7 +73,7 @@ assertEquals(descObjectElement.value, 42); var a = new String('foobar'); for (var i = 0; i < a.length; i++) { var descStringObject = Object.getOwnPropertyDescriptor(a, i); - assertFalse(descStringObject.enumerable); + assertTrue(descStringObject.enumerable); assertFalse(descStringObject.configurable); assertFalse(descStringObject.writable); assertEquals(descStringObject.value, a.substring(i, i+1)); diff --git a/test/mjsunit/getter-in-value-prototype.js b/test/mjsunit/getter-in-value-prototype.js index b55320ac..abe2cb19 100644 --- a/test/mjsunit/getter-in-value-prototype.js +++ b/test/mjsunit/getter-in-value-prototype.js @@ -31,5 +31,5 @@ // JSObject. String.prototype.__defineGetter__('x', function() { return this; }); -assertEquals('asdf', 'asdf'.x); +assertEquals(Object('asdf'), 'asdf'.x); diff --git a/test/mjsunit/global-const-var-conflicts.js b/test/mjsunit/global-const-var-conflicts.js index d38d0ee8..2fca96f9 100644 --- a/test/mjsunit/global-const-var-conflicts.js +++ b/test/mjsunit/global-const-var-conflicts.js @@ -26,7 +26,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Check that dynamically introducing conflicting consts/vars -// leads to exceptions. +// is silently ignored (and does not lead to exceptions). var caught = 0; @@ -46,12 +46,12 @@ eval("var c"); try { eval("const c"); } catch (e) { caught++; assertTrue(e instanceof TypeError); } assertTrue(typeof c == 'undefined'); try { eval("const c = 1"); } catch (e) { caught++; assertTrue(e instanceof TypeError); } -assertTrue(typeof c == 'undefined'); +assertEquals(1, c); eval("var d = 0"); try { eval("const d"); } catch (e) { caught++; assertTrue(e instanceof TypeError); } -assertEquals(0, d); +assertEquals(undefined, d); try { eval("const d = 1"); } catch (e) { caught++; assertTrue(e instanceof TypeError); } -assertEquals(0, d); +assertEquals(1, d); -assertEquals(8, caught); +assertEquals(0, caught); diff --git a/test/mjsunit/harmony/block-conflicts.js b/test/mjsunit/harmony/block-conflicts.js index 8d3de6f9..8388504b 100644 --- a/test/mjsunit/harmony/block-conflicts.js +++ b/test/mjsunit/harmony/block-conflicts.js @@ -25,10 +25,13 @@ // (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-block-scoping +// Flags: --harmony-scoping // Test for conflicting variable bindings. +// TODO(ES6): properly activate extended mode +"use strict"; + function CheckException(e) { var string = e.toString(); assertTrue(string.indexOf("has already been declared") >= 0 || @@ -80,6 +83,11 @@ var letbinds = [ "let x", "let x = function() {}", "let x, y", "let y, x", + "const x = 0", + "const x = undefined", + "const x = function() {}", + "const x = 2, y = 3", + "const y = 4, x = 5", ]; var varbinds = [ "var x", "var x = 0", @@ -122,5 +130,5 @@ for (var v = 0; v < varbinds.length; ++v) { // Test conflicting parameter/var bindings. for (var v = 0; v < varbinds.length; ++v) { - TestConflict('(function (x) { ' + varbinds[v] + '; })()'); + TestNoConflict('(function (x) { ' + varbinds[v] + '; })()'); } diff --git a/test/mjsunit/harmony/block-const-assign.js b/test/mjsunit/harmony/block-const-assign.js new file mode 100644 index 00000000..8297a558 --- /dev/null +++ b/test/mjsunit/harmony/block-const-assign.js @@ -0,0 +1,131 @@ +// Copyright 2011 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-scoping + +// Test that we throw early syntax errors in harmony mode +// when using an immutable binding in an assigment or with +// prefix/postfix decrement/increment operators. +// TODO(ES6): properly activate extended mode +"use strict"; + + +// Function local const. +function constDecl0(use) { + return "(function() { const constvar = 1; " + use + "; });"; +} + + +function constDecl1(use) { + return "(function() { " + use + "; const constvar = 1; });"; +} + + +// Function local const, assign from eval. +function constDecl2(use) { + use = "eval('(function() { " + use + " })')"; + return "(function() { const constvar = 1; " + use + "; })();"; +} + + +function constDecl3(use) { + use = "eval('(function() { " + use + " })')"; + return "(function() { " + use + "; const constvar = 1; })();"; +} + + +// Block local const. +function constDecl4(use) { + return "(function() { { const constvar = 1; " + use + "; } });"; +} + + +function constDecl5(use) { + return "(function() { { " + use + "; const constvar = 1; } });"; +} + + +// Block local const, assign from eval. +function constDecl6(use) { + use = "eval('(function() {" + use + "})')"; + return "(function() { { const constvar = 1; " + use + "; } })();"; +} + + +function constDecl7(use) { + use = "eval('(function() {" + use + "})')"; + return "(function() { { " + use + "; const constvar = 1; } })();"; +} + + +// Function expression name. +function constDecl8(use) { + return "(function constvar() { " + use + "; });"; +} + + +// Function expression name, assign from eval. +function constDecl9(use) { + use = "eval('(function(){" + use + "})')"; + return "(function constvar() { " + use + "; })();"; +} + +let decls = [ constDecl0, + constDecl1, + constDecl2, + constDecl3, + constDecl4, + constDecl5, + constDecl6, + constDecl7, + constDecl8, + constDecl9 + ]; +let uses = [ 'constvar = 1;', + 'constvar += 1;', + '++constvar;', + 'constvar++;' + ]; + +function Test(d,u) { + 'use strict'; + try { + print(d(u)); + eval(d(u)); + } catch (e) { + assertInstanceof(e, SyntaxError); + assertTrue(e.toString().indexOf("Assignment to constant variable") >= 0); + return; + } + assertUnreachable(); +} + +for (var d = 0; d < decls.length; ++d) { + for (var u = 0; u < uses.length; ++u) { + Test(decls[d], uses[u]); + } +} diff --git a/test/mjsunit/harmony/block-early-errors.js b/test/mjsunit/harmony/block-early-errors.js new file mode 100644 index 00000000..791f001a --- /dev/null +++ b/test/mjsunit/harmony/block-early-errors.js @@ -0,0 +1,55 @@ +// Copyright 2011 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-scoping + +function CheckException(e) { + var string = e.toString(); + assertInstanceof(e, SyntaxError); + assertTrue(string.indexOf("Illegal let") >= 0); +} + +function Check(str) { + try { + eval("(function () { " + str + " })"); + assertUnreachable(); + } catch (e) { + CheckException(e); + } + try { + eval("(function () { { " + str + " } })"); + assertUnreachable(); + } catch (e) { + CheckException(e); + } +} + +// Check for early syntax errors when using let +// declarations outside of extended mode. +Check("let x;"); +Check("let x = 1;"); +Check("let x, y;"); diff --git a/test/mjsunit/harmony/block-for.js b/test/mjsunit/harmony/block-for.js new file mode 100644 index 00000000..e84f0d2f --- /dev/null +++ b/test/mjsunit/harmony/block-for.js @@ -0,0 +1,146 @@ +// Copyright 2011 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-scoping + +// TODO(ES6): properly activate extended mode +"use strict"; + +function props(x) { + var array = []; + for (let p in x) array.push(p); + return array.sort(); +} + +assertEquals(0, props({}).length); +assertEquals(1, props({x:1}).length); +assertEquals(2, props({x:1, y:2}).length); + +assertArrayEquals(["x"], props({x:1})); +assertArrayEquals(["x", "y"], props({x:1, y:2})); +assertArrayEquals(["x", "y", "zoom"], props({x:1, y:2, zoom:3})); + +assertEquals(0, props([]).length); +assertEquals(1, props([1]).length); +assertEquals(2, props([1,2]).length); + +assertArrayEquals(["0"], props([1])); +assertArrayEquals(["0", "1"], props([1,2])); +assertArrayEquals(["0", "1", "2"], props([1,2,3])); + +var o = {}; +var a = []; +let i = "outer_i"; +let s = "outer_s"; +for (let i = 0x0020; i < 0x01ff; i+=2) { + let s = 'char:' + String.fromCharCode(i); + a.push(s); + o[s] = i; +} +assertArrayEquals(a, props(o)); +assertEquals(i, "outer_i"); +assertEquals(s, "outer_s"); + +var a = []; +assertEquals(0, props(a).length); +a[Math.pow(2,30)-1] = 0; +assertEquals(1, props(a).length); +a[Math.pow(2,31)-1] = 0; +assertEquals(2, props(a).length); +a[1] = 0; +assertEquals(3, props(a).length); + +var result = ''; +for (let p in {a : [0], b : 1}) { result += p; } +assertEquals('ab', result); + +var result = ''; +for (let p in {a : {v:1}, b : 1}) { result += p; } +assertEquals('ab', result); + +var result = ''; +for (let p in { get a() {}, b : 1}) { result += p; } +assertEquals('ab', result); + +var result = ''; +for (let p in { get a() {}, set a(x) {}, b : 1}) { result += p; } +assertEquals('ab', result); + + +// Check that there is exactly one variable without initializer +// in a for-in statement with let variables. +// TODO(ES6): properly activate extended mode +assertThrows("function foo() { 'use strict'; for (let in {}) { } }", SyntaxError); +assertThrows("function foo() { 'use strict'; for (let x = 3 in {}) { } }", SyntaxError); +assertThrows("function foo() { 'use strict'; for (let x, y in {}) { } }", SyntaxError); +assertThrows("function foo() { 'use strict'; for (let x = 3, y in {}) { } }", SyntaxError); +assertThrows("function foo() { 'use strict'; for (let x, y = 4 in {}) { } }", SyntaxError); +assertThrows("function foo() { 'use strict'; for (let x = 3, y = 4 in {}) { } }", SyntaxError); + + +// In a normal for statement the iteration variable is not +// freshly allocated for each iteration. +function closures1() { + let a = []; + for (let i = 0; i < 5; ++i) { + a.push(function () { return i; }); + } + for (let j = 0; j < 5; ++j) { + assertEquals(5, a[j]()); + } +} +closures1(); + + +function closures2() { + let a = [], b = []; + for (let i = 0, j = 10; i < 5; ++i, ++j) { + a.push(function () { return i; }); + b.push(function () { return j; }); + } + for (let k = 0; k < 5; ++k) { + assertEquals(5, a[k]()); + assertEquals(15, b[k]()); + } +} +closures2(); + + +// In a for-in statement the iteration variable is fresh +// for earch iteration. +function closures3(x) { + let a = []; + for (let p in x) { + a.push(function () { return p; }); + } + let k = 0; + for (let q in x) { + assertEquals(q, a[k]()); + ++k; + } +} +closures3({a : [0], b : 1, c : {v : 1}, get d() {}, set e(x) {}}); diff --git a/test/mjsunit/harmony/block-leave.js b/test/mjsunit/harmony/block-leave.js index 73eaf294..a7f6b694 100644 --- a/test/mjsunit/harmony/block-leave.js +++ b/test/mjsunit/harmony/block-leave.js @@ -25,7 +25,10 @@ // (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-block-scoping +// Flags: --harmony-scoping + +// TODO(ES6): properly activate extended mode +"use strict"; // We want to test the context chain shape. In each of the tests cases // below, the outer with is to force a runtime lookup of the identifier 'x' @@ -64,31 +67,30 @@ try { } catch (e) { caught = true; assertEquals(25, e); - with ({y:19}) { - assertEquals(19, y); + (function () { try { // NOTE: This checks that the block scope containing xx has been // removed from the context chain. - xx; + eval('xx'); assertTrue(false); // should not reach here } catch (e2) { assertTrue(e2 instanceof ReferenceError); } - } + })(); } assertTrue(caught); -with ({x: 'outer'}) { +(function(x) { label: { let x = 'inner'; break label; } - assertEquals('outer', x); -} + assertEquals('outer', eval('x')); +})('outer'); -with ({x: 'outer'}) { +(function(x) { label: { let x = 'middle'; { @@ -96,20 +98,20 @@ with ({x: 'outer'}) { break label; } } - assertEquals('outer', x); -} + assertEquals('outer', eval('x')); +})('outer'); -with ({x: 'outer'}) { +(function(x) { for (var i = 0; i < 10; ++i) { let x = 'inner' + i; continue; } - assertEquals('outer', x); -} + assertEquals('outer', eval('x')); +})('outer'); -with ({x: 'outer'}) { +(function(x) { label: for (var i = 0; i < 10; ++i) { let x = 'middle' + i; for (var j = 0; j < 10; ++j) { @@ -117,21 +119,21 @@ with ({x: 'outer'}) { continue label; } } - assertEquals('outer', x); -} + assertEquals('outer', eval('x')); +})('outer'); -with ({x: 'outer'}) { +(function(x) { try { let x = 'inner'; throw 0; } catch (e) { - assertEquals('outer', x); + assertEquals('outer', eval('x')); } -} +})('outer'); -with ({x: 'outer'}) { +(function(x) { try { let x = 'middle'; { @@ -139,27 +141,27 @@ with ({x: 'outer'}) { throw 0; } } catch (e) { - assertEquals('outer', x); + assertEquals('outer', eval('x')); } -} +})('outer'); try { - with ({x: 'outer'}) { + (function(x) { try { let x = 'inner'; throw 0; } finally { - assertEquals('outer', x); + assertEquals('outer', eval('x')); } - } + })('outer'); } catch (e) { if (e instanceof MjsUnitAssertionError) throw e; } try { - with ({x: 'outer'}) { + (function(x) { try { let x = 'middle'; { @@ -167,9 +169,9 @@ try { throw 0; } } finally { - assertEquals('outer', x); + assertEquals('outer', eval('x')); } - } + })('outer'); } catch (e) { if (e instanceof MjsUnitAssertionError) throw e; } @@ -179,47 +181,47 @@ try { // from with. function f() {} -with ({x: 'outer'}) { +(function(x) { label: { let x = 'inner'; break label; } f(); // The context could be restored from the stack after the call. - assertEquals('outer', x); -} + assertEquals('outer', eval('x')); +})('outer'); -with ({x: 'outer'}) { +(function(x) { for (var i = 0; i < 10; ++i) { let x = 'inner'; continue; } f(); - assertEquals('outer', x); -} + assertEquals('outer', eval('x')); +})('outer'); -with ({x: 'outer'}) { +(function(x) { try { let x = 'inner'; throw 0; } catch (e) { f(); - assertEquals('outer', x); + assertEquals('outer', eval('x')); } -} +})('outer'); try { - with ({x: 'outer'}) { + (function(x) { try { let x = 'inner'; throw 0; } finally { f(); - assertEquals('outer', x); + assertEquals('outer', eval('x')); } - } + })('outer'); } catch (e) { if (e instanceof MjsUnitAssertionError) throw e; } diff --git a/test/mjsunit/harmony/block-let-crankshaft.js b/test/mjsunit/harmony/block-let-crankshaft.js index c2fb96b6..1db1792e 100644 --- a/test/mjsunit/harmony/block-let-crankshaft.js +++ b/test/mjsunit/harmony/block-let-crankshaft.js @@ -25,10 +25,209 @@ // (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-block-scoping --allow-natives-syntax +// Flags: --harmony-scoping --allow-natives-syntax + +// TODO(ES6): properly activate extended mode +"use strict"; + +// Check that the following functions are optimizable. +var functions = [ f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, + f15, f16, f17, f18, f19, f20, f21, f22, f23 ]; + +for (var i = 0; i < functions.length; ++i) { + var func = functions[i]; + print("Testing:"); + print(func); + for (var j = 0; j < 10; ++j) { + func(12); + } + %OptimizeFunctionOnNextCall(func); + func(12); + assertTrue(%GetOptimizationStatus(func) != 2); +} + +function f1() { } + +function f2(x) { } + +function f3() { + let x; +} + +function f4() { + function foo() { + } +} + +function f5() { + let x = 1; +} + +function f6() { + const x = 1; +} + +function f7(x) { + return x; +} + +function f8() { + let x; + return x; +} + +function f9() { + function x() { + } + return x; +} + +function f10(x) { + x = 1; +} + +function f11() { + let x; + x = 1; +} + +function f12() { + function x() {}; + x = 1; +} + +function f13(x) { + (function() { x; }); +} + +function f14() { + let x; + (function() { x; }); +} + +function f15() { + function x() { + } + (function() { x; }); +} + +function f16() { + let x = 1; + (function() { x; }); +} + +function f17() { + const x = 1; + (function() { x; }); +} + +function f18(x) { + return x; + (function() { x; }); +} + +function f19() { + let x; + return x; + (function() { x; }); +} + +function f20() { + function x() { + } + return x; + (function() { x; }); +} + +function f21(x) { + x = 1; + (function() { x; }); +} + +function f22() { + let x; + x = 1; + (function() { x; }); +} + +function f23() { + function x() { } + x = 1; + (function() { x; }); +} + // Test that temporal dead zone semantics for function and block scoped -// ket bindings are handled by the optimizing compiler. +// let bindings are handled by the optimizing compiler. + +function TestFunctionLocal(s) { + 'use strict'; + var func = eval("(function baz(){" + s + "; })"); + print("Testing:"); + print(func); + for (var i = 0; i < 5; ++i) { + try { + func(); + assertUnreachable(); + } catch (e) { + assertInstanceof(e, ReferenceError); + } + } + %OptimizeFunctionOnNextCall(func); + try { + func(); + assertUnreachable(); + } catch (e) { + assertInstanceof(e, ReferenceError); + } +} + +function TestFunctionContext(s) { + 'use strict'; + var func = eval("(function baz(){ " + s + "; (function() { x; }); })"); + print("Testing:"); + print(func); + for (var i = 0; i < 5; ++i) { + print(i); + try { + func(); + assertUnreachable(); + } catch (e) { + assertInstanceof(e, ReferenceError); + } + } + print("optimize"); + %OptimizeFunctionOnNextCall(func); + try { + print("call"); + func(); + assertUnreachable(); + } catch (e) { + print("catch"); + assertInstanceof(e, ReferenceError); + } +} + +function TestAll(s) { + TestFunctionLocal(s); + TestFunctionContext(s); +} + +// Use before initialization in declaration statement. +TestAll('let x = x + 1'); +TestAll('let x = x += 1'); +TestAll('let x = x++'); +TestAll('let x = ++x'); +TestAll('const x = x + 1'); + +// Use before initialization in prior statement. +TestAll('x + 1; let x;'); +TestAll('x = 1; let x;'); +TestAll('x += 1; let x;'); +TestAll('++x; let x;'); +TestAll('x++; let x;'); +TestAll('let y = x; const x = 1;'); + function f(x, b) { let y = (b ? y : x) + 42; diff --git a/test/mjsunit/harmony/block-let-declaration.js b/test/mjsunit/harmony/block-let-declaration.js index 49b63481..480e0334 100644 --- a/test/mjsunit/harmony/block-let-declaration.js +++ b/test/mjsunit/harmony/block-let-declaration.js @@ -25,41 +25,113 @@ // (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-block-scoping +// Flags: --harmony-scoping // Test let declarations in various settings. +// TODO(ES6): properly activate extended mode +"use strict"; // Global let x; let y = 2; +const z = 4; // Block local { let y; let x = 3; + const z = 5; } assertEquals(undefined, x); assertEquals(2,y); +assertEquals(4,z); if (true) { let y; assertEquals(undefined, y); } +// Invalid declarations are early errors in harmony mode and thus should trigger +// an exception in eval code during parsing, before even compiling or executing +// the code. Thus the generated function is not called here. function TestLocalThrows(str, expect) { - assertThrows("(function(){" + str + "})()", expect); + assertThrows("(function(){ 'use strict'; " + str + "})", expect); } function TestLocalDoesNotThrow(str) { - assertDoesNotThrow("(function(){" + str + "})()"); + assertDoesNotThrow("(function(){ 'use strict'; " + str + "})()"); } -// Unprotected statement +// Test let declarations in statement positions. TestLocalThrows("if (true) let x;", SyntaxError); +TestLocalThrows("if (true) {} else let x;", SyntaxError); TestLocalThrows("do let x; while (false)", SyntaxError); TestLocalThrows("while (false) let x;", SyntaxError); +TestLocalThrows("label: let x;", SyntaxError); +TestLocalThrows("for (;false;) let x;", SyntaxError); +TestLocalThrows("switch (true) { case true: let x; }", SyntaxError); +TestLocalThrows("switch (true) { default: let x; }", SyntaxError); +// Test const declarations with initialisers in statement positions. +TestLocalThrows("if (true) const x = 1;", SyntaxError); +TestLocalThrows("if (true) {} else const x = 1;", SyntaxError); +TestLocalThrows("do const x = 1; while (false)", SyntaxError); +TestLocalThrows("while (false) const x = 1;", SyntaxError); +TestLocalThrows("label: const x = 1;", SyntaxError); +TestLocalThrows("for (;false;) const x = 1;", SyntaxError); +TestLocalThrows("switch (true) { case true: const x = 1; }", SyntaxError); +TestLocalThrows("switch (true) { default: const x = 1; }", SyntaxError); + +// Test const declarations without initialisers. +TestLocalThrows("const x;", SyntaxError); +TestLocalThrows("const x = 1, y;", SyntaxError); +TestLocalThrows("const x, y = 1;", SyntaxError); + +// Test const declarations without initialisers in statement positions. +TestLocalThrows("if (true) const x;", SyntaxError); +TestLocalThrows("if (true) {} else const x;", SyntaxError); +TestLocalThrows("do const x; while (false)", SyntaxError); +TestLocalThrows("while (false) const x;", SyntaxError); +TestLocalThrows("label: const x;", SyntaxError); +TestLocalThrows("for (;false;) const x;", SyntaxError); +TestLocalThrows("switch (true) { case true: const x; }", SyntaxError); +TestLocalThrows("switch (true) { default: const x; }", SyntaxError); + +// Test var declarations in statement positions. TestLocalDoesNotThrow("if (true) var x;"); +TestLocalDoesNotThrow("if (true) {} else var x;"); TestLocalDoesNotThrow("do var x; while (false)"); TestLocalDoesNotThrow("while (false) var x;"); +TestLocalDoesNotThrow("label: var x;"); +TestLocalDoesNotThrow("for (;false;) var x;"); +TestLocalDoesNotThrow("switch (true) { case true: var x; }"); +TestLocalDoesNotThrow("switch (true) { default: var x; }"); + +// Test function declarations in source element and +// non-strict statement positions. +function f() { + // Non-strict source element positions. + function g0() { + "use strict"; + // Strict source element positions. + function h() { } + { + function h1() { } + } + } + { + function g1() { } + } +} +f(); + +// Test function declarations in statement position in strict mode. +TestLocalThrows("function f() { if (true) function g() {}", SyntaxError); +TestLocalThrows("function f() { if (true) {} else function g() {}", SyntaxError); +TestLocalThrows("function f() { do function g() {} while (false)", SyntaxError); +TestLocalThrows("function f() { while (false) function g() {}", SyntaxError); +TestLocalThrows("function f() { label: function g() {}", SyntaxError); +TestLocalThrows("function f() { for (;false;) function g() {}", SyntaxError); +TestLocalThrows("function f() { switch (true) { case true: function g() {} }", SyntaxError); +TestLocalThrows("function f() { switch (true) { default: function g() {} }", SyntaxError); diff --git a/test/mjsunit/harmony/block-let-semantics.js b/test/mjsunit/harmony/block-let-semantics.js index 198c3b4f..d14e7cd3 100644 --- a/test/mjsunit/harmony/block-let-semantics.js +++ b/test/mjsunit/harmony/block-let-semantics.js @@ -25,7 +25,10 @@ // (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-block-scoping +// Flags: --harmony-scoping + +// TODO(ES6): properly activate extended mode +"use strict"; // Test temporal dead zone semantics of let bound variables in // function and block scopes. @@ -61,6 +64,7 @@ TestAll('let x = x + 1'); TestAll('let x = x += 1'); TestAll('let x = x++'); TestAll('let x = ++x'); +TestAll('const x = x + 1'); // Use before initialization in prior statement. TestAll('x + 1; let x;'); @@ -68,25 +72,36 @@ TestAll('x = 1; let x;'); TestAll('x += 1; let x;'); TestAll('++x; let x;'); TestAll('x++; let x;'); +TestAll('let y = x; const x = 1;'); TestAll('f(); let x; function f() { return x + 1; }'); TestAll('f(); let x; function f() { x = 1; }'); TestAll('f(); let x; function f() { x += 1; }'); TestAll('f(); let x; function f() { ++x; }'); TestAll('f(); let x; function f() { x++; }'); +TestAll('f(); const x = 1; function f() { return x; }'); TestAll('f()(); let x; function f() { return function() { return x + 1; } }'); TestAll('f()(); let x; function f() { return function() { x = 1; } }'); TestAll('f()(); let x; function f() { return function() { x += 1; } }'); TestAll('f()(); let x; function f() { return function() { ++x; } }'); TestAll('f()(); let x; function f() { return function() { x++; } }'); +TestAll('f()(); const x = 1; function f() { return function() { return x; } }'); -// Use in before initialization with a dynamic lookup. +// Use before initialization with a dynamic lookup. TestAll('eval("x + 1;"); let x;'); TestAll('eval("x = 1;"); let x;'); TestAll('eval("x += 1;"); let x;'); TestAll('eval("++x;"); let x;'); TestAll('eval("x++;"); let x;'); +TestAll('eval("x"); const x = 1;'); + +// Use before initialization with check for eval-shadowed bindings. +TestAll('function f() { eval("var y = 2;"); x + 1; }; f(); let x;'); +TestAll('function f() { eval("var y = 2;"); x = 1; }; f(); let x;'); +TestAll('function f() { eval("var y = 2;"); x += 1; }; f(); let x;'); +TestAll('function f() { eval("var y = 2;"); ++x; }; f(); let x;'); +TestAll('function f() { eval("var y = 2;"); x++; }; f(); let x;'); // Test that variables introduced by function declarations are created and // initialized upon entering a function / block scope. @@ -115,7 +130,7 @@ TestAll('{ function k() { return 0; } }; k(); '); // Test that a function declaration sees the scope it resides in. function f2() { - let m, n; + let m, n, o, p; { m = g; function g() { @@ -132,7 +147,44 @@ function f2() { function h() { return b + c; } - let b = 3; + let c = 3; } assertEquals(5, n()); + + { + o = i; + function i() { + return d; + } + let d = 4; + } + assertEquals(4, o()); + + try { + throw 5; + } catch(e) { + p = j; + function j() { + return e + f; + } + let f = 6; + } + assertEquals(11, p()); +} +f2(); + +// Test that resolution of let bound variables works with scopes that call eval. +function outer() { + function middle() { + function inner() { + return x; + } + eval("1 + 1"); + return x + inner(); + } + + let x = 1; + return middle(); } + +assertEquals(2, outer()); diff --git a/test/mjsunit/harmony/block-scoping.js b/test/mjsunit/harmony/block-scoping.js index 266e3807..31194d99 100644 --- a/test/mjsunit/harmony/block-scoping.js +++ b/test/mjsunit/harmony/block-scoping.js @@ -25,9 +25,12 @@ // (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 --harmony-block-scoping +// Flags: --allow-natives-syntax --harmony-scoping // Test functionality of block scopes. +// TODO(ES6): properly activate extended mode +"use strict"; + // Hoisting of var declarations. function f1() { { @@ -44,12 +47,16 @@ f1(); function f2(one) { var x = one + 1; let y = one + 2; + const u = one + 4; { let z = one + 3; + const v = one + 5; assertEquals(1, eval('one')); assertEquals(2, eval('x')); assertEquals(3, eval('y')); assertEquals(4, eval('z')); + assertEquals(5, eval('u')); + assertEquals(6, eval('v')); } } f2(1); @@ -59,12 +66,17 @@ f2(1); function f3(one) { var x = one + 1; let y = one + 2; + const u = one + 4; { let z = one + 3; + const v = one + 5; assertEquals(1, one); assertEquals(2, x); assertEquals(3, y); assertEquals(4, z); + assertEquals(5, u); + assertEquals(6, v); + } } f3(1); @@ -74,13 +86,17 @@ f3(1); function f4(one) { var x = one + 1; let y = one + 2; + const u = one + 4; { let z = one + 3; + const v = one + 5; function f() { assertEquals(1, eval('one')); assertEquals(2, eval('x')); assertEquals(3, eval('y')); assertEquals(4, eval('z')); + assertEquals(5, eval('u')); + assertEquals(6, eval('v')); }; } } @@ -91,13 +107,17 @@ f4(1); function f5(one) { var x = one + 1; let y = one + 2; + const u = one + 4; { let z = one + 3; + const v = one + 5; function f() { assertEquals(1, one); assertEquals(2, x); assertEquals(3, y); assertEquals(4, z); + assertEquals(5, u); + assertEquals(6, v); }; } } @@ -107,8 +127,10 @@ f5(1); // Return from block. function f6() { let x = 1; + const u = 3; { let y = 2; + const v = 4; return x + y; } } @@ -120,13 +142,26 @@ function f7(a) { let b = 1; var c = 1; var d = 1; - { // let variables shadowing argument, let and var variables + const e = 1; + { // let variables shadowing argument, let, const and var variables let a = 2; let b = 2; let c = 2; + let e = 2; + assertEquals(2,a); + assertEquals(2,b); + assertEquals(2,c); + assertEquals(2,e); + } + { // const variables shadowing argument, let, const and var variables + const a = 2; + const b = 2; + const c = 2; + const e = 2; assertEquals(2,a); assertEquals(2,b); assertEquals(2,c); + assertEquals(2,e); } try { throw 'stuff1'; @@ -156,6 +191,12 @@ function f7(a) { } catch (c) { // catch variable shadowing var variable assertEquals('stuff3',c); + { + // const variable shadowing catch variable + const c = 3; + assertEquals(3,c); + } + assertEquals('stuff3',c); try { throw 'stuff4'; } catch(c) { @@ -178,14 +219,16 @@ function f7(a) { c = 2; } assertEquals(1,c); - (function(a,b,c) { - // arguments shadowing argument, let and var variable + (function(a,b,c,e) { + // arguments shadowing argument, let, const and var variable a = 2; b = 2; c = 2; + e = 2; assertEquals(2,a); assertEquals(2,b); assertEquals(2,c); + assertEquals(2,e); // var variable shadowing var variable var d = 2; })(1,1); @@ -193,24 +236,30 @@ function f7(a) { assertEquals(1,b); assertEquals(1,c); assertEquals(1,d); + assertEquals(1,e); } f7(1); -// Ensure let variables are block local and var variables function local. +// Ensure let and const variables are block local +// and var variables function local. function f8() { var let_accessors = []; var var_accessors = []; + var const_accessors = []; for (var i = 0; i < 10; i++) { let x = i; var y = i; + const z = i; let_accessors[i] = function() { return x; } var_accessors[i] = function() { return y; } + const_accessors[i] = function() { return z; } } for (var j = 0; j < 10; j++) { y = j + 10; assertEquals(j, let_accessors[j]()); assertEquals(y, var_accessors[j]()); + assertEquals(j, const_accessors[j]()); } } f8(); diff --git a/test/mjsunit/harmony/collections.js b/test/mjsunit/harmony/collections.js new file mode 100644 index 00000000..412e6f14 --- /dev/null +++ b/test/mjsunit/harmony/collections.js @@ -0,0 +1,314 @@ +// Copyright 2011 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-collections --expose-gc + + +// Test valid getter and setter calls on Sets. +function TestValidSetCalls(m) { + assertDoesNotThrow(function () { m.add(new Object) }); + assertDoesNotThrow(function () { m.has(new Object) }); + assertDoesNotThrow(function () { m.delete(new Object) }); +} +TestValidSetCalls(new Set); + + +// Test valid getter and setter calls on Maps and WeakMaps +function TestValidMapCalls(m) { + assertDoesNotThrow(function () { m.get(new Object) }); + assertDoesNotThrow(function () { m.set(new Object) }); + assertDoesNotThrow(function () { m.has(new Object) }); + assertDoesNotThrow(function () { m.delete(new Object) }); +} +TestValidMapCalls(new Map); +TestValidMapCalls(new WeakMap); + + +// Test invalid getter and setter calls for WeakMap only +function TestInvalidCalls(m) { + assertThrows(function () { m.get(undefined) }, TypeError); + assertThrows(function () { m.set(undefined, 0) }, TypeError); + assertThrows(function () { m.get(null) }, TypeError); + assertThrows(function () { m.set(null, 0) }, TypeError); + assertThrows(function () { m.get(0) }, TypeError); + assertThrows(function () { m.set(0, 0) }, TypeError); + assertThrows(function () { m.get('a-key') }, TypeError); + assertThrows(function () { m.set('a-key', 0) }, TypeError); +} +TestInvalidCalls(new WeakMap); + + +// Test expected behavior for Sets +function TestSet(set, key) { + assertFalse(set.has(key)); + set.add(key); + assertTrue(set.has(key)); + set.delete(key); + assertFalse(set.has(key)); +} +function TestSetBehavior(set) { + for (var i = 0; i < 20; i++) { + TestSet(set, new Object); + TestSet(set, i); + TestSet(set, i / 100); + TestSet(set, 'key-' + i); + } + var keys = [ +0, -0, +Infinity, -Infinity, true, false, null, undefined ]; + for (var i = 0; i < keys.length; i++) { + TestSet(set, keys[i]); + } +} +TestSetBehavior(new Set); + + +// Test expected mapping behavior for Maps and WeakMaps +function TestMapping(map, key, value) { + map.set(key, value); + assertSame(value, map.get(key)); +} +function TestMapBehavior1(m) { + TestMapping(m, new Object, 23); + TestMapping(m, new Object, 'the-value'); + TestMapping(m, new Object, new Object); +} +TestMapBehavior1(new Map); +TestMapBehavior1(new WeakMap); + + +// Test expected mapping behavior for Maps only +function TestMapBehavior2(m) { + for (var i = 0; i < 20; i++) { + TestMapping(m, i, new Object); + TestMapping(m, i / 10, new Object); + TestMapping(m, 'key-' + i, new Object); + } + var keys = [ +0, -0, +Infinity, -Infinity, true, false, null, undefined ]; + for (var i = 0; i < keys.length; i++) { + TestMapping(m, keys[i], new Object); + } +} +TestMapBehavior2(new Map); + + +// Test expected querying behavior of Maps and WeakMaps +function TestQuery(m) { + var key = new Object; + TestMapping(m, key, 'to-be-present'); + assertTrue(m.has(key)); + assertFalse(m.has(new Object)); + TestMapping(m, key, undefined); + assertFalse(m.has(key)); + assertFalse(m.has(new Object)); +} +TestQuery(new Map); +TestQuery(new WeakMap); + + +// Test expected deletion behavior of Maps and WeakMaps +function TestDelete(m) { + var key = new Object; + TestMapping(m, key, 'to-be-deleted'); + assertTrue(m.delete(key)); + assertFalse(m.delete(key)); + assertFalse(m.delete(new Object)); + assertSame(m.get(key), undefined); +} +TestDelete(new Map); +TestDelete(new WeakMap); + + +// Test GC of Maps and WeakMaps with entry +function TestGC1(m) { + var key = new Object; + m.set(key, 'not-collected'); + gc(); + assertSame('not-collected', m.get(key)); +} +TestGC1(new Map); +TestGC1(new WeakMap); + + +// Test GC of Maps and WeakMaps with chained entries +function TestGC2(m) { + var head = new Object; + for (key = head, i = 0; i < 10; i++, key = m.get(key)) { + m.set(key, new Object); + } + gc(); + var count = 0; + for (key = head; key != undefined; key = m.get(key)) { + count++; + } + assertEquals(11, count); +} +TestGC2(new Map); +TestGC2(new WeakMap); + + +// Test property attribute [[Enumerable]] +function TestEnumerable(func) { + function props(x) { + var array = []; + for (var p in x) array.push(p); + return array.sort(); + } + assertArrayEquals([], props(func)); + assertArrayEquals([], props(func.prototype)); + assertArrayEquals([], props(new func())); +} +TestEnumerable(Set); +TestEnumerable(Map); +TestEnumerable(WeakMap); + + +// Test arbitrary properties on Maps and WeakMaps +function TestArbitrary(m) { + function TestProperty(map, property, value) { + map[property] = value; + assertEquals(value, map[property]); + } + for (var i = 0; i < 20; i++) { + TestProperty(m, i, 'val' + i); + TestProperty(m, 'foo' + i, 'bar' + i); + } + TestMapping(m, new Object, 'foobar'); +} +TestArbitrary(new Map); +TestArbitrary(new WeakMap); + + +// Test direct constructor call +assertTrue(Set() instanceof Set); +assertTrue(Map() instanceof Map); +assertTrue(WeakMap() instanceof WeakMap); + + +// Test whether NaN values as keys are treated correctly. +var s = new Set; +assertFalse(s.has(NaN)); +assertFalse(s.has(NaN + 1)); +assertFalse(s.has(23)); +s.add(NaN); +assertTrue(s.has(NaN)); +assertTrue(s.has(NaN + 1)); +assertFalse(s.has(23)); +var m = new Map; +assertFalse(m.has(NaN)); +assertFalse(m.has(NaN + 1)); +assertFalse(m.has(23)); +m.set(NaN, 'a-value'); +assertTrue(m.has(NaN)); +assertTrue(m.has(NaN + 1)); +assertFalse(m.has(23)); + + +// Test some common JavaScript idioms for Sets +var s = new Set; +assertTrue(s instanceof Set); +assertTrue(Set.prototype.add instanceof Function) +assertTrue(Set.prototype.has instanceof Function) +assertTrue(Set.prototype.delete instanceof Function) + + +// Test some common JavaScript idioms for Maps +var m = new Map; +assertTrue(m instanceof Map); +assertTrue(Map.prototype.set instanceof Function) +assertTrue(Map.prototype.get instanceof Function) +assertTrue(Map.prototype.has instanceof Function) +assertTrue(Map.prototype.delete instanceof Function) + + +// Test some common JavaScript idioms for WeakMaps +var m = new WeakMap; +assertTrue(m instanceof WeakMap); +assertTrue(WeakMap.prototype.set instanceof Function) +assertTrue(WeakMap.prototype.get instanceof Function) +assertTrue(WeakMap.prototype.has instanceof Function) +assertTrue(WeakMap.prototype.delete instanceof Function) + + +// Regression test for WeakMap prototype. +assertTrue(WeakMap.prototype.constructor === WeakMap) +assertTrue(Object.getPrototypeOf(WeakMap.prototype) === Object.prototype) + + +// Regression test for issue 1617: The prototype of the WeakMap constructor +// needs to be unique (i.e. different from the one of the Object constructor). +assertFalse(WeakMap.prototype === Object.prototype); +var o = Object.create({}); +assertFalse("get" in o); +assertFalse("set" in o); +assertEquals(undefined, o.get); +assertEquals(undefined, o.set); +var o = Object.create({}, { myValue: { + value: 10, + enumerable: false, + configurable: true, + writable: true +}}); +assertEquals(10, o.myValue); + + +// Regression test for issue 1884: Invoking any of the methods for Harmony +// maps, sets, or weak maps, with a wrong type of receiver should be throwing +// a proper TypeError. +var alwaysBogus = [ undefined, null, true, "x", 23, {} ]; +var bogusReceiversTestSet = [ + { proto: Set.prototype, + funcs: [ 'add', 'has', 'delete' ], + receivers: alwaysBogus.concat([ new Map, new WeakMap ]), + }, + { proto: Map.prototype, + funcs: [ 'get', 'set', 'has', 'delete' ], + receivers: alwaysBogus.concat([ new Set, new WeakMap ]), + }, + { proto: WeakMap.prototype, + funcs: [ 'get', 'set', 'has', 'delete' ], + receivers: alwaysBogus.concat([ new Set, new Map ]), + }, +]; +function TestBogusReceivers(testSet) { + for (var i = 0; i < testSet.length; i++) { + var proto = testSet[i].proto; + var funcs = testSet[i].funcs; + var receivers = testSet[i].receivers; + for (var j = 0; j < funcs.length; j++) { + var func = proto[funcs[j]]; + for (var k = 0; k < receivers.length; k++) { + assertThrows(function () { func.call(receivers[k], {}) }, TypeError); + } + } + } +} +TestBogusReceivers(bogusReceiversTestSet); + + +// Stress Test +// There is a proposed stress-test available at the es-discuss mailing list +// which cannot be reasonably automated. Check it out by hand if you like: +// https://mail.mozilla.org/pipermail/es-discuss/2011-May/014096.html
\ No newline at end of file diff --git a/test/mjsunit/harmony/debug-blockscopes.js b/test/mjsunit/harmony/debug-blockscopes.js index 0230e84b..10aac2db 100644 --- a/test/mjsunit/harmony/debug-blockscopes.js +++ b/test/mjsunit/harmony/debug-blockscopes.js @@ -25,13 +25,15 @@ // (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 --harmony-block-scoping +// Flags: --expose-debug-as debug --harmony-scoping // The functions used for testing backtraces. They are at the top to make the // testing of source line/column easier. +// TODO(ES6): properly activate extended mode +"use strict"; // Get the Debug object exposed from the debug context global object. -Debug = debug.Debug; +var Debug = debug.Debug; var test_name; var listener_delegate; @@ -76,6 +78,7 @@ function EndTest() { end_test_count++; } +var global_object = this; // Check that the scope chain contains the expected types of scopes. function CheckScopeChain(scopes, exec_state) { @@ -89,7 +92,7 @@ function CheckScopeChain(scopes, exec_state) { if (scopes[i] == debug.ScopeType.Global) { // Objects don't have same class (one is "global", other is "Object", // so just check the properties directly. - assertPropertiesEqual(this, scope.scopeObject().value()); + assertPropertiesEqual(global_object, scope.scopeObject().value()); } } @@ -329,138 +332,139 @@ local_7(1); EndTest(); -// Single empty with block. -BeginTest("With block 1"); +// Simple closure formed by returning an inner function referering to an outer +// block local variable and an outer function's parameter. +BeginTest("Closure 1"); -function with_block_1() { - with({}) { - debugger; +function closure_1(a) { + var x = 2; + let y = 3; + if (true) { + let z = 4; + function f() { + debugger; + return a + x + y + z; + }; + return f; } } listener_delegate = function(exec_state) { - CheckScopeChain([debug.ScopeType.With, - debug.ScopeType.Local, + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Block, + debug.ScopeType.Closure, debug.ScopeType.Global], exec_state); CheckScopeContent({}, 0, exec_state); - CheckScopeContent({}, 1, exec_state); + CheckScopeContent({a:1,x:2,y:3}, 2, exec_state); }; -with_block_1(); +closure_1(1)(); EndTest(); -// Nested empty with blocks. -BeginTest("With block 2"); +// Simple for-in loop over the keys of an object. +BeginTest("For loop 1"); -function with_block_2() { - with({}) { - with({}) { - debugger; - } +function for_loop_1() { + for (let x in {y:undefined}) { + debugger; } } listener_delegate = function(exec_state) { - CheckScopeChain([debug.ScopeType.With, - debug.ScopeType.With, + CheckScopeChain([debug.ScopeType.Block, debug.ScopeType.Local, debug.ScopeType.Global], exec_state); - CheckScopeContent({}, 0, exec_state); - CheckScopeContent({}, 1, exec_state); - CheckScopeContent({}, 2, exec_state); + CheckScopeContent({x:'y'}, 0, exec_state); + // The function scope contains a temporary iteration variable. + CheckScopeContent({x:'y'}, 1, exec_state); }; -with_block_2(); +for_loop_1(); EndTest(); -// With block using an in-place object literal. -BeginTest("With block 3"); +// For-in loop over the keys of an object with a block scoped let variable +// shadowing the iteration variable. +BeginTest("For loop 2"); -function with_block_3() { - with({a:1,b:2}) { +function for_loop_2() { + for (let x in {y:undefined}) { + let x = 3; debugger; } } listener_delegate = function(exec_state) { - CheckScopeChain([debug.ScopeType.With, + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Block, debug.ScopeType.Local, debug.ScopeType.Global], exec_state); - CheckScopeContent({a:1,b:2}, 0, exec_state); + CheckScopeContent({x:3}, 0, exec_state); + CheckScopeContent({x:'y'}, 1, exec_state); + // The function scope contains a temporary iteration variable. + CheckScopeContent({x:'y'}, 2, exec_state); }; -with_block_3(); +for_loop_2(); EndTest(); -// Nested with blocks using in-place object literals. -BeginTest("With block 4"); +// Simple for loop. +BeginTest("For loop 3"); -function with_block_4() { - with({a:1,b:2}) { - with({a:2,b:1}) { - debugger; - } +function for_loop_3() { + for (let x = 3; x < 4; ++x) { + debugger; } } listener_delegate = function(exec_state) { - CheckScopeChain([debug.ScopeType.With, - debug.ScopeType.With, + CheckScopeChain([debug.ScopeType.Block, debug.ScopeType.Local, debug.ScopeType.Global], exec_state); - CheckScopeContent({a:2,b:1}, 0, exec_state); - CheckScopeContent({a:1,b:2}, 1, exec_state); + CheckScopeContent({x:3}, 0, exec_state); + CheckScopeContent({}, 1, exec_state); }; -with_block_4(); +for_loop_3(); EndTest(); -// With block and a block local variable. -BeginTest("With block 5"); +// For loop with a block scoped let variable shadowing the iteration variable. +BeginTest("For loop 4"); -function with_block_5() { - with({a:1}) { - let a = 2; +function for_loop_4() { + for (let x = 3; x < 4; ++x) { + let x = 5; debugger; } } listener_delegate = function(exec_state) { CheckScopeChain([debug.ScopeType.Block, - debug.ScopeType.With, + debug.ScopeType.Block, debug.ScopeType.Local, debug.ScopeType.Global], exec_state); - CheckScopeContent({a:2}, 0, exec_state); - CheckScopeContent({a:1}, 1, exec_state); + CheckScopeContent({x:5}, 0, exec_state); + CheckScopeContent({x:3}, 1, exec_state); + CheckScopeContent({}, 2, exec_state); }; -with_block_5(); +for_loop_4(); EndTest(); -// Simple closure formed by returning an inner function referering to an outer -// block local variable and an outer function's parameter. -BeginTest("Closure 1"); +// For loop with two variable declarations. +BeginTest("For loop 5"); -function closure_1(a) { - var x = 2; - let y = 3; - if (true) { - let z = 4; - function f() { - debugger; - return a + x + y + z; - }; - return f; +function for_loop_5() { + for (let x = 3, y = 5; x < 4; ++x) { + debugger; } } listener_delegate = function(exec_state) { - CheckScopeChain([debug.ScopeType.Local, - debug.ScopeType.Block, - debug.ScopeType.Closure, + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, debug.ScopeType.Global], exec_state); - CheckScopeContent({}, 0, exec_state); - CheckScopeContent({a:1,x:2,y:3}, 2, exec_state); + CheckScopeContent({x:3,y:5}, 0, exec_state); + CheckScopeContent({}, 1, exec_state); }; -closure_1(1)(); +for_loop_5(); EndTest(); diff --git a/test/mjsunit/harmony/debug-evaluate-blockscopes.js b/test/mjsunit/harmony/debug-evaluate-blockscopes.js index 549960a2..d6ce8b2b 100644 --- a/test/mjsunit/harmony/debug-evaluate-blockscopes.js +++ b/test/mjsunit/harmony/debug-evaluate-blockscopes.js @@ -25,11 +25,17 @@ // (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 --harmony-block-scoping +// Flags: --expose-debug-as debug --harmony-scoping // Test debug evaluation for functions without local context, but with // nested catch contexts. +// TODO(ES6): properly activate extended mode +"use strict"; + +var x; +var result; + function f() { { // Line 1. let i = 1; // Line 2. @@ -42,7 +48,7 @@ function f() { }; // Get the Debug object exposed from the debug context global object. -Debug = debug.Debug +var Debug = debug.Debug // Set breakpoint on line 6. var bp = Debug.setBreakPoint(f, 6); diff --git a/test/mjsunit/harmony/module-parsing.js b/test/mjsunit/harmony/module-parsing.js new file mode 100644 index 00000000..93e69e3a --- /dev/null +++ b/test/mjsunit/harmony/module-parsing.js @@ -0,0 +1,159 @@ +// 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: --harmony-modules + +// Test basic module syntax, with and without automatic semicolon insertion. + +module A {} + +module A1 = A +module A2 = A; +module A3 = A2 + +module B { + export vx + export vy, lz, c, f + + var vx + var vx, vy; + var vx = 0, vy + let lx, ly + let lz = 1 + const c = 9 + function f() {} + + module C0 {} + + export module C { + let x + export module D { export let x } + let y + } + + let zz = "" + + export var x0 + export var x1, x2 = 6, x3 + export let y0 + export let y1 = 0, y2 + export const z0 = 0 + export const z1 = 2, z2 = 3 + export function f0() {} + export module M1 {} + export module M2 = C.D + export module M3 at "http://where" + + import i0 from I + import i1, i2, i3, M from I + import i4, i5 from "http://where" +} + +module I { + export let i0, i1, i2, i3; + export module M {} +} + +module C1 = B.C; +module D1 = B.C.D +module D2 = C1.D +module D3 = D2 + +module E1 at "http://where" +module E2 at "http://where"; +module E3 = E1.F + +// Check that ASI does not interfere. + +module X +{ +let x +} + +module Y += +X + +module Z +at +"file://local" + +import +x +, +y +from +"file://local" + + +module Wrap { +export +x +, +y + +export +var +v1 = 1 + +export +let +v2 = 2 + +export +const +v3 = 3 + +export +function +f +( +) +{ +} + +export +module V +{ +} +} + +export A, A1, A2, A3, B, I, C1, D1, D2, D3, E1, E2, E3, X, Y, Z, Wrap, x, y, UU + + + +// Check that 'module' still works as an identifier. + +var module +module = {} +module["a"] = 6 +function module() {} +function f(module) { return module } +try {} catch (module) {} + +module +v = 20 diff --git a/test/mjsunit/harmony/module-resolution.js b/test/mjsunit/harmony/module-resolution.js new file mode 100644 index 00000000..f9f492cf --- /dev/null +++ b/test/mjsunit/harmony/module-resolution.js @@ -0,0 +1,139 @@ +// 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: --harmony-modules --harmony-scoping + +// Test basic module interface inference. + +"use strict"; + +print("begin.") + +export let x = print("0") + +export module B = A.B + +export module A { + export let x = print("1") + export let f = function() { return B.x } + export module B { + module BB = B + export BB, x + let x = print("2") + let y = print("3") + let Ax = A.x + let ABx = A.B.x + let Ay = A.y + let BBx = BB.x + let Af = A.f + function f(x,y) { return x } + } + export let y = print("4") + let Ax = A.x + let Bx = B.x + let ABx = A.B.x + module C { + export let z = print("5") + export module D = B + // TODO(rossberg): turn these into proper negative test cases once we have + // suitable error messages. + // import C.z // multiple declarations + import x from B + } + module D { + // TODO(rossberg): Handle import *. + // import A.* // invalid forward import + } + module M {} + // TODO(rossberg): Handle import *. + // import M.* // invalid forward import + let Cz = C.z + let CDx = C.D.x +} + +export module Imports { + module A1 { + export module A2 {} + } + module B { + // TODO(rossberg): Handle import *. + // import A1.* + // import A2.* // unbound variable A2 + } +} + +export module E { + export let xx = x + export y, B + let Bx = B.x + // TODO(rossberg): Handle import *. + // import A.* +} + +export module M1 { + export module A2 = M2 +} +export module M2 { + export module A1 = M1 +} + +// TODO(rossberg): turn these into proper negative test cases once we have +// suitable error messages. +// module W1 = W2.W +// module W2 = { export module W = W3 } +// module W3 = W1 // cyclic module definition + +// module W1 = W2.W3 +// module W2 = { +// export module W3 = W4 +// export module W4 = W1 +// } // cyclic module definition + +// TODO(rossberg): Handle import *. +//module M3B = M3.B +//export module M3 { +// export module B { export let x = "" } +// module C1 = { import M3.* } +// module C2 = { import M3.B.* } +// module C3 = { import M3B.* } +// module C4 = { export x import B.* } +//// TODO(rossberg): turn these into proper negative test cases once we have +//// suitable error messages. +//// export module C5 = { import C5.* } // invalid forward import +//// export module C6 = { import M3.C6.* } // invalid forward import +//} + +export module External at "external.js" +export module External1 = External +export module ExternalA = External.A +export module InnerExternal { + export module E at "external.js" +} +export module External2 = InnerExternal.E +//export let xxx = InnerExternal.E.A.x + +print("end.") diff --git a/test/mjsunit/harmony/proxies-example-membrane.js b/test/mjsunit/harmony/proxies-example-membrane.js new file mode 100644 index 00000000..c6e7f9f9 --- /dev/null +++ b/test/mjsunit/harmony/proxies-example-membrane.js @@ -0,0 +1,512 @@ +// Copyright 2011 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 + + +// A simple no-op handler. Adapted from: +// http://wiki.ecmascript.org/doku.php?id=harmony:proxies#examplea_no-op_forwarding_proxy + +function createHandler(obj) { + return { + getOwnPropertyDescriptor: function(name) { + var desc = Object.getOwnPropertyDescriptor(obj, name); + if (desc !== undefined) desc.configurable = true; + return desc; + }, + getPropertyDescriptor: function(name) { + var desc = Object.getOwnPropertyDescriptor(obj, name); + //var desc = Object.getPropertyDescriptor(obj, name); // not in ES5 + if (desc !== undefined) desc.configurable = true; + return desc; + }, + getOwnPropertyNames: function() { + return Object.getOwnPropertyNames(obj); + }, + getPropertyNames: function() { + return Object.getOwnPropertyNames(obj); + //return Object.getPropertyNames(obj); // not in ES5 + }, + defineProperty: function(name, desc) { + Object.defineProperty(obj, name, desc); + }, + delete: function(name) { + return delete 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 + }, + has: function(name) { return name in obj; }, + hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); }, + get: function(receiver, name) { return obj[name]; }, + set: function(receiver, name, val) { + obj[name] = val; // bad behavior when set fails in non-strict mode + return true; + }, + enumerate: function() { + var result = []; + for (var name in obj) { result.push(name); }; + return result; + }, + keys: function() { return Object.keys(obj); } + }; +} + + + +// Auxiliary definitions enabling tracking of object identity in output. + +var objectMap = new WeakMap; +var objectCounter = 0; + +function registerObject(x, s) { + if (x === Object(x) && !objectMap.has(x)) + objectMap.set(x, ++objectCounter + (s == undefined ? "" : ":" + s)); +} + +registerObject(this, "global"); +registerObject(Object.prototype, "Object.prototype"); + +function str(x) { + if (x === Object(x)) return "[" + typeof x + " " + objectMap.get(x) + "]"; + if (typeof x == "string") return "\"" + x + "\""; + return "" + x; +} + + + +// A simple membrane. Adapted from: +// http://wiki.ecmascript.org/doku.php?id=harmony:proxies#a_simple_membrane + +function createSimpleMembrane(target) { + var enabled = true; + + function wrap(obj) { + registerObject(obj); + print("wrap enter", str(obj)); + try { + var x = wrap2(obj); + registerObject(x, "wrapped"); + print("wrap exit", str(obj), "as", str(x)); + return x; + } catch(e) { + print("wrap exception", str(e)); + throw e; + } + } + + function wrap2(obj) { + if (obj !== Object(obj)) { + return obj; + } + + function wrapCall(fun, that, args) { + registerObject(that); + print("wrapCall enter", fun, str(that)); + try { + var x = wrapCall2(fun, that, args); + print("wrapCall exit", fun, str(that), "returning", str(x)); + return x; + } catch(e) { + print("wrapCall exception", fun, str(that), str(e)); + throw e; + } + } + + function wrapCall2(fun, that, args) { + if (!enabled) { throw new Error("disabled"); } + try { + return wrap(fun.apply(that, Array.prototype.map.call(args, wrap))); + } catch (e) { + throw wrap(e); + } + } + + var baseHandler = createHandler(obj); + var handler = Proxy.create(Object.freeze({ + get: function(receiver, name) { + return function() { + var arg = (name === "get" || name == "set") ? arguments[1] : ""; + print("handler enter", name, arg); + var x = wrapCall(baseHandler[name], baseHandler, arguments); + print("handler exit", name, arg, "returning", str(x)); + return x; + } + } + })); + registerObject(baseHandler, "basehandler"); + registerObject(handler, "handler"); + + if (typeof obj === "function") { + function callTrap() { + print("call trap enter", str(obj), str(this)); + var x = wrapCall(obj, wrap(this), arguments); + print("call trap exit", str(obj), str(this), "returning", str(x)); + return x; + } + function constructTrap() { + if (!enabled) { throw new Error("disabled"); } + try { + function forward(args) { return obj.apply(this, args) } + return wrap(new forward(Array.prototype.map.call(arguments, wrap))); + } catch (e) { + throw wrap(e); + } + } + return Proxy.createFunction(handler, callTrap, constructTrap); + } else { + var prototype = wrap(Object.getPrototypeOf(obj)); + return Proxy.create(handler, prototype); + } + } + + var gate = Object.freeze({ + enable: function() { enabled = true; }, + disable: function() { enabled = false; } + }); + + return Object.freeze({ + wrapper: wrap(target), + gate: gate + }); +} + + +var o = { + a: 6, + b: {bb: 8}, + f: function(x) { return x }, + g: function(x) { return x.a }, + h: function(x) { this.q = x } +}; +o[2] = {c: 7}; +var m = createSimpleMembrane(o); +var w = m.wrapper; +print("o =", str(o)) +print("w =", str(w)); + +var f = w.f; +var x = f(66); +var x = f({a: 1}); +var x = w.f({a: 1}); +var a = x.a; +assertEquals(6, w.a); +assertEquals(8, w.b.bb); +assertEquals(7, w[2]["c"]); +assertEquals(undefined, w.c); +assertEquals(1, w.f(1)); +assertEquals(1, w.f({a: 1}).a); +assertEquals(2, w.g({a: 2})); +assertEquals(3, (w.r = {a: 3}).a); +assertEquals(3, w.r.a); +assertEquals(3, o.r.a); +w.h(3); +assertEquals(3, w.q); +assertEquals(3, o.q); +assertEquals(4, (new w.h(4)).q); + +var wb = w.b; +var wr = w.r; +var wf = w.f; +var wf3 = w.f(3); +var wfx = w.f({a: 6}); +var wgx = w.g({a: {aa: 7}}); +var wh4 = new w.h(4); +m.gate.disable(); +assertEquals(3, wf3); +assertThrows(function() { w.a }, Error); +assertThrows(function() { w.r }, Error); +assertThrows(function() { w.r = {a: 4} }, Error); +assertThrows(function() { o.r.a }, Error); +assertEquals("object", typeof o.r); +assertEquals(5, (o.r = {a: 5}).a); +assertEquals(5, o.r.a); +assertThrows(function() { w[1] }, Error); +assertThrows(function() { w.c }, Error); +assertThrows(function() { wb.bb }, Error); +assertThrows(function() { wr.a }, Error); +assertThrows(function() { wf(4) }, Error); +assertThrows(function() { wfx.a }, Error); +assertThrows(function() { wgx.aa }, Error); +assertThrows(function() { wh4.q }, Error); + +m.gate.enable(); +assertEquals(6, w.a); +assertEquals(5, w.r.a); +assertEquals(5, o.r.a); +assertEquals(7, w.r = 7); +assertEquals(7, w.r); +assertEquals(7, o.r); +assertEquals(8, w.b.bb); +assertEquals(7, w[2]["c"]); +assertEquals(undefined, w.c); +assertEquals(8, wb.bb); +assertEquals(3, wr.a); +assertEquals(4, wf(4)); +assertEquals(3, wf3); +assertEquals(6, wfx.a); +assertEquals(7, wgx.aa); +assertEquals(4, wh4.q); + + +// An identity-preserving membrane. Adapted from: +// http://wiki.ecmascript.org/doku.php?id=harmony:proxies#an_identity-preserving_membrane + +function createMembrane(wetTarget) { + var wet2dry = WeakMap(); + var dry2wet = WeakMap(); + + function asDry(obj) { + registerObject(obj) + print("asDry enter", str(obj)) + try { + var x = asDry2(obj); + registerObject(x, "dry"); + print("asDry exit", str(obj), "as", str(x)); + return x; + } catch(e) { + print("asDry exception", str(e)); + throw e; + } + } + function asDry2(wet) { + if (wet !== Object(wet)) { + // primitives provide only irrevocable knowledge, so don't + // bother wrapping it. + return wet; + } + var dryResult = wet2dry.get(wet); + if (dryResult) { return dryResult; } + + var wetHandler = createHandler(wet); + var dryRevokeHandler = Proxy.create(Object.freeze({ + get: function(receiver, name) { + return function() { + var arg = (name === "get" || name == "set") ? arguments[1] : ""; + print("dry handler enter", name, arg); + var optWetHandler = dry2wet.get(dryRevokeHandler); + try { + var x = asDry(optWetHandler[name].apply( + optWetHandler, Array.prototype.map.call(arguments, asWet))); + print("dry handler exit", name, arg, "returning", str(x)); + return x; + } catch (eWet) { + var x = asDry(eWet); + print("dry handler exception", name, arg, "throwing", str(x)); + throw x; + } + }; + } + })); + dry2wet.set(dryRevokeHandler, wetHandler); + + if (typeof wet === "function") { + function callTrap() { + print("dry call trap enter", str(this)); + var x = asDry(wet.apply( + asWet(this), Array.prototype.map.call(arguments, asWet))); + print("dry call trap exit", str(this), "returning", str(x)); + return x; + } + function constructTrap() { + function forward(args) { return wet.apply(this, args) } + return asDry(new forward(Array.prototype.map.call(arguments, asWet))); + } + dryResult = + Proxy.createFunction(dryRevokeHandler, callTrap, constructTrap); + } else { + dryResult = + Proxy.create(dryRevokeHandler, asDry(Object.getPrototypeOf(wet))); + } + wet2dry.set(wet, dryResult); + dry2wet.set(dryResult, wet); + return dryResult; + } + + function asWet(obj) { + registerObject(obj) + print("asWet enter", str(obj)) + try { + var x = asWet2(obj) + registerObject(x, "wet") + print("asWet exit", str(obj), "as", str(x)) + return x + } catch(e) { + print("asWet exception", str(e)) + throw e + } + } + function asWet2(dry) { + if (dry !== Object(dry)) { + // primitives provide only irrevocable knowledge, so don't + // bother wrapping it. + return dry; + } + var wetResult = dry2wet.get(dry); + if (wetResult) { return wetResult; } + + var dryHandler = createHandler(dry); + var wetRevokeHandler = Proxy.create(Object.freeze({ + get: function(receiver, name) { + return function() { + var arg = (name === "get" || name == "set") ? arguments[1] : ""; + print("wet handler enter", name, arg); + var optDryHandler = wet2dry.get(wetRevokeHandler); + try { + var x = asWet(optDryHandler[name].apply( + optDryHandler, Array.prototype.map.call(arguments, asDry))); + print("wet handler exit", name, arg, "returning", str(x)); + return x; + } catch (eDry) { + var x = asWet(eDry); + print("wet handler exception", name, arg, "throwing", str(x)); + throw x; + } + }; + } + })); + wet2dry.set(wetRevokeHandler, dryHandler); + + if (typeof dry === "function") { + function callTrap() { + print("wet call trap enter", str(this)); + var x = asWet(dry.apply( + asDry(this), Array.prototype.map.call(arguments, asDry))); + print("wet call trap exit", str(this), "returning", str(x)); + return x; + } + function constructTrap() { + function forward(args) { return dry.apply(this, args) } + return asWet(new forward(Array.prototype.map.call(arguments, asDry))); + } + wetResult = + Proxy.createFunction(wetRevokeHandler, callTrap, constructTrap); + } else { + wetResult = + Proxy.create(wetRevokeHandler, asWet(Object.getPrototypeOf(dry))); + } + dry2wet.set(dry, wetResult); + wet2dry.set(wetResult, dry); + return wetResult; + } + + var gate = Object.freeze({ + revoke: function() { + dry2wet = wet2dry = Object.freeze({ + get: function(key) { throw new Error("revoked"); }, + set: function(key, val) { throw new Error("revoked"); } + }); + } + }); + + return Object.freeze({ wrapper: asDry(wetTarget), gate: gate }); +} + + +var receiver +var argument +var o = { + a: 6, + b: {bb: 8}, + f: function(x) { receiver = this; argument = x; return x }, + g: function(x) { receiver = this; argument = x; return x.a }, + h: function(x) { receiver = this; argument = x; this.q = x }, + s: function(x) { receiver = this; argument = x; this.x = {y: x}; return this } +} +o[2] = {c: 7} +var m = createMembrane(o) +var w = m.wrapper +print("o =", str(o)) +print("w =", str(w)) + +var f = w.f +var x = f(66) +var x = f({a: 1}) +var x = w.f({a: 1}) +var a = x.a +assertEquals(6, w.a) +assertEquals(8, w.b.bb) +assertEquals(7, w[2]["c"]) +assertEquals(undefined, w.c) +assertEquals(1, w.f(1)) +assertSame(o, receiver) +assertEquals(1, w.f({a: 1}).a) +assertSame(o, receiver) +assertEquals(2, w.g({a: 2})) +assertSame(o, receiver) +assertSame(w, w.f(w)) +assertSame(o, receiver) +assertSame(o, argument) +assertSame(o, w.f(o)) +assertSame(o, receiver) +// Note that argument !== o, since o isn't dry, so gets wrapped wet again. +assertEquals(3, (w.r = {a: 3}).a) +assertEquals(3, w.r.a) +assertEquals(3, o.r.a) +w.h(3) +assertEquals(3, w.q) +assertEquals(3, o.q) +assertEquals(4, (new w.h(4)).q) +assertEquals(5, w.s(5).x.y) +assertSame(o, receiver) + +var wb = w.b +var wr = w.r +var wf = w.f +var wf3 = w.f(3) +var wfx = w.f({a: 6}) +var wgx = w.g({a: {aa: 7}}) +var wh4 = new w.h(4) +var ws5 = w.s(5) +var ws5x = ws5.x +m.gate.revoke() +assertEquals(3, wf3) +assertThrows(function() { w.a }, Error) +assertThrows(function() { w.r }, Error) +assertThrows(function() { w.r = {a: 4} }, Error) +assertThrows(function() { o.r.a }, Error) +assertEquals("object", typeof o.r) +assertEquals(5, (o.r = {a: 5}).a) +assertEquals(5, o.r.a) +assertThrows(function() { w[1] }, Error) +assertThrows(function() { w.c }, Error) +assertThrows(function() { wb.bb }, Error) +assertEquals(3, wr.a) +assertThrows(function() { wf(4) }, Error) +assertEquals(6, wfx.a) +assertEquals(7, wgx.aa) +assertThrows(function() { wh4.q }, Error) +assertThrows(function() { ws5.x }, Error) +assertThrows(function() { ws5x.y }, Error) diff --git a/test/mjsunit/harmony/proxies-for.js b/test/mjsunit/harmony/proxies-for.js new file mode 100644 index 00000000..3d419c6d --- /dev/null +++ b/test/mjsunit/harmony/proxies-for.js @@ -0,0 +1,168 @@ +// Copyright 2011 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-proxies + + +// Helper. + +function TestWithProxies(test, x, y, z) { + test(Proxy.create, x, y, z) + test(function(h) {return Proxy.createFunction(h, function() {})}, x, y, z) +} + + +// Iterate over a proxy. + +function TestForIn(properties, handler) { + TestWithProxies(TestForIn2, properties, handler) +} + +function TestForIn2(create, properties, handler) { + var p = create(handler) + var found = [] + for (var x in p) found.push(x) + assertArrayEquals(properties, found) +} + +TestForIn(["0", "a"], { + enumerate: function() { return [0, "a"] } +}) + +TestForIn(["null", "a"], { + enumerate: function() { return this.enumerate2() }, + enumerate2: function() { return [null, "a"] } +}) + +TestForIn(["b", "d"], { + getPropertyNames: function() { return ["a", "b", "c", "d", "e"] }, + getPropertyDescriptor: function(k) { + switch (k) { + case "a": return {enumerable: false, value: "3"}; + case "b": return {enumerable: true, get get() {}}; + case "c": return {value: 4}; + case "d": return {get enumerable() { return true }}; + default: return undefined; + } + } +}) + +TestForIn(["b", "a", "0", "c"], Proxy.create({ + get: function(pr, pk) { + return function() { return ["b", "a", 0, "c"] } + } +})) + + + +// Iterate over an object with a proxy prototype. + +function TestForInDerived(properties, handler) { + TestWithProxies(TestForInDerived2, properties, handler) +} + +function TestForInDerived2(create, properties, handler) { + var p = create(handler) + var o = Object.create(p) + o.z = 0 + var found = [] + for (var x in o) found.push(x) + assertArrayEquals(["z"].concat(properties), found) + + var oo = Object.create(o) + oo.y = 0 + var found = [] + for (var x in oo) found.push(x) + assertArrayEquals(["y", "z"].concat(properties), found) +} + +TestForInDerived(["0", "a"], { + enumerate: function() { return [0, "a"] }, + getPropertyDescriptor: function(k) { + return k == "0" || k == "a" ? {} : undefined + } +}) + +TestForInDerived(["null", "a"], { + enumerate: function() { return this.enumerate2() }, + enumerate2: function() { return [null, "a"] }, + getPropertyDescriptor: function(k) { + return k == "null" || k == "a" ? {} : undefined + } +}) + +TestForInDerived(["b", "d"], { + getPropertyNames: function() { return ["a", "b", "c", "d", "e"] }, + getPropertyDescriptor: function(k) { + switch (k) { + case "a": return {enumerable: false, value: "3"}; + case "b": return {enumerable: true, get get() {}}; + case "c": return {value: 4}; + case "d": return {get enumerable() { return true }}; + default: return undefined; + } + } +}) + + + +// Throw exception in enumerate trap. + +function TestForInThrow(handler) { + TestWithProxies(TestForInThrow2, handler) +} + +function TestForInThrow2(create, handler) { + var p = create(handler) + var o = Object.create(p) + assertThrows(function(){ for (var x in p) {} }, "myexn") + assertThrows(function(){ for (var x in o) {} }, "myexn") +} + +TestForInThrow({ + enumerate: function() { throw "myexn" } +}) + +TestForInThrow({ + enumerate: function() { return this.enumerate2() }, + enumerate2: function() { throw "myexn" } +}) + +TestForInThrow({ + getPropertyNames: function() { throw "myexn" } +}) + +TestForInThrow({ + getPropertyNames: function() { return ["a"] }, + getPropertyDescriptor: function() { throw "myexn" } +}) + +TestForInThrow(Proxy.create({ + get: function(pr, pk) { + return function() { throw "myexn" } + } +})) diff --git a/test/mjsunit/harmony/proxies-function.js b/test/mjsunit/harmony/proxies-function.js new file mode 100644 index 00000000..6b8d0984 --- /dev/null +++ b/test/mjsunit/harmony/proxies-function.js @@ -0,0 +1,748 @@ +// Copyright 2011 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-proxies --allow-natives-syntax + + +// Helper. + +function CreateFrozen(handler, callTrap, constructTrap) { + if (handler.fix === undefined) handler.fix = function() { return {} } + var f = Proxy.createFunction(handler, callTrap, constructTrap) + Object.freeze(f) + return f +} + + +// Ensures that checking the "length" property of a function proxy doesn't +// crash due to lack of a [[Get]] method. +var handler = { + get : function(r, n) { return n == "length" ? 2 : undefined } +} + + +// Calling (call, Function.prototype.call, Function.prototype.apply, +// Function.prototype.bind). + +var global_object = this +var receiver + +function TestCall(isStrict, callTrap) { + assertEquals(42, callTrap(5, 37)) + // TODO(rossberg): strict mode seems to be broken on x64... + // assertSame(isStrict ? undefined : global_object, receiver) + + var handler = { + get: function(r, k) { + return k == "length" ? 2 : Function.prototype[k] + } + } + var f = Proxy.createFunction(handler, callTrap) + var o = {f: f} + global_object.f = f + + receiver = 333 + assertEquals(42, f(11, 31)) + // TODO(rossberg): strict mode seems to be broken on x64... + // assertSame(isStrict ? undefined : global_object, receiver) + receiver = 333 + assertEquals(42, o.f(10, 32)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, o["f"](9, 33)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, (1, o).f(8, 34)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, (1, o)["f"](7, 35)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, f.call(o, 32, 10)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, f.call(undefined, 33, 9)) + assertSame(isStrict ? undefined : global_object, receiver) + receiver = 333 + assertEquals(42, f.call(null, 33, 9)) + assertSame(isStrict ? null : global_object, receiver) + receiver = 333 + assertEquals(44, f.call(2, 21, 23)) + assertSame(2, receiver.valueOf()) + receiver = 333 + assertEquals(42, Function.prototype.call.call(f, o, 20, 22)) + assertSame(o, receiver) + receiver = 333 + assertEquals(43, Function.prototype.call.call(f, null, 20, 23)) + assertSame(isStrict ? null : global_object, receiver) + assertEquals(44, Function.prototype.call.call(f, 2, 21, 23)) + assertEquals(2, receiver.valueOf()) + receiver = 333 + assertEquals(32, f.apply(o, [16, 16])) + assertSame(o, receiver) + receiver = 333 + assertEquals(32, Function.prototype.apply.call(f, o, [17, 15])) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Call(o, 11, 31, f)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Call(null, 11, 31, f)) + assertSame(isStrict ? null : global_object, receiver) + receiver = 333 + assertEquals(42, %Apply(f, o, [11, 31], 0, 2)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Apply(f, null, [11, 31], 0, 2)) + assertSame(isStrict ? null : global_object, receiver) + receiver = 333 + assertEquals(42, %_CallFunction(o, 11, 31, f)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %_CallFunction(null, 11, 31, f)) + assertSame(isStrict ? null : global_object, receiver) + + var ff = Function.prototype.bind.call(f, o, 12) + assertTrue(ff.length <= 1) // TODO(rossberg): Not spec'ed yet, be lax. + receiver = 333 + assertEquals(42, ff(30)) + assertSame(o, receiver) + receiver = 333 + assertEquals(33, Function.prototype.call.call(ff, {}, 21)) + assertSame(o, receiver) + receiver = 333 + assertEquals(32, Function.prototype.apply.call(ff, {}, [20])) + assertSame(o, receiver) + receiver = 333 + assertEquals(23, %Call({}, 11, ff)) + assertSame(o, receiver) + receiver = 333 + assertEquals(23, %Call({}, 11, 3, ff)) + assertSame(o, receiver) + receiver = 333 + assertEquals(24, %Apply(ff, {}, [12, 13], 0, 1)) + assertSame(o, receiver) + receiver = 333 + assertEquals(24, %Apply(ff, {}, [12, 13], 0, 2)) + assertSame(o, receiver) + receiver = 333 + assertEquals(34, %_CallFunction({}, 22, ff)) + assertSame(o, receiver) + receiver = 333 + assertEquals(34, %_CallFunction({}, 22, 3, ff)) + assertSame(o, receiver) + + var fff = Function.prototype.bind.call(ff, o, 30) + assertEquals(0, fff.length) + receiver = 333 + assertEquals(42, fff()) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, Function.prototype.call.call(fff, {})) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, Function.prototype.apply.call(fff, {})) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Call({}, fff)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Call({}, 11, 3, fff)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Apply(fff, {}, [], 0, 0)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Apply(fff, {}, [12, 13], 0, 0)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %Apply(fff, {}, [12, 13], 0, 2)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %_CallFunction({}, fff)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %_CallFunction({}, 3, 4, 5, fff)) + assertSame(o, receiver) + + var f = CreateFrozen({}, callTrap) + receiver = 333 + assertEquals(42, f(11, 31)) + assertSame(isStrict ? undefined : global_object, receiver) + var o = {f: f} + receiver = 333 + assertEquals(42, o.f(10, 32)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, o["f"](9, 33)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, (1, o).f(8, 34)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, (1, o)["f"](7, 35)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, Function.prototype.call.call(f, o, 20, 22)) + assertSame(o, receiver) + receiver = 333 + assertEquals(32, Function.prototype.apply.call(f, o, [17, 15])) + assertSame(o, receiver) + receiver = 333 + assertEquals(23, %Call(o, 11, 12, f)) + assertSame(o, receiver) + receiver = 333 + assertEquals(27, %Apply(f, o, [12, 13, 14], 1, 2)) + assertSame(o, receiver) + receiver = 333 + assertEquals(42, %_CallFunction(o, 18, 24, f)) + assertSame(o, receiver) +} + +TestCall(false, function(x, y) { + receiver = this + return x + y +}) + +TestCall(true, function(x, y) { + "use strict" + receiver = this + return x + y +}) + +TestCall(false, function() { + receiver = this + return arguments[0] + arguments[1] +}) + +TestCall(false, Proxy.createFunction(handler, function(x, y) { + receiver = this + return x + y +})) + +TestCall(true, Proxy.createFunction(handler, function(x, y) { + "use strict" + receiver = this + return x + y +})) + +TestCall(false, CreateFrozen(handler, function(x, y) { + receiver = this + return x + y +})) + + + +// Using intrinsics as call traps. + +function TestCallIntrinsic(type, callTrap) { + var f = Proxy.createFunction({}, callTrap) + var x = f() + assertTrue(typeof x == type) +} + +TestCallIntrinsic("boolean", Boolean) +TestCallIntrinsic("number", Number) +TestCallIntrinsic("string", String) +TestCallIntrinsic("object", Object) +TestCallIntrinsic("function", Function) + + + +// Throwing from call trap. + +function TestCallThrow(callTrap) { + var f = Proxy.createFunction({}, callTrap) + assertThrows(function(){ f(11) }, "myexn") + assertThrows(function(){ ({x: f}).x(11) }, "myexn") + assertThrows(function(){ ({x: f})["x"](11) }, "myexn") + assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn") + assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn") + assertThrows(function(){ %Call({}, f) }, "myexn") + assertThrows(function(){ %Call({}, 1, 2, f) }, "myexn") + assertThrows(function(){ %Apply({}, f, [], 3, 0) }, "myexn") + assertThrows(function(){ %Apply({}, f, [3, 4], 0, 1) }, "myexn") + assertThrows(function(){ %_CallFunction({}, f) }, "myexn") + assertThrows(function(){ %_CallFunction({}, 1, 2, f) }, "myexn") + + var f = CreateFrozen({}, callTrap) + assertThrows(function(){ f(11) }, "myexn") + assertThrows(function(){ ({x: f}).x(11) }, "myexn") + assertThrows(function(){ ({x: f})["x"](11) }, "myexn") + assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn") + assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn") + assertThrows(function(){ %Call({}, f) }, "myexn") + assertThrows(function(){ %Call({}, 1, 2, f) }, "myexn") + assertThrows(function(){ %Apply({}, f, [], 3, 0) }, "myexn") + assertThrows(function(){ %Apply({}, f, [3, 4], 0, 1) }, "myexn") + assertThrows(function(){ %_CallFunction({}, f) }, "myexn") + assertThrows(function(){ %_CallFunction({}, 1, 2, f) }, "myexn") +} + +TestCallThrow(function() { throw "myexn" }) +TestCallThrow(Proxy.createFunction({}, function() { throw "myexn" })) +TestCallThrow(CreateFrozen({}, function() { throw "myexn" })) + + + +// Construction (new). + +var prototype = {myprop: 0} +var receiver + +var handlerWithPrototype = { + fix: function() { return { prototype: { value: prototype } }; }, + get: function(r, n) { + if (n == "length") return 2; + assertEquals("prototype", n); + return prototype; + } +} + +var handlerSansPrototype = { + fix: function() { return { length: { value: 2 } } }, + get: function(r, n) { + if (n == "length") return 2; + assertEquals("prototype", n); + return undefined; + } +} + +function ReturnUndef(x, y) { + "use strict"; + receiver = this; + this.sum = x + y; +} + +function ReturnThis(x, y) { + "use strict"; + receiver = this; + this.sum = x + y; + return this; +} + +function ReturnNew(x, y) { + "use strict"; + receiver = this; + return {sum: x + y}; +} + +function ReturnNewWithProto(x, y) { + "use strict"; + receiver = this; + var result = Object.create(prototype); + result.sum = x + y; + return result; +} + +function TestConstruct(proto, constructTrap) { + TestConstruct2(proto, constructTrap, handlerWithPrototype) + TestConstruct2(proto, constructTrap, handlerSansPrototype) +} + +function TestConstruct2(proto, constructTrap, handler) { + var f = Proxy.createFunction(handler, function() {}, constructTrap) + var o = new f(11, 31) + assertEquals(undefined, receiver) + assertEquals(42, o.sum) + assertSame(proto, Object.getPrototypeOf(o)) + + var f = CreateFrozen(handler, function() {}, constructTrap) + var o = new f(11, 32) + assertEquals(undefined, receiver) + assertEquals(43, o.sum) + assertSame(proto, Object.getPrototypeOf(o)) +} + +TestConstruct(Object.prototype, ReturnNew) +TestConstruct(prototype, ReturnNewWithProto) + +TestConstruct(Object.prototype, Proxy.createFunction(handler, ReturnNew)) +TestConstruct(prototype, Proxy.createFunction(handler, ReturnNewWithProto)) + +TestConstruct(Object.prototype, CreateFrozen(handler, ReturnNew)) +TestConstruct(prototype, CreateFrozen(handler, ReturnNewWithProto)) + + + +// Construction with derived construct trap. + +function TestConstructFromCall(proto, returnsThis, callTrap) { + TestConstructFromCall2(prototype, returnsThis, callTrap, handlerWithPrototype) + TestConstructFromCall2(proto, returnsThis, callTrap, handlerSansPrototype) +} + +function TestConstructFromCall2(proto, returnsThis, callTrap, handler) { + // TODO(rossberg): handling of prototype for derived construct trap will be + // fixed in a separate change. Commenting out checks below for now. + var f = Proxy.createFunction(handler, callTrap) + var o = new f(11, 31) + if (returnsThis) assertEquals(o, receiver) + assertEquals(42, o.sum) + // assertSame(proto, Object.getPrototypeOf(o)) + + var g = CreateFrozen(handler, callTrap) + // assertSame(f.prototype, g.prototype) + var o = new g(11, 32) + if (returnsThis) assertEquals(o, receiver) + assertEquals(43, o.sum) + // assertSame(proto, Object.getPrototypeOf(o)) +} + +TestConstructFromCall(Object.prototype, true, ReturnUndef) +TestConstructFromCall(Object.prototype, true, ReturnThis) +TestConstructFromCall(Object.prototype, false, ReturnNew) +TestConstructFromCall(prototype, false, ReturnNewWithProto) + +TestConstructFromCall(Object.prototype, true, + Proxy.createFunction(handler, ReturnUndef)) +TestConstructFromCall(Object.prototype, true, + Proxy.createFunction(handler, ReturnThis)) +TestConstructFromCall(Object.prototype, false, + Proxy.createFunction(handler, ReturnNew)) +TestConstructFromCall(prototype, false, + Proxy.createFunction(handler, ReturnNewWithProto)) + +TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnUndef)) +TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnThis)) +TestConstructFromCall(Object.prototype, false, CreateFrozen({}, ReturnNew)) +TestConstructFromCall(prototype, false, CreateFrozen({}, ReturnNewWithProto)) + +ReturnUndef.prototype = prototype +ReturnThis.prototype = prototype +ReturnNew.prototype = prototype +ReturnNewWithProto.prototype = prototype + +TestConstructFromCall(prototype, true, ReturnUndef) +TestConstructFromCall(prototype, true, ReturnThis) +TestConstructFromCall(Object.prototype, false, ReturnNew) +TestConstructFromCall(prototype, false, ReturnNewWithProto) + +TestConstructFromCall(Object.prototype, true, + Proxy.createFunction(handler, ReturnUndef)) +TestConstructFromCall(Object.prototype, true, + Proxy.createFunction(handler, ReturnThis)) +TestConstructFromCall(Object.prototype, false, + Proxy.createFunction(handler, ReturnNew)) +TestConstructFromCall(prototype, false, + Proxy.createFunction(handler, ReturnNewWithProto)) + +TestConstructFromCall(prototype, true, + Proxy.createFunction(handlerWithPrototype, ReturnUndef)) +TestConstructFromCall(prototype, true, + Proxy.createFunction(handlerWithPrototype, ReturnThis)) +TestConstructFromCall(Object.prototype, false, + Proxy.createFunction(handlerWithPrototype, ReturnNew)) +TestConstructFromCall(prototype, false, + Proxy.createFunction(handlerWithPrototype, + ReturnNewWithProto)) + +TestConstructFromCall(prototype, true, + CreateFrozen(handlerWithPrototype, ReturnUndef)) +TestConstructFromCall(prototype, true, + CreateFrozen(handlerWithPrototype, ReturnThis)) +TestConstructFromCall(Object.prototype, false, + CreateFrozen(handlerWithPrototype, ReturnNew)) +TestConstructFromCall(prototype, false, + CreateFrozen(handlerWithPrototype, ReturnNewWithProto)) + + + +// Throwing from the construct trap. + +function TestConstructThrow(trap) { + TestConstructThrow2(Proxy.createFunction({ fix: function() {return {};} }, + trap)) + TestConstructThrow2(Proxy.createFunction({ fix: function() {return {};} }, + function() {}, + trap)) +} + +function TestConstructThrow2(f) { + assertThrows(function(){ new f(11) }, "myexn") + Object.freeze(f) + assertThrows(function(){ new f(11) }, "myexn") +} + +TestConstructThrow(function() { throw "myexn" }) +TestConstructThrow(Proxy.createFunction({}, function() { throw "myexn" })) +TestConstructThrow(CreateFrozen({}, function() { throw "myexn" })) + + + +// Using function proxies as getters and setters. + +var value +var receiver + +function TestAccessorCall(getterCallTrap, setterCallTrap) { + var handler = { fix: function() { return {} } } + var pgetter = Proxy.createFunction(handler, getterCallTrap) + var psetter = Proxy.createFunction(handler, setterCallTrap) + + var o = {} + var oo = Object.create(o) + Object.defineProperty(o, "a", {get: pgetter, set: psetter}) + Object.defineProperty(o, "b", {get: pgetter}) + Object.defineProperty(o, "c", {set: psetter}) + Object.defineProperty(o, "3", {get: pgetter, set: psetter}) + Object.defineProperty(oo, "a", {value: 43}) + + receiver = "" + assertEquals(42, o.a) + assertSame(o, receiver) + receiver = "" + assertEquals(42, o.b) + assertSame(o, receiver) + receiver = "" + assertEquals(undefined, o.c) + assertEquals("", receiver) + receiver = "" + assertEquals(42, o["a"]) + assertSame(o, receiver) + receiver = "" + assertEquals(42, o[3]) + assertSame(o, receiver) + + receiver = "" + assertEquals(43, oo.a) + assertEquals("", receiver) + receiver = "" + assertEquals(42, oo.b) + assertSame(oo, receiver) + receiver = "" + assertEquals(undefined, oo.c) + assertEquals("", receiver) + receiver = "" + assertEquals(43, oo["a"]) + assertEquals("", receiver) + receiver = "" + assertEquals(42, oo[3]) + assertSame(oo, receiver) + + receiver = "" + assertEquals(50, o.a = 50) + assertSame(o, receiver) + assertEquals(50, value) + receiver = "" + assertEquals(51, o.b = 51) + assertEquals("", receiver) + assertEquals(50, value) // no setter + assertThrows(function() { "use strict"; o.b = 51 }, TypeError) + receiver = "" + assertEquals(52, o.c = 52) + assertSame(o, receiver) + assertEquals(52, value) + receiver = "" + assertEquals(53, o["a"] = 53) + assertSame(o, receiver) + assertEquals(53, value) + receiver = "" + assertEquals(54, o[3] = 54) + assertSame(o, receiver) + assertEquals(54, value) + + value = 0 + receiver = "" + assertEquals(60, oo.a = 60) + assertEquals("", receiver) + assertEquals(0, value) // oo has own 'a' + assertEquals(61, oo.b = 61) + assertSame("", receiver) + assertEquals(0, value) // no setter + assertThrows(function() { "use strict"; oo.b = 61 }, TypeError) + receiver = "" + assertEquals(62, oo.c = 62) + assertSame(oo, receiver) + assertEquals(62, value) + receiver = "" + assertEquals(63, oo["c"] = 63) + assertSame(oo, receiver) + assertEquals(63, value) + receiver = "" + assertEquals(64, oo[3] = 64) + assertSame(oo, receiver) + assertEquals(64, value) +} + +TestAccessorCall( + function() { receiver = this; return 42 }, + function(x) { receiver = this; value = x } +) + +TestAccessorCall( + function() { "use strict"; receiver = this; return 42 }, + function(x) { "use strict"; receiver = this; value = x } +) + +TestAccessorCall( + Proxy.createFunction({}, function() { receiver = this; return 42 }), + Proxy.createFunction({}, function(x) { receiver = this; value = x }) +) + +TestAccessorCall( + CreateFrozen({}, function() { receiver = this; return 42 }), + CreateFrozen({}, function(x) { receiver = this; value = x }) +) + + + +// Passing a proxy function to higher-order library functions. + +function TestHigherOrder(f) { + assertEquals(6, [6, 2].map(f)[0]) + assertEquals(4, [5, 2].reduce(f, 4)) + assertTrue([1, 2].some(f)) + assertEquals("a.b.c", "a.b.c".replace(".", f)) +} + +TestHigherOrder(function(x) { return x }) +TestHigherOrder(function(x) { "use strict"; return x }) +TestHigherOrder(Proxy.createFunction({}, function(x) { return x })) +TestHigherOrder(CreateFrozen({}, function(x) { return x })) + + + +// TODO(rossberg): Ultimately, I want to have the following test function +// run through, but it currently fails on so many cases (some not even +// involving proxies), that I leave that for later... +/* +function TestCalls() { + var handler = { + get: function(r, k) { + return k == "length" ? 2 : Function.prototype[k] + } + } + var bind = Function.prototype.bind + var o = {} + + var traps = [ + function(x, y) { + return {receiver: this, result: x + y, strict: false} + }, + function(x, y) { "use strict"; + return {receiver: this, result: x + y, strict: true} + }, + function() { + var x = arguments[0], y = arguments[1] + return {receiver: this, result: x + y, strict: false} + }, + Proxy.createFunction(handler, function(x, y) { + return {receiver: this, result: x + y, strict: false} + }), + Proxy.createFunction(handler, function() { + var x = arguments[0], y = arguments[1] + return {receiver: this, result: x + y, strict: false} + }), + Proxy.createFunction(handler, function(x, y) { "use strict" + return {receiver: this, result: x + y, strict: true} + }), + CreateFrozen(handler, function(x, y) { + return {receiver: this, result: x + y, strict: false} + }), + CreateFrozen(handler, function(x, y) { "use strict" + return {receiver: this, result: x + y, strict: true} + }), + ] + var creates = [ + function(trap) { return trap }, + function(trap) { return CreateFrozen({}, callTrap) }, + function(trap) { return Proxy.createFunction(handler, callTrap) }, + function(trap) { + return Proxy.createFunction(handler, CreateFrozen({}, callTrap)) + }, + function(trap) { + return Proxy.createFunction(handler, Proxy.createFunction(handler, callTrap)) + }, + ] + var binds = [ + function(f, o, x, y) { return f }, + function(f, o, x, y) { return bind.call(f, o) }, + function(f, o, x, y) { return bind.call(f, o, x) }, + function(f, o, x, y) { return bind.call(f, o, x, y) }, + function(f, o, x, y) { return bind.call(f, o, x, y, 5) }, + function(f, o, x, y) { return bind.call(bind.call(f, o), {}, x, y) }, + function(f, o, x, y) { return bind.call(bind.call(f, o, x), {}, y) }, + function(f, o, x, y) { return bind.call(bind.call(f, o, x, y), {}, 5) }, + ] + var calls = [ + function(f, x, y) { return f(x, y) }, + function(f, x, y) { var g = f; return g(x, y) }, + function(f, x, y) { with ({}) return f(x, y) }, + function(f, x, y) { var g = f; with ({}) return g(x, y) }, + function(f, x, y, o) { with (o) return f(x, y) }, + function(f, x, y, o) { return f.call(o, x, y) }, + function(f, x, y, o) { return f.apply(o, [x, y]) }, + function(f, x, y, o) { return Function.prototype.call.call(f, o, x, y) }, + function(f, x, y, o) { return Function.prototype.apply.call(f, o, [x, y]) }, + function(f, x, y, o) { return %_CallFunction(o, x, y, f) }, + function(f, x, y, o) { return %Call(o, x, y, f) }, + function(f, x, y, o) { return %Apply(f, o, [null, x, y, null], 1, 2) }, + function(f, x, y, o) { return %Apply(f, o, arguments, 2, 2) }, + function(f, x, y, o) { if (typeof o == "object") return o.f(x, y) }, + function(f, x, y, o) { if (typeof o == "object") return o["f"](x, y) }, + function(f, x, y, o) { if (typeof o == "object") return (1, o).f(x, y) }, + function(f, x, y, o) { if (typeof o == "object") return (1, o)["f"](x, y) }, + ] + var receivers = [o, global_object, undefined, null, 2, "bla", true] + var expectedNonStricts = [o, global_object, global_object, global_object] + + for (var t = 0; t < traps.length; ++t) { + for (var i = 0; i < creates.length; ++i) { + for (var j = 0; j < binds.length; ++j) { + for (var k = 0; k < calls.length; ++k) { + for (var m = 0; m < receivers.length; ++m) { + for (var n = 0; n < receivers.length; ++n) { + var bound = receivers[m] + var receiver = receivers[n] + var func = binds[j](creates[i](traps[t]), bound, 31, 11) + var expected = j > 0 ? bound : receiver + var expectedNonStrict = expectedNonStricts[j > 0 ? m : n] + o.f = func + global_object.f = func + var x = calls[k](func, 11, 31, receiver) + if (x !== undefined) { + assertEquals(42, x.result) + if (calls[k].length < 4) + assertSame(x.strict ? undefined : global_object, x.receiver) + else if (x.strict) + assertSame(expected, x.receiver) + else if (expectedNonStrict === undefined) + assertSame(expected, x.receiver.valueOf()) + else + assertSame(expectedNonStrict, x.receiver) + } + } + } + } + } + } + } +} + +TestCalls() +*/ diff --git a/test/mjsunit/harmony/proxies-hash.js b/test/mjsunit/harmony/proxies-hash.js new file mode 100644 index 00000000..abfc0f5f --- /dev/null +++ b/test/mjsunit/harmony/proxies-hash.js @@ -0,0 +1,122 @@ +// Copyright 2011 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-proxies --harmony-collections + + +// Helper. + +function TestWithProxies(test, construct, handler) { + test(construct, handler, Proxy.create) + test(construct, handler, function(h) { + return Proxy.createFunction(h, function() {}) + }) +} + + +// Sets. + +function TestSet(construct, fix) { + TestWithProxies(TestSet2, construct, fix) +} + +function TestSet2(construct, fix, create) { + var handler = {fix: function() { return {} }} + var p1 = create(handler) + var p2 = create(handler) + var p3 = create(handler) + fix(p3) + + var s = construct(); + s.add(p1); + s.add(p2); + assertTrue(s.has(p1)); + assertTrue(s.has(p2)); + assertFalse(s.has(p3)); + + fix(p1) + fix(p2) + assertTrue(s.has(p1)); + assertTrue(s.has(p2)); + assertFalse(s.has(p3)); + + s.delete(p2); + assertTrue(s.has(p1)); + assertFalse(s.has(p2)); + assertFalse(s.has(p3)); +} + +TestSet(Set, Object.seal) +TestSet(Set, Object.freeze) +TestSet(Set, Object.preventExtensions) + + +// Maps and weak maps. + +function TestMap(construct, fix) { + TestWithProxies(TestMap2, construct, fix) +} + +function TestMap2(construct, fix, create) { + var handler = {fix: function() { return {} }} + var p1 = create(handler) + var p2 = create(handler) + var p3 = create(handler) + fix(p3) + + var m = construct(); + m.set(p1, 123); + m.set(p2, 321); + assertTrue(m.has(p1)); + assertTrue(m.has(p2)); + assertFalse(m.has(p3)); + assertSame(123, m.get(p1)); + assertSame(321, m.get(p2)); + + fix(p1) + fix(p2) + assertTrue(m.has(p1)); + assertTrue(m.has(p2)); + assertFalse(m.has(p3)); + assertSame(123, m.get(p1)); + assertSame(321, m.get(p2)); + + m.delete(p2); + assertTrue(m.has(p1)); + assertFalse(m.has(p2)); + assertFalse(m.has(p3)); + assertSame(123, m.get(p1)); + assertSame(undefined, m.get(p2)); +} + +TestMap(Map, Object.seal) +TestMap(Map, Object.freeze) +TestMap(Map, Object.preventExtensions) + +TestMap(WeakMap, Object.seal) +TestMap(WeakMap, Object.freeze) +TestMap(WeakMap, Object.preventExtensions) diff --git a/test/mjsunit/harmony/proxies.js b/test/mjsunit/harmony/proxies.js index 3c4e5f61..8d8f8399 100644 --- a/test/mjsunit/harmony/proxies.js +++ b/test/mjsunit/harmony/proxies.js @@ -1,4 +1,4 @@ -// Copyright 2008 the V8 project authors. All rights reserved. +// Copyright 2011 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: @@ -28,70 +28,167 @@ // Flags: --harmony-proxies -// TODO(rossberg): for-in for proxies not implemented. -// TODO(rossberg): inheritance from proxies not implemented. -// TODO(rossberg): function proxies as constructors not implemented. +// Helper. +function TestWithProxies(test, x, y, z) { + test(Proxy.create, x, y, z) + test(function(h) {return Proxy.createFunction(h, function() {})}, x, y, z) +} -// Helper. -function TestWithProxies(test, handler) { - test(handler, Proxy.create) - test(handler, function(h) {return Proxy.createFunction(h, function() {})}) + +// Getting property descriptors (Object.getOwnPropertyDescriptor). + +var key + +function TestGetOwnProperty(handler) { + TestWithProxies(TestGetOwnProperty2, handler) +} + +function TestGetOwnProperty2(create, handler) { + var p = create(handler) + assertEquals(42, Object.getOwnPropertyDescriptor(p, "a").value) + assertEquals("a", key) + assertEquals(42, Object.getOwnPropertyDescriptor(p, 99).value) + assertEquals("99", key) } +TestGetOwnProperty({ + getOwnPropertyDescriptor: function(k) { + key = k + return {value: 42, configurable: true} + } +}) + +TestGetOwnProperty({ + getOwnPropertyDescriptor: function(k) { + return this.getOwnPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2: function(k) { + key = k + return {value: 42, configurable: true} + } +}) + +TestGetOwnProperty({ + getOwnPropertyDescriptor: function(k) { + key = k + return {get value() { return 42 }, get configurable() { return true }} + } +}) + +TestGetOwnProperty(Proxy.create({ + get: function(pr, pk) { + return function(k) { key = k; return {value: 42, configurable: true} } + } +})) -// Getters. + +function TestGetOwnPropertyThrow(handler) { + TestWithProxies(TestGetOwnPropertyThrow2, handler) +} + +function TestGetOwnPropertyThrow2(create, handler) { + var p = create(handler) + assertThrows(function(){ Object.getOwnPropertyDescriptor(p, "a") }, "myexn") + assertThrows(function(){ Object.getOwnPropertyDescriptor(p, 77) }, "myexn") +} + +TestGetOwnPropertyThrow({ + getOwnPropertyDescriptor: function(k) { throw "myexn" } +}) + +TestGetOwnPropertyThrow({ + getOwnPropertyDescriptor: function(k) { + return this.getPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2: function(k) { throw "myexn" } +}) + +TestGetOwnPropertyThrow({ + getOwnPropertyDescriptor: function(k) { + return {get value() { throw "myexn" }} + } +}) + +TestGetOwnPropertyThrow(Proxy.create({ + get: function(pr, pk) { + return function(k) { throw "myexn" } + } +})) + + + +// Getters (dot, brackets). + +var key function TestGet(handler) { TestWithProxies(TestGet2, handler) } -function TestGet2(handler, create) { +function TestGet2(create, handler) { var p = create(handler) assertEquals(42, p.a) + assertEquals("a", key) assertEquals(42, p["b"]) + assertEquals("b", key) + assertEquals(42, p[99]) + assertEquals("99", key) + assertEquals(42, (function(n) { return p[n] })("c")) + assertEquals("c", key) + assertEquals(42, (function(n) { return p[n] })(101)) + assertEquals("101", key) - // TODO(rossberg): inheritance from proxies not yet implemented. - // var o = Object.create(p, {x: {value: 88}}) - // assertEquals(42, o.a) - // assertEquals(42, o["b"]) - // assertEquals(88, o.x) - // assertEquals(88, o["x"]) + var o = Object.create(p, {x: {value: 88}}) + assertEquals(42, o.a) + assertEquals("a", key) + assertEquals(42, o["b"]) + assertEquals("b", key) + assertEquals(42, o[99]) + assertEquals("99", key) + assertEquals(88, o.x) + assertEquals(88, o["x"]) + assertEquals(42, (function(n) { return o[n] })("c")) + assertEquals("c", key) + assertEquals(42, (function(n) { return o[n] })(101)) + assertEquals("101", key) + assertEquals(88, (function(n) { return o[n] })("x")) } TestGet({ - get: function(r, k) { return 42 } + get: function(r, k) { key = k; return 42 } }) TestGet({ get: function(r, k) { return this.get2(r, k) }, - get2: function(r, k) { return 42 } + get2: function(r, k) { key = k; return 42 } }) TestGet({ - getPropertyDescriptor: function(k) { return {value: 42} } + getPropertyDescriptor: function(k) { key = k; return {value: 42} } }) TestGet({ getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, - getPropertyDescriptor2: function(k) { return {value: 42} } + getPropertyDescriptor2: function(k) { key = k; return {value: 42} } }) TestGet({ getPropertyDescriptor: function(k) { + key = k; return {get value() { return 42 }} } }) TestGet({ get: undefined, - getPropertyDescriptor: function(k) { return {value: 42} } + getPropertyDescriptor: function(k) { key = k; return {value: 42} } }) TestGet(Proxy.create({ get: function(pr, pk) { - return function(r, k) { return 42 } + return function(r, k) { key = k; return 42 } } })) @@ -100,14 +197,43 @@ function TestGetCall(handler) { TestWithProxies(TestGetCall2, handler) } -function TestGetCall2(handler, create) { +function TestGetCall2(create, handler) { var p = create(handler) assertEquals(55, p.f()) + assertEquals(55, p["f"]()) assertEquals(55, p.f("unused", "arguments")) assertEquals(55, p.f.call(p)) + assertEquals(55, p["f"].call(p)) + assertEquals(55, p[101].call(p)) assertEquals(55, p.withargs(45, 5)) assertEquals(55, p.withargs.call(p, 11, 22)) + assertEquals(55, (function(n) { return p[n]() })("f")) + assertEquals(55, (function(n) { return p[n].call(p) })("f")) + assertEquals(55, (function(n) { return p[n](15, 20) })("withargs")) + assertEquals(55, (function(n) { return p[n].call(p, 13, 21) })("withargs")) assertEquals("6655", "66" + p) // calls p.toString + + var o = Object.create(p, {g: {value: function(x) { return x + 88 }}}) + assertEquals(55, o.f()) + assertEquals(55, o["f"]()) + assertEquals(55, o.f("unused", "arguments")) + assertEquals(55, o.f.call(o)) + assertEquals(55, o.f.call(p)) + assertEquals(55, o["f"].call(p)) + assertEquals(55, o[101].call(p)) + assertEquals(55, o.withargs(45, 5)) + assertEquals(55, o.withargs.call(p, 11, 22)) + assertEquals(90, o.g(2)) + assertEquals(91, o.g.call(o, 3)) + assertEquals(92, o.g.call(p, 4)) + assertEquals(55, (function(n) { return o[n]() })("f")) + assertEquals(55, (function(n) { return o[n].call(o) })("f")) + assertEquals(55, (function(n) { return o[n](15, 20) })("withargs")) + assertEquals(55, (function(n) { return o[n].call(o, 13, 21) })("withargs")) + assertEquals(93, (function(n) { return o[n](5) })("g")) + assertEquals(94, (function(n) { return o[n].call(o, 6) })("g")) + assertEquals(95, (function(n) { return o[n].call(p, 7) })("g")) + assertEquals("6655", "66" + o) // calls o.toString } TestGetCall({ @@ -168,10 +294,20 @@ function TestGetThrow(handler) { TestWithProxies(TestGetThrow2, handler) } -function TestGetThrow2(handler, create) { +function TestGetThrow2(create, handler) { var p = create(handler) assertThrows(function(){ p.a }, "myexn") assertThrows(function(){ p["b"] }, "myexn") + assertThrows(function(){ p[3] }, "myexn") + assertThrows(function(){ (function(n) { p[n] })("c") }, "myexn") + assertThrows(function(){ (function(n) { p[n] })(99) }, "myexn") + + var o = Object.create(p, {x: {value: 88}, '4': {value: 89}}) + assertThrows(function(){ o.a }, "myexn") + assertThrows(function(){ o["b"] }, "myexn") + assertThrows(function(){ o[3] }, "myexn") + assertThrows(function(){ (function(n) { o[n] })("c") }, "myexn") + assertThrows(function(){ (function(n) { o[n] })(99) }, "myexn") } TestGetThrow({ @@ -220,11 +356,11 @@ TestGetThrow(Proxy.create({ var key var val -function TestSet(handler, create) { +function TestSet(handler) { TestWithProxies(TestSet2, handler) } -function TestSet2(handler, create) { +function TestSet2(create, handler) { var p = create(handler) assertEquals(42, p.a = 42) assertEquals("a", key) @@ -232,6 +368,16 @@ function TestSet2(handler, create) { assertEquals(43, p["b"] = 43) assertEquals("b", key) assertEquals(43, val) + assertEquals(44, p[77] = 44) + assertEquals("77", key) + assertEquals(44, val) + + assertEquals(45, (function(n) { return p[n] = 45 })("c")) + assertEquals("c", key) + assertEquals(45, val) + assertEquals(46, (function(n) { return p[n] = 46 })(99)) + assertEquals("99", key) + assertEquals(46, val) } TestSet({ @@ -304,15 +450,17 @@ TestSet(Proxy.create({ })) - -function TestSetThrow(handler, create) { +function TestSetThrow(handler) { TestWithProxies(TestSetThrow2, handler) } -function TestSetThrow2(handler, create) { +function TestSetThrow2(create, handler) { var p = create(handler) assertThrows(function(){ p.a = 42 }, "myexn") assertThrows(function(){ p["b"] = 42 }, "myexn") + assertThrows(function(){ p[22] = 42 }, "myexn") + assertThrows(function(){ (function(n) { p[n] = 45 })("c") }, "myexn") + assertThrows(function(){ (function(n) { p[n] = 46 })(99) }, "myexn") } TestSetThrow({ @@ -424,6 +572,124 @@ TestSetThrow(Proxy.create({ })) +var key +var val + +function TestSetForDerived(handler) { + TestWithProxies(TestSetForDerived2, handler) +} + +function TestSetForDerived2(create, handler) { + var p = create(handler) + var o = Object.create(p, {x: {value: 88, writable: true}, + '1': {value: 89, writable: true}}) + + key = "" + assertEquals(48, o.x = 48) + assertEquals("", key) // trap not invoked + assertEquals(48, o.x) + + assertEquals(47, o[1] = 47) + assertEquals("", key) // trap not invoked + assertEquals(47, o[1]) + + assertEquals(49, o.y = 49) + assertEquals("y", key) + assertEquals(49, o.y) + + assertEquals(50, o[2] = 50) + assertEquals("2", key) + assertEquals(50, o[2]) + + assertEquals(44, o.p_writable = 44) + assertEquals("p_writable", key) + assertEquals(44, o.p_writable) + + assertEquals(45, o.p_nonwritable = 45) + assertEquals("p_nonwritable", key) + assertEquals(45, o.p_nonwritable) + + assertEquals(46, o.p_setter = 46) + assertEquals("p_setter", key) + assertEquals(46, val) // written to parent + assertFalse(Object.prototype.hasOwnProperty.call(o, "p_setter")) + + val = "" + assertEquals(47, o.p_nosetter = 47) + assertEquals("p_nosetter", key) + assertEquals("", val) // not written at all + assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nosetter")); + + key = "" + assertThrows(function(){ "use strict"; o.p_nosetter = 50 }, TypeError) + assertEquals("p_nosetter", key) + assertEquals("", val) // not written at all + + assertThrows(function(){ o.p_nonconf = 53 }, TypeError) + assertEquals("p_nonconf", key) + + assertThrows(function(){ o.p_throw = 51 }, "myexn") + assertEquals("p_throw", key) + + assertThrows(function(){ o.p_setterthrow = 52 }, "myexn") + assertEquals("p_setterthrow", key) +} + +TestSetForDerived({ + getPropertyDescriptor: function(k) { + key = k; + switch (k) { + case "p_writable": return {writable: true, configurable: true} + case "p_nonwritable": return {writable: false, configurable: true} + case "p_setter":return {set: function(x) { val = x }, configurable: true} + case "p_nosetter": return {get: function() { return 1 }, configurable: true} + case "p_nonconf":return {} + case "p_throw": throw "myexn" + case "p_setterthrow": return {set: function(x) { throw "myexn" }} + default: return undefined + } + } +}) + + +// Evil proxy-induced side-effects shouldn't crash. +// TODO(rossberg): proper behaviour isn't really spec'ed yet, so ignore results. + +TestWithProxies(function(create) { + var calls = 0 + var handler = { + getPropertyDescriptor: function() { + ++calls + return (calls % 2 == 1) + ? {get: function() { return 5 }, configurable: true} + : {set: function() { return false }, configurable: true} + } + } + var p = create(handler) + var o = Object.create(p) + // Make proxy prototype property read-only after CanPut check. + try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } +}) + +TestWithProxies(function(create) { + var handler = { + getPropertyDescriptor: function() { + Object.defineProperty(o, "x", {get: function() { return 5 }}); + return {set: function() {}} + } + } + var p = create(handler) + var o = Object.create(p) + // Make object property read-only after CanPut check. + try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } +}) + + + +// TODO(rossberg): TestSetReject, returning false +// TODO(rossberg): TestGetProperty, TestSetProperty + + // Property definition (Object.defineProperty and Object.defineProperties). @@ -434,7 +700,7 @@ function TestDefine(handler) { TestWithProxies(TestDefine2, handler) } -function TestDefine2(handler, create) { +function TestDefine2(create, handler) { var p = create(handler) assertEquals(p, Object.defineProperty(p, "a", {value: 44})) assertEquals("a", key) @@ -453,6 +719,12 @@ function TestDefine2(handler, create) { assertEquals(46, desc.value) assertEquals(false, desc.enumerable) + assertEquals(p, Object.defineProperty(p, 101, {value: 47, enumerable: false})) + assertEquals("101", key) + assertEquals(2, Object.getOwnPropertyNames(desc).length) + assertEquals(47, desc.value) + assertEquals(false, desc.enumerable) + var attributes = {configurable: true, mine: 66, minetoo: 23} assertEquals(p, Object.defineProperty(p, "d", attributes)) assertEquals("d", key) @@ -474,20 +746,20 @@ function TestDefine2(handler, create) { assertEquals("zzz", key) assertEquals(0, Object.getOwnPropertyNames(desc).length) -// TODO(rossberg): This test requires for-in on proxies. -// var d = create({ -// get: function(r, k) { return (k === "value") ? 77 : void 0 }, -// getOwnPropertyNames: function() { return ["value"] } -// }) -// assertEquals(1, Object.getOwnPropertyNames(d).length) -// assertEquals(77, d.value) -// assertEquals(p, Object.defineProperty(p, "p", d)) -// assertEquals("p", key) -// assertEquals(1, Object.getOwnPropertyNames(desc).length) -// assertEquals(77, desc.value) + var d = create({ + get: function(r, k) { return (k === "value") ? 77 : void 0 }, + getOwnPropertyNames: function() { return ["value"] }, + enumerate: function() { return ["value"] } + }) + assertEquals(1, Object.getOwnPropertyNames(d).length) + assertEquals(77, d.value) + assertEquals(p, Object.defineProperty(p, "p", d)) + assertEquals("p", key) + assertEquals(1, Object.getOwnPropertyNames(desc).length) + assertEquals(77, desc.value) var props = { - 'bla': {}, + '11': {}, blub: {get: function() { return true }}, '': {get value() { return 20 }}, last: {value: 21, configurable: true, mine: "eyes"} @@ -524,21 +796,21 @@ function TestDefineThrow(handler) { TestWithProxies(TestDefineThrow2, handler) } -function TestDefineThrow2(handler, create) { +function TestDefineThrow2(create, handler) { var p = create(handler) assertThrows(function(){ Object.defineProperty(p, "a", {value: 44})}, "myexn") - -// TODO(rossberg): These tests require for-in on proxies. -// var d1 = create({ -// get: function(r, k) { throw "myexn" }, -// getOwnPropertyNames: function() { return ["value"] } -// }) -// assertThrows(function(){ Object.defineProperty(p, "p", d1) }, "myexn") -// var d2 = create({ -// get: function(r, k) { return 77 }, -// getOwnPropertyNames: function() { throw "myexn" } -// }) -// assertThrows(function(){ Object.defineProperty(p, "p", d2) }, "myexn") + assertThrows(function(){ Object.defineProperty(p, 0, {value: 44})}, "myexn") + + var d1 = create({ + get: function(r, k) { throw "myexn" }, + getOwnPropertyNames: function() { return ["value"] } + }) + assertThrows(function(){ Object.defineProperty(p, "p", d1) }, "myexn") + var d2 = create({ + get: function(r, k) { return 77 }, + getOwnPropertyNames: function() { throw "myexn" } + }) + assertThrows(function(){ Object.defineProperty(p, "p", d2) }, "myexn") var props = {bla: {get value() { throw "otherexn" }}} assertThrows(function(){ Object.defineProperties(p, props) }, "otherexn") @@ -573,12 +845,14 @@ function TestDelete(handler) { TestWithProxies(TestDelete2, handler) } -function TestDelete2(handler, create) { +function TestDelete2(create, handler) { var p = create(handler) assertEquals(true, delete p.a) assertEquals("a", key) assertEquals(true, delete p["b"]) assertEquals("b", key) + assertEquals(true, delete p[1]) + assertEquals("1", key) assertEquals(false, delete p.z1) assertEquals("z1", key) @@ -591,6 +865,8 @@ function TestDelete2(handler, create) { assertEquals("c", key) assertEquals(true, delete p["d"]) assertEquals("d", key) + assertEquals(true, delete p[2]) + assertEquals("2", key) assertThrows(function(){ delete p.z3 }, TypeError) assertEquals("z3", key) @@ -619,15 +895,17 @@ function TestDeleteThrow(handler) { TestWithProxies(TestDeleteThrow2, handler) } -function TestDeleteThrow2(handler, create) { +function TestDeleteThrow2(create, handler) { var p = create(handler) assertThrows(function(){ delete p.a }, "myexn") assertThrows(function(){ delete p["b"] }, "myexn"); + assertThrows(function(){ delete p[3] }, "myexn"); (function() { "use strict" assertThrows(function(){ delete p.c }, "myexn") assertThrows(function(){ delete p["d"] }, "myexn") + assertThrows(function(){ delete p[4] }, "myexn"); })() } @@ -658,7 +936,7 @@ function TestDescriptor(handler) { TestWithProxies(TestDescriptor2, handler) } -function TestDescriptor2(handler, create) { +function TestDescriptor2(create, handler) { var p = create(handler) var descs = [ {configurable: true}, @@ -697,7 +975,7 @@ function TestDescriptorThrow(handler) { TestWithProxies(TestDescriptorThrow2, handler) } -function TestDescriptorThrow2(handler, create) { +function TestDescriptorThrow2(create, handler) { var p = create(handler) assertThrows(function(){ Object.getOwnPropertyDescriptor(p, "a") }, "myexn") } @@ -721,7 +999,7 @@ function TestComparison(eq) { TestWithProxies(TestComparison2, eq) } -function TestComparison2(eq, create) { +function TestComparison2(create, eq) { var p1 = create({}) var p2 = create({}) @@ -764,7 +1042,7 @@ function TestIn(handler) { TestWithProxies(TestIn2, handler) } -function TestIn2(handler, create) { +function TestIn2(create, handler) { var p = create(handler) assertTrue("a" in p) assertEquals("a", key) @@ -778,6 +1056,7 @@ function TestIn2(handler, create) { assertEquals(0, ("zzz" in p) ? 2 : 0) assertEquals(2, !("zzz" in p) ? 2 : 0) + // Test compilation in conditionals. if ("b" in p) { } else { assertTrue(false) @@ -830,7 +1109,7 @@ TestIn({ }) TestIn({ - get: undefined, + has: undefined, getPropertyDescriptor: function(k) { key = k; return k < "z" ? {value: 42} : void 0 } @@ -847,9 +1126,10 @@ function TestInThrow(handler) { TestWithProxies(TestInThrow2, handler) } -function TestInThrow2(handler, create) { +function TestInThrow2(create, handler) { var p = create(handler) assertThrows(function(){ return "a" in o }, "myexn") + assertThrows(function(){ return 99 in o }, "myexn") assertThrows(function(){ return !("a" in o) }, "myexn") assertThrows(function(){ return ("a" in o) ? 2 : 3 }, "myexn") assertThrows(function(){ if ("b" in o) {} }, "myexn") @@ -876,7 +1156,7 @@ TestInThrow({ }) TestInThrow({ - get: undefined, + has: undefined, getPropertyDescriptor: function(k) { throw "myexn" } }) @@ -891,6 +1171,158 @@ TestInThrow(Proxy.create({ })) +function TestInForDerived(handler) { + TestWithProxies(TestInForDerived2, handler) +} + +function TestInForDerived2(create, handler) { + var p = create(handler) + var o = Object.create(p) + + assertTrue("a" in o) + assertEquals("a", key) + assertTrue(99 in o) + assertEquals("99", key) + assertFalse("z" in o) + assertEquals("z", key) + + assertEquals(2, ("a" in o) ? 2 : 0) + assertEquals(0, !("a" in o) ? 2 : 0) + assertEquals(0, ("zzz" in o) ? 2 : 0) + assertEquals(2, !("zzz" in o) ? 2 : 0) + + if ("b" in o) { + } else { + assertTrue(false) + } + assertEquals("b", key) + + if ("zz" in o) { + assertTrue(false) + } + assertEquals("zz", key) + + if (!("c" in o)) { + assertTrue(false) + } + assertEquals("c", key) + + if (!("zzz" in o)) { + } else { + assertTrue(false) + } + assertEquals("zzz", key) +} + +TestInForDerived({ + getPropertyDescriptor: function(k) { + key = k; return k < "z" ? {value: 42, configurable: true} : void 0 + } +}) + +TestInForDerived({ + getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) }, + getPropertyDescriptor2: function(k) { + key = k; return k < "z" ? {value: 42, configurable: true} : void 0 + } +}) + +TestInForDerived({ + getPropertyDescriptor: function(k) { + key = k; + return k < "z" ? {get value() { return 42 }, configurable: true} : void 0 + } +}) + +/* TODO(rossberg): this will work once we implement the newest proposal + * regarding default traps for getPropertyDescriptor. +TestInForDerived({ + getOwnPropertyDescriptor: function(k) { + key = k; return k < "z" ? {value: 42, configurable: true} : void 0 + } +}) + +TestInForDerived({ + getOwnPropertyDescriptor: function(k) { + return this.getOwnPropertyDescriptor2(k) + }, + getOwnPropertyDescriptor2: function(k) { + key = k; return k < "z" ? {value: 42, configurable: true} : void 0 + } +}) + +TestInForDerived({ + getOwnPropertyDescriptor: function(k) { + key = k; + return k < "z" ? {get value() { return 42 }, configurable: true} : void 0 + } +}) +*/ + +TestInForDerived(Proxy.create({ + get: function(pr, pk) { + return function(k) { + key = k; return k < "z" ? {value: 42, configurable: true} : void 0 + } + } +})) + + + +// Property descriptor conversion. + +var descget + +function TestDescriptorGetOrder(handler) { + var p = Proxy.create(handler) + var o = Object.create(p, {b: {value: 0}}) + TestDescriptorGetOrder2(function(n) { return p[n] }, "vV") + TestDescriptorGetOrder2(function(n) { return n in p }, "") + TestDescriptorGetOrder2(function(n) { return o[n] }, "vV") + TestDescriptorGetOrder2(function(n) { return n in o }, "eEcCvVwWgs") +} + +function TestDescriptorGetOrder2(f, access) { + descget = "" + assertTrue(f("a")) + assertEquals(access, descget) + descget = "" + assertTrue(f(99)) + assertEquals(access, descget) + descget = "" + assertFalse(!!f("z")) + assertEquals("", descget) +} + +TestDescriptorGetOrder({ + getPropertyDescriptor: function(k) { + if (k >= "z") return void 0 + // Return a proxy as property descriptor, so that we can log accesses. + return Proxy.create({ + get: function(r, attr) { + descget += attr[0].toUpperCase() + return true + }, + has: function(attr) { + descget += attr[0] + switch (attr) { + case "writable": + case "enumerable": + case "configurable": + case "value": + return true + case "get": + case "set": + return false + default: + assertUnreachable() + } + } + }) + } +}) + + // Own Properties (Object.prototype.hasOwnProperty). @@ -900,7 +1332,7 @@ function TestHasOwn(handler) { TestWithProxies(TestHasOwn2, handler) } -function TestHasOwn2(handler, create) { +function TestHasOwn2(create, handler) { var p = create(handler) assertTrue(Object.prototype.hasOwnProperty.call(p, "a")) assertEquals("a", key) @@ -958,7 +1390,7 @@ function TestHasOwnThrow(handler) { TestWithProxies(TestHasOwnThrow2, handler) } -function TestHasOwnThrow2(handler, create) { +function TestHasOwnThrow2(create, handler) { var p = create(handler) assertThrows(function(){ Object.prototype.hasOwnProperty.call(p, "a")}, "myexn") @@ -1005,84 +1437,173 @@ TestHasOwnThrow(Proxy.create({ // Instanceof (instanceof) -function TestInstanceof() { - var o = {} +function TestProxyInstanceof() { + var o1 = {} var p1 = Proxy.create({}) - var p2 = Proxy.create({}, o) + var p2 = Proxy.create({}, o1) var p3 = Proxy.create({}, p2) + var o2 = Object.create(p2) var f0 = function() {} - f0.prototype = o + f0.prototype = o1 var f1 = function() {} f1.prototype = p1 var f2 = function() {} f2.prototype = p2 - - assertTrue(o instanceof Object) - assertFalse(o instanceof f0) - assertFalse(o instanceof f1) - assertFalse(o instanceof f2) + var f3 = function() {} + f3.prototype = o2 + + assertTrue(o1 instanceof Object) + assertFalse(o1 instanceof f0) + assertFalse(o1 instanceof f1) + assertFalse(o1 instanceof f2) + assertFalse(o1 instanceof f3) assertFalse(p1 instanceof Object) assertFalse(p1 instanceof f0) assertFalse(p1 instanceof f1) assertFalse(p1 instanceof f2) + assertFalse(p1 instanceof f3) assertTrue(p2 instanceof Object) assertTrue(p2 instanceof f0) assertFalse(p2 instanceof f1) assertFalse(p2 instanceof f2) + assertFalse(p2 instanceof f3) assertTrue(p3 instanceof Object) assertTrue(p3 instanceof f0) assertFalse(p3 instanceof f1) assertTrue(p3 instanceof f2) + assertFalse(p3 instanceof f3) + assertTrue(o2 instanceof Object) + assertTrue(o2 instanceof f0) + assertFalse(o2 instanceof f1) + assertTrue(o2 instanceof f2) + assertFalse(o2 instanceof f3) var f = Proxy.createFunction({}, function() {}) assertTrue(f instanceof Function) } -TestInstanceof() +TestProxyInstanceof() + + +function TestInstanceofProxy() { + var o0 = Object.create(null) + var o1 = {} + var o2 = Object.create(o0) + var o3 = Object.create(o1) + var o4 = Object.create(o2) + var o5 = Object.create(o3) + + function handler(o) { return {get: function() { return o } } } + var f0 = Proxy.createFunction(handler(o0), function() {}) + var f1 = Proxy.createFunction(handler(o1), function() {}) + var f2 = Proxy.createFunction(handler(o2), function() {}) + var f3 = Proxy.createFunction(handler(o3), function() {}) + var f4 = Proxy.createFunction(handler(o4), function() {}) + var f5 = Proxy.createFunction(handler(o4), function() {}) + + assertFalse(null instanceof f0) + assertFalse(o0 instanceof f0) + assertFalse(o0 instanceof f1) + assertFalse(o0 instanceof f2) + assertFalse(o0 instanceof f3) + assertFalse(o0 instanceof f4) + assertFalse(o0 instanceof f5) + assertFalse(o1 instanceof f0) + assertFalse(o1 instanceof f1) + assertFalse(o1 instanceof f2) + assertFalse(o1 instanceof f3) + assertFalse(o1 instanceof f4) + assertFalse(o1 instanceof f5) + assertTrue(o2 instanceof f0) + assertFalse(o2 instanceof f1) + assertFalse(o2 instanceof f2) + assertFalse(o2 instanceof f3) + assertFalse(o2 instanceof f4) + assertFalse(o2 instanceof f5) + assertFalse(o3 instanceof f0) + assertTrue(o3 instanceof f1) + assertFalse(o3 instanceof f2) + assertFalse(o3 instanceof f3) + assertFalse(o3 instanceof f4) + assertFalse(o3 instanceof f5) + assertTrue(o4 instanceof f0) + assertFalse(o4 instanceof f1) + assertTrue(o4 instanceof f2) + assertFalse(o4 instanceof f3) + assertFalse(o4 instanceof f4) + assertFalse(o4 instanceof f5) + assertFalse(o5 instanceof f0) + assertTrue(o5 instanceof f1) + assertFalse(o5 instanceof f2) + assertTrue(o5 instanceof f3) + assertFalse(o5 instanceof f4) + assertFalse(o5 instanceof f5) + + var f = Proxy.createFunction({}, function() {}) + var ff = Proxy.createFunction(handler(Function), function() {}) + assertTrue(f instanceof Function) + assertFalse(f instanceof ff) +} + +TestInstanceofProxy() // Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf). function TestPrototype() { - var o = {} + var o1 = {} var p1 = Proxy.create({}) - var p2 = Proxy.create({}, o) + var p2 = Proxy.create({}, o1) var p3 = Proxy.create({}, p2) - var p4 = Proxy.create({}, 666) + var p4 = Proxy.create({}, null) + var o2 = Object.create(p3) - assertSame(Object.getPrototypeOf(o), Object.prototype) + assertSame(Object.getPrototypeOf(o1), Object.prototype) assertSame(Object.getPrototypeOf(p1), null) - assertSame(Object.getPrototypeOf(p2), o) + assertSame(Object.getPrototypeOf(p2), o1) assertSame(Object.getPrototypeOf(p3), p2) assertSame(Object.getPrototypeOf(p4), null) + assertSame(Object.getPrototypeOf(o2), p3) - assertTrue(Object.prototype.isPrototypeOf(o)) + assertTrue(Object.prototype.isPrototypeOf(o1)) assertFalse(Object.prototype.isPrototypeOf(p1)) assertTrue(Object.prototype.isPrototypeOf(p2)) assertTrue(Object.prototype.isPrototypeOf(p3)) assertFalse(Object.prototype.isPrototypeOf(p4)) - assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o)) + assertTrue(Object.prototype.isPrototypeOf(o2)) + assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o1)) assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p1)) assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p2)) assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p3)) assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p4)) - assertFalse(Object.prototype.isPrototypeOf.call(o, o)) - assertFalse(Object.prototype.isPrototypeOf.call(o, p1)) - assertTrue(Object.prototype.isPrototypeOf.call(o, p2)) - assertTrue(Object.prototype.isPrototypeOf.call(o, p3)) - assertFalse(Object.prototype.isPrototypeOf.call(o, p4)) + assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o2)) + assertFalse(Object.prototype.isPrototypeOf.call(o1, o1)) + assertFalse(Object.prototype.isPrototypeOf.call(o1, p1)) + assertTrue(Object.prototype.isPrototypeOf.call(o1, p2)) + assertTrue(Object.prototype.isPrototypeOf.call(o1, p3)) + assertFalse(Object.prototype.isPrototypeOf.call(o1, p4)) + assertTrue(Object.prototype.isPrototypeOf.call(o1, o2)) assertFalse(Object.prototype.isPrototypeOf.call(p1, p1)) - assertFalse(Object.prototype.isPrototypeOf.call(p1, o)) + assertFalse(Object.prototype.isPrototypeOf.call(p1, o1)) assertFalse(Object.prototype.isPrototypeOf.call(p1, p2)) assertFalse(Object.prototype.isPrototypeOf.call(p1, p3)) assertFalse(Object.prototype.isPrototypeOf.call(p1, p4)) + assertFalse(Object.prototype.isPrototypeOf.call(p1, o2)) assertFalse(Object.prototype.isPrototypeOf.call(p2, p1)) assertFalse(Object.prototype.isPrototypeOf.call(p2, p2)) assertTrue(Object.prototype.isPrototypeOf.call(p2, p3)) assertFalse(Object.prototype.isPrototypeOf.call(p2, p4)) + assertTrue(Object.prototype.isPrototypeOf.call(p2, o2)) assertFalse(Object.prototype.isPrototypeOf.call(p3, p2)) + assertTrue(Object.prototype.isPrototypeOf.call(p3, o2)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, o1)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, p1)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, p2)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, p3)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, p4)) + assertFalse(Object.prototype.isPrototypeOf.call(o2, o2)) var f = Proxy.createFunction({}, function() {}) assertSame(Object.getPrototypeOf(f), Function.prototype) @@ -1097,12 +1618,12 @@ TestPrototype() // Property names (Object.getOwnPropertyNames, Object.keys). function TestPropertyNames(names, handler) { - TestWithProxies(TestPropertyNames2, [names, handler]) + TestWithProxies(TestPropertyNames2, handler, names) } -function TestPropertyNames2(names_handler, create) { - var p = create(names_handler[1]) - assertArrayEquals(names_handler[0], Object.getOwnPropertyNames(p)) +function TestPropertyNames2(create, handler, names) { + var p = create(handler) + assertArrayEquals(names, Object.getOwnPropertyNames(p)) } TestPropertyNames([], { @@ -1129,7 +1650,7 @@ function TestPropertyNamesThrow(handler) { TestWithProxies(TestPropertyNamesThrow2, handler) } -function TestPropertyNamesThrow2(handler, create) { +function TestPropertyNamesThrow2(create, handler) { var p = create(handler) assertThrows(function(){ Object.getOwnPropertyNames(p) }, "myexn") } @@ -1145,12 +1666,12 @@ TestPropertyNamesThrow({ function TestKeys(names, handler) { - TestWithProxies(TestKeys2, [names, handler]) + TestWithProxies(TestKeys2, handler, names) } -function TestKeys2(names_handler, create) { - var p = create(names_handler[1]) - assertArrayEquals(names_handler[0], Object.keys(p)) +function TestKeys2(create, handler, names) { + var p = create(handler) + assertArrayEquals(names, Object.keys(p)) } TestKeys([], { @@ -1174,7 +1695,9 @@ TestKeys(["[object Object]"], { TestKeys(["a", "0"], { getOwnPropertyNames: function() { return ["a", 23, "zz", "", 0] }, - getOwnPropertyDescriptor: function(k) { return {enumerable: k.length == 1} } + getOwnPropertyDescriptor: function(k) { + return k == "" ? undefined : {enumerable: k.length == 1} + } }) TestKeys(["23", "zz", ""], { @@ -1188,10 +1711,12 @@ TestKeys(["23", "zz", ""], { TestKeys(["a", "b", "c", "5"], { get getOwnPropertyNames() { - return function() { return ["0", 4, "a", "b", "c", 5] } + return function() { return ["0", 4, "a", "b", "c", 5, "ety"] } }, get getOwnPropertyDescriptor() { - return function(k) { return {enumerable: k >= "44"} } + return function(k) { + return k == "ety" ? undefined : {enumerable: k >= "44"} + } } }) @@ -1207,7 +1732,7 @@ function TestKeysThrow(handler) { TestWithProxies(TestKeysThrow2, handler) } -function TestKeysThrow2(handler, create) { +function TestKeysThrow2(create, handler) { var p = create(handler) assertThrows(function(){ Object.keys(p) }, "myexn") } @@ -1267,7 +1792,6 @@ TestKeysThrow([], { // Fixing (Object.freeze, Object.seal, Object.preventExtensions, // Object.isFrozen, Object.isSealed, Object.isExtensible) -// TODO(rossberg): use TestWithProxies to include funciton proxies function TestFix(names, handler) { var proto = {p: 77} var assertFixing = function(o, s, f, e) { @@ -1314,19 +1838,27 @@ function TestFix(names, handler) { Object.keys(p3).sort()) assertEquals(proto, Object.getPrototypeOf(p3)) assertEquals(77, p3.p) + + var p = Proxy.create(handler, proto) + var o = Object.create(p) + assertFixing(p, false, false, true) + assertFixing(o, false, false, true) + Object.freeze(o) + assertFixing(p, false, false, true) + assertFixing(o, true, true, false) } TestFix([], { fix: function() { return {} } }) -TestFix(["a", "b", "c", "d", "zz"], { +TestFix(["a", "b", "c", "3", "zz"], { fix: function() { return { a: {value: "a", writable: true, configurable: false, enumerable: true}, b: {value: 33, writable: false, configurable: false, enumerable: true}, c: {value: 0, writable: true, configurable: true, enumerable: true}, - d: {value: true, writable: false, configurable: true, enumerable: true}, + '3': {value: true, writable: false, configurable: true, enumerable: true}, zz: {value: 0, enumerable: false} } } @@ -1377,8 +1909,8 @@ function TestFixThrow(handler) { TestWithProxies(TestFixThrow2, handler) } -function TestFixThrow2(handler) { - var p = Proxy.create(handler, {}) +function TestFixThrow2(create, handler) { + var p = create(handler, {}) assertThrows(function(){ Object.seal(p) }, "myexn") assertThrows(function(){ Object.freeze(p) }, "myexn") assertThrows(function(){ Object.preventExtensions(p) }, "myexn") @@ -1404,6 +1936,135 @@ TestFixThrow({ }) +// Freeze a proxy in the middle of operations on it. +// TODO(rossberg): actual behaviour not specified consistently at the moment, +// just make sure that we do not crash. +function TestReentrantFix(f) { + TestWithProxies(f, Object.freeze) + TestWithProxies(f, Object.seal) + TestWithProxies(f, Object.preventExtensions) +} + +TestReentrantFix(function(create, freeze) { + var handler = { + get get() { freeze(p); return undefined }, + fix: function() { return {} } + } + var p = create(handler) + // Freeze while getting get trap. + try { p.x } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + get: function() { freeze(p); return 3 }, + fix: function() { return {} } + } + var p = create(handler) + // Freeze while executing get trap. + try { p.x } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + getPropertyDescriptor: function() { freeze(p); return undefined }, + fix: function() { return {} } + } + var p = create(handler) + // Freeze while executing default get trap. + try { p.x } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + getPropertyDescriptor: function() { freeze(p); return {get: function(){}} }, + fix: function() { return {} } + } + var p = create(handler) + var o = Object.create(p) + // Freeze while getting a property from prototype. + try { o.x } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + get set() { freeze(p); return undefined }, + fix: function() { return {} } + } + var p = create(handler) + // Freeze while getting set trap. + try { p.x = 4 } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + set: function() { freeze(p); return true }, + fix: function() { return {} } + } + var p = create(handler) + // Freeze while executing set trap. + try { p.x = 4 } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + getOwnPropertyDescriptor: function() { freeze(p); return undefined }, + fix: function() { return {} } + } + var p = create(handler) + // Freeze while executing default set trap. + try { p.x } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + getPropertyDescriptor: function() { freeze(p); return {set: function(){}} }, + fix: function() { return {} } + } + var p = create(handler) + var o = Object.create(p) + // Freeze while setting a property in prototype, dropping the property! + try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + getPropertyDescriptor: function() { freeze(p); return {set: function(){}} }, + fix: function() { return {x: {get: function(){}}} } + } + var p = create(handler) + var o = Object.create(p) + // Freeze while setting a property in prototype, making it read-only! + try { o.x = 4 } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + get fix() { freeze(p); return function(){} } + } + var p = create(handler) + // Freeze while getting fix trap. + try { Object.freeze(p) } catch (e) { assertInstanceof(e, Error) } + p = create(handler) + try { Object.seal(p) } catch (e) { assertInstanceof(e, Error) } + p = create(handler) + try { Object.preventExtensions(p) } catch (e) { assertInstanceof(e, Error) } +}) + +TestReentrantFix(function(create, freeze) { + var handler = { + fix: function() { freeze(p); return {} } + } + var p = create(handler) + // Freeze while executing fix trap. + try { Object.freeze(p) } catch (e) { assertInstanceof(e, Error) } + p = create(handler) + try { Object.seal(p) } catch (e) { assertInstanceof(e, Error) } + p = create(handler) + try { Object.preventExtensions(p) } catch (e) { assertInstanceof(e, Error) } +}) + + // String conversion (Object.prototype.toString, // Object.prototype.toLocaleString, @@ -1426,6 +2087,13 @@ function TestToString(handler) { assertEquals("my_proxy", Object.prototype.toLocaleString.call(f)) assertEquals("toString", key) assertDoesNotThrow(function(){ Function.prototype.toString.call(f) }) + + var o = Object.create(p) + key = "" + assertEquals("[object Object]", Object.prototype.toString.call(o)) + assertEquals("", key) + assertEquals("my_proxy", Object.prototype.toLocaleString.call(o)) + assertEquals("toString", key) } TestToString({ @@ -1452,6 +2120,10 @@ function TestToStringThrow(handler) { var f = Proxy.createFunction(handler, function() {}) assertEquals("[object Function]", Object.prototype.toString.call(f)) assertThrows(function(){ Object.prototype.toLocaleString.call(f) }, "myexn") + + var o = Object.create(p) + assertEquals("[object Object]", Object.prototype.toString.call(o)) + assertThrows(function(){ Object.prototype.toLocaleString.call(o) }, "myexn") } TestToStringThrow({ @@ -1485,7 +2157,7 @@ function TestValueOf(handler) { TestWithProxies(TestValueOf2, handler) } -function TestValueOf2(handler, create) { +function TestValueOf2(create, handler) { var p = create(handler) assertSame(p, Object.prototype.valueOf.call(p)) } @@ -1502,7 +2174,7 @@ function TestIsEnumerable(handler) { TestWithProxies(TestIsEnumerable2, handler) } -function TestIsEnumerable2(handler, create) { +function TestIsEnumerable2(create, handler) { var p = create(handler) assertTrue(Object.prototype.propertyIsEnumerable.call(p, "a")) assertEquals("a", key) @@ -1510,6 +2182,11 @@ function TestIsEnumerable2(handler, create) { assertEquals("2", key) assertFalse(Object.prototype.propertyIsEnumerable.call(p, "z")) assertEquals("z", key) + + var o = Object.create(p) + key = "" + assertFalse(Object.prototype.propertyIsEnumerable.call(o, "a")) + assertEquals("", key) // trap not invoked } TestIsEnumerable({ @@ -1546,7 +2223,7 @@ function TestIsEnumerableThrow(handler) { TestWithProxies(TestIsEnumerableThrow2, handler) } -function TestIsEnumerableThrow2(handler, create) { +function TestIsEnumerableThrow2(create, handler) { var p = create(handler) assertThrows(function(){ Object.prototype.propertyIsEnumerable.call(p, "a") }, "myexn") @@ -1583,100 +2260,19 @@ TestIsEnumerableThrow(Proxy.create({ -// Calling (call, Function.prototype.call, Function.prototype.apply, -// Function.prototype.bind). - -var global = this -var receiver - -function TestCall(isStrict, callTrap) { - assertEquals(42, callTrap(5, 37)) -// TODO(rossberg): unrelated bug: this does not succeed for optimized code. -// assertEquals(isStrict ? undefined : global, receiver) - - var f = Proxy.createFunction({fix: function() { return {} }}, callTrap) - receiver = 333 - assertEquals(42, f(11, 31)) - assertEquals(isStrict ? undefined : global, receiver) - var o = {} - assertEquals(42, Function.prototype.call.call(f, o, 20, 22)) - assertEquals(o, receiver) - assertEquals(43, Function.prototype.call.call(f, null, 20, 23)) - assertEquals(isStrict ? null : global, receiver) - assertEquals(44, Function.prototype.call.call(f, 2, 21, 23)) - assertEquals(2, receiver.valueOf()) - receiver = 333 - assertEquals(32, Function.prototype.apply.call(f, o, [17, 15])) - assertEquals(o, receiver) - var ff = Function.prototype.bind.call(f, o, 12) - receiver = 333 - assertEquals(42, ff(30)) - assertEquals(o, receiver) - receiver = 333 - assertEquals(32, Function.prototype.apply.call(ff, {}, [20])) - assertEquals(o, receiver) - - Object.freeze(f) - receiver = 333 - assertEquals(42, f(11, 31)) -// TODO(rossberg): unrelated bug: this does not succeed for optimized code. -// assertEquals(isStrict ? undefined : global, receiver) - receiver = 333 - assertEquals(42, Function.prototype.call.call(f, o, 20, 22)) - assertEquals(o, receiver) - receiver = 333 - assertEquals(32, Function.prototype.apply.call(f, o, [17, 15])) - assertEquals(o, receiver) - receiver = 333 - assertEquals(42, ff(30)) - assertEquals(o, receiver) - receiver = 333 - assertEquals(32, Function.prototype.apply.call(ff, {}, [20])) - assertEquals(o, receiver) -} - -TestCall(false, function(x, y) { - receiver = this; return x + y -}) - -TestCall(true, function(x, y) { - "use strict"; - receiver = this; return x + y -}) - -TestCall(false, Proxy.createFunction({}, function(x, y) { - receiver = this; return x + y -})) - -TestCall(true, Proxy.createFunction({}, function(x, y) { - "use strict"; - receiver = this; return x + y -})) - -var p = Proxy.createFunction({fix: function() {return {}}}, function(x, y) { - receiver = this; return x + y -}) -TestCall(false, p) -Object.freeze(p) -TestCall(false, p) +// Constructor functions with proxy prototypes. +function TestConstructorWithProxyPrototype() { + TestWithProxies(TestConstructorWithProxyPrototype2, {}) +} -function TestCallThrow(callTrap) { - var f = Proxy.createFunction({fix: function() {return {}}}, callTrap) - assertThrows(function(){ f(11) }, "myexn") - assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn") - assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn") +function TestConstructorWithProxyPrototype2(create, handler) { + function C() {}; + C.prototype = create(handler); - Object.freeze(f) - assertThrows(function(){ f(11) }, "myexn") - assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn") - assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn") + var o = new C; + assertSame(C.prototype, o.__proto__); + assertSame(C.prototype, Object.getPrototypeOf(o)); } -TestCallThrow(function() { throw "myexn" }) -TestCallThrow(Proxy.createFunction({}, function() { throw "myexn" })) - -var p = Proxy.createFunction( - {fix: function() {return {}}}, function() { throw "myexn" }) -Object.freeze(p) -TestCallThrow(p) +TestConstructorWithProxyPrototype(); diff --git a/test/mjsunit/harmony/weakmaps.js b/test/mjsunit/harmony/weakmaps.js deleted file mode 100644 index 7b5dcaf0..00000000 --- a/test/mjsunit/harmony/weakmaps.js +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2011 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-weakmaps --expose-gc - - -// Test valid getter and setter calls -var m = new WeakMap; -assertDoesNotThrow(function () { m.get(new Object) }); -assertDoesNotThrow(function () { m.set(new Object) }); -assertDoesNotThrow(function () { m.has(new Object) }); -assertDoesNotThrow(function () { m.delete(new Object) }); - - -// Test invalid getter and setter calls -var m = new WeakMap; -assertThrows(function () { m.get(undefined) }, TypeError); -assertThrows(function () { m.set(undefined, 0) }, TypeError); -assertThrows(function () { m.get(0) }, TypeError); -assertThrows(function () { m.set(0, 0) }, TypeError); -assertThrows(function () { m.get('a-key') }, TypeError); -assertThrows(function () { m.set('a-key', 0) }, TypeError); - - -// Test expected mapping behavior -var m = new WeakMap; -function TestMapping(map, key, value) { - map.set(key, value); - assertSame(value, map.get(key)); -} -TestMapping(m, new Object, 23); -TestMapping(m, new Object, 'the-value'); -TestMapping(m, new Object, new Object); - - -// Test expected querying behavior -var m = new WeakMap; -var key = new Object; -TestMapping(m, key, 'to-be-present'); -assertTrue(m.has(key)); -assertFalse(m.has(new Object)); -TestMapping(m, key, undefined); -assertFalse(m.has(key)); -assertFalse(m.has(new Object)); - - -// Test expected deletion behavior -var m = new WeakMap; -var key = new Object; -TestMapping(m, key, 'to-be-deleted'); -assertTrue(m.delete(key)); -assertFalse(m.delete(key)); -assertFalse(m.delete(new Object)); -assertSame(m.get(key), undefined); - - -// Test GC of map with entry -var m = new WeakMap; -var key = new Object; -m.set(key, 'not-collected'); -gc(); -assertSame('not-collected', m.get(key)); - - -// Test GC of map with chained entries -var m = new WeakMap; -var head = new Object; -for (key = head, i = 0; i < 10; i++, key = m.get(key)) { - m.set(key, new Object); -} -gc(); -var count = 0; -for (key = head; key != undefined; key = m.get(key)) { - count++; -} -assertEquals(11, count); - - -// Test property attribute [[Enumerable]] -var m = new WeakMap; -function props(x) { - var array = []; - for (var p in x) array.push(p); - return array.sort(); -} -assertArrayEquals([], props(WeakMap)); -assertArrayEquals([], props(WeakMap.prototype)); -assertArrayEquals([], props(m)); - - -// Test arbitrary properties on weak maps -var m = new WeakMap; -function TestProperty(map, property, value) { - map[property] = value; - assertEquals(value, map[property]); -} -for (i = 0; i < 20; i++) { - TestProperty(m, i, 'val' + i); - TestProperty(m, 'foo' + i, 'bar' + i); -} -TestMapping(m, new Object, 'foobar'); - - -// Test direct constructor call -var m = WeakMap(); -assertTrue(m instanceof WeakMap); - - -// Test some common JavaScript idioms -var m = new WeakMap; -assertTrue(m instanceof WeakMap); -assertTrue(WeakMap.prototype.set instanceof Function) -assertTrue(WeakMap.prototype.get instanceof Function) -assertTrue(WeakMap.prototype.has instanceof Function) -assertTrue(WeakMap.prototype.delete instanceof Function) - - -// Regression test for WeakMap prototype. -assertTrue(WeakMap.prototype.constructor === WeakMap) -assertTrue(Object.getPrototypeOf(WeakMap.prototype) === Object.prototype) - - -// Regression test for issue 1617: The prototype of the WeakMap constructor -// needs to be unique (i.e. different from the one of the Object constructor). -assertFalse(WeakMap.prototype === Object.prototype); -var o = Object.create({}); -assertFalse("get" in o); -assertFalse("set" in o); -assertEquals(undefined, o.get); -assertEquals(undefined, o.set); -var o = Object.create({}, { myValue: { - value: 10, - enumerable: false, - configurable: true, - writable: true -}}); -assertEquals(10, o.myValue); - - -// Stress Test -// There is a proposed stress-test available at the es-discuss mailing list -// which cannot be reasonably automated. Check it out by hand if you like: -// https://mail.mozilla.org/pipermail/es-discuss/2011-May/014096.html diff --git a/test/mjsunit/math-min-max.js b/test/mjsunit/math-min-max.js index 0833c5c8..e4fd3135 100644 --- a/test/mjsunit/math-min-max.js +++ b/test/mjsunit/math-min-max.js @@ -115,3 +115,75 @@ assertEquals(NaN, Math.max(1, 'oxen')); assertEquals(Infinity, 1/Math.max(ZERO, -0)); assertEquals(Infinity, 1/Math.max(-0, ZERO)); + +function run(crankshaft_test) { + crankshaft_test(1); + crankshaft_test(1); + %OptimizeFunctionOnNextCall(crankshaft_test); + crankshaft_test(-0); +} + +function crankshaft_test_1(arg) { + var v1 = 1; + var v2 = 5; + var v3 = 1.5; + var v4 = 5.5; + var v5 = 2; + var v6 = 6; + var v7 = 0; + var v8 = -0; + + var v9 = 9.9; + var v0 = 10.1; + // Integer32 representation. + assertEquals(v2, Math.max(v1++, v2++)); + assertEquals(v1, Math.min(v1++, v2++)); + // Tagged representation. + assertEquals(v4, Math.max(v3, v4)); + assertEquals(v3, Math.min(v3, v4)); + assertEquals(v6, Math.max(v5, v6)); + assertEquals(v5, Math.min(v5, v6)); + // Double representation. + assertEquals(v0, Math.max(v0++, v9++)); + assertEquals(v9, Math.min(v0++, v9++)); + // Mixed representation. + assertEquals(v1, Math.min(v1++, v9++)); // int32, double + assertEquals(v0, Math.max(v0++, v2++)); // double, int32 + assertEquals(v1, Math.min(v1++, v6)); // int32, tagged + assertEquals(v2, Math.max(v5, v2++)); // tagged, int32 + assertEquals(v6, Math.min(v6, v9++)); // tagged, double + assertEquals(v0, Math.max(v0++, v5)); // double, tagged + + // Minus zero. + assertEquals(Infinity, 1/Math.max(v7, v8)); + assertEquals(-Infinity, 1/Math.min(v7, v8)); + // NaN. + assertEquals(NaN, Math.max(NaN, v8)); + assertEquals(NaN, Math.min(NaN, v9)); + assertEquals(NaN, Math.max(v8, NaN)); + assertEquals(NaN, Math.min(v9, NaN)); + // Minus zero as Integer32. + assertEquals((arg === -0) ? -Infinity : 1, 1/Math.min(arg, v2)); +} + +run(crankshaft_test_1); + +function crankshaft_test_2() { + var v9 = {}; + v9.valueOf = function() { return 6; } + // Deopt expected due to non-heapnumber objects. + assertEquals(6, Math.min(v9, 12)); +} + +run(crankshaft_test_2); + +// Test overriding Math.min and Math.max +Math.min = function(a, b) { return a + b; } +Math.max = function(a, b) { return a - b; } + +function crankshaft_test_3() { + assertEquals(8, Math.min(3, 5)); + assertEquals(3, Math.max(5, 2)); +} + +run(crankshaft_test_3); diff --git a/test/mjsunit/math-pow.js b/test/mjsunit/math-pow.js index 30d0cbdc..fb5f8a1f 100644 --- a/test/mjsunit/math-pow.js +++ b/test/mjsunit/math-pow.js @@ -25,118 +25,149 @@ // (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 // Tests the special cases specified by ES 15.8.2.13 -// Simple sanity check -assertEquals(4, Math.pow(2, 2)); -assertEquals(2147483648, Math.pow(2, 31)); -assertEquals(0.25, Math.pow(2, -2)); -assertEquals(0.0625, Math.pow(2, -4)); -assertEquals(1, Math.pow(1, 100)); -assertEquals(0, Math.pow(0, 1000)); - -// Spec tests -assertEquals(NaN, Math.pow(2, NaN)); -assertEquals(NaN, Math.pow(+0, NaN)); -assertEquals(NaN, Math.pow(-0, NaN)); -assertEquals(NaN, Math.pow(Infinity, NaN)); -assertEquals(NaN, Math.pow(-Infinity, NaN)); - -assertEquals(1, Math.pow(NaN, +0)); -assertEquals(1, Math.pow(NaN, -0)); - -assertEquals(NaN, Math.pow(NaN, NaN)); -assertEquals(NaN, Math.pow(NaN, 2.2)); -assertEquals(NaN, Math.pow(NaN, 1)); -assertEquals(NaN, Math.pow(NaN, -1)); -assertEquals(NaN, Math.pow(NaN, -2.2)); -assertEquals(NaN, Math.pow(NaN, Infinity)); -assertEquals(NaN, Math.pow(NaN, -Infinity)); - -assertEquals(Infinity, Math.pow(1.1, Infinity)); -assertEquals(Infinity, Math.pow(-1.1, Infinity)); -assertEquals(Infinity, Math.pow(2, Infinity)); -assertEquals(Infinity, Math.pow(-2, Infinity)); - -// Because +0 == -0, we need to compare 1/{+,-}0 to {+,-}Infinity -assertEquals(+Infinity, 1/Math.pow(1.1, -Infinity)); -assertEquals(+Infinity, 1/Math.pow(-1.1, -Infinity)); -assertEquals(+Infinity, 1/Math.pow(2, -Infinity)); -assertEquals(+Infinity, 1/Math.pow(-2, -Infinity)); - -assertEquals(NaN, Math.pow(1, Infinity)); -assertEquals(NaN, Math.pow(1, -Infinity)); -assertEquals(NaN, Math.pow(-1, Infinity)); -assertEquals(NaN, Math.pow(-1, -Infinity)); - -assertEquals(+0, Math.pow(0.1, Infinity)); -assertEquals(+0, Math.pow(-0.1, Infinity)); -assertEquals(+0, Math.pow(0.999, Infinity)); -assertEquals(+0, Math.pow(-0.999, Infinity)); - -assertEquals(Infinity, Math.pow(0.1, -Infinity)); -assertEquals(Infinity, Math.pow(-0.1, -Infinity)); -assertEquals(Infinity, Math.pow(0.999, -Infinity)); -assertEquals(Infinity, Math.pow(-0.999, -Infinity)); - -assertEquals(Infinity, Math.pow(Infinity, 0.1)); -assertEquals(Infinity, Math.pow(Infinity, 2)); - -assertEquals(+Infinity, 1/Math.pow(Infinity, -0.1)); -assertEquals(+Infinity, 1/Math.pow(Infinity, -2)); - -assertEquals(-Infinity, Math.pow(-Infinity, 3)); -assertEquals(-Infinity, Math.pow(-Infinity, 13)); - -assertEquals(Infinity, Math.pow(-Infinity, 3.1)); -assertEquals(Infinity, Math.pow(-Infinity, 2)); - -assertEquals(-Infinity, 1/Math.pow(-Infinity, -3)); -assertEquals(-Infinity, 1/Math.pow(-Infinity, -13)); - -assertEquals(+Infinity, 1/Math.pow(-Infinity, -3.1)); -assertEquals(+Infinity, 1/Math.pow(-Infinity, -2)); - -assertEquals(+Infinity, 1/Math.pow(+0, 1.1)); -assertEquals(+Infinity, 1/Math.pow(+0, 2)); - -assertEquals(Infinity, Math.pow(+0, -1.1)); -assertEquals(Infinity, Math.pow(+0, -2)); - -assertEquals(-Infinity, 1/Math.pow(-0, 3)); -assertEquals(-Infinity, 1/Math.pow(-0, 13)); - -assertEquals(+Infinity, 1/Math.pow(-0, 3.1)); -assertEquals(+Infinity, 1/Math.pow(-0, 2)); - -assertEquals(-Infinity, Math.pow(-0, -3)); -assertEquals(-Infinity, Math.pow(-0, -13)); - -assertEquals(Infinity, Math.pow(-0, -3.1)); -assertEquals(Infinity, Math.pow(-0, -2)); - -assertEquals(NaN, Math.pow(-0.00001, 1.1)); -assertEquals(NaN, Math.pow(-0.00001, -1.1)); -assertEquals(NaN, Math.pow(-1.1, 1.1)); -assertEquals(NaN, Math.pow(-1.1, -1.1)); -assertEquals(NaN, Math.pow(-2, 1.1)); -assertEquals(NaN, Math.pow(-2, -1.1)); -assertEquals(NaN, Math.pow(-1000, 1.1)); -assertEquals(NaN, Math.pow(-1000, -1.1)); - -assertEquals(+Infinity, 1/Math.pow(-0, 0.5)); -assertEquals(+Infinity, 1/Math.pow(-0, 0.6)); -assertEquals(-Infinity, 1/Math.pow(-0, 1)); -assertEquals(-Infinity, 1/Math.pow(-0, 10000000001)); - -assertEquals(+Infinity, Math.pow(-0, -0.5)); -assertEquals(+Infinity, Math.pow(-0, -0.6)); -assertEquals(-Infinity, Math.pow(-0, -1)); -assertEquals(-Infinity, Math.pow(-0, -10000000001)); - - - -// Tests from Sputnik S8.5_A13_T1. -assertTrue((1*((Math.pow(2,53))-1)*(Math.pow(2,-1074))) === 4.4501477170144023e-308); -assertTrue((1*(Math.pow(2,52))*(Math.pow(2,-1074))) === 2.2250738585072014e-308); -assertTrue((-1*(Math.pow(2,52))*(Math.pow(2,-1074))) === -2.2250738585072014e-308); +function test() { + // Simple sanity check + assertEquals(4, Math.pow(2, 2)); + assertEquals(2147483648, Math.pow(2, 31)); + assertEquals(0.25, Math.pow(2, -2)); + assertEquals(0.0625, Math.pow(2, -4)); + assertEquals(1, Math.pow(1, 100)); + assertEquals(0, Math.pow(0, 1000)); + + // Spec tests + assertEquals(NaN, Math.pow(2, NaN)); + assertEquals(NaN, Math.pow(+0, NaN)); + assertEquals(NaN, Math.pow(-0, NaN)); + assertEquals(NaN, Math.pow(Infinity, NaN)); + assertEquals(NaN, Math.pow(-Infinity, NaN)); + + assertEquals(1, Math.pow(NaN, +0)); + assertEquals(1, Math.pow(NaN, -0)); + + assertEquals(NaN, Math.pow(NaN, NaN)); + assertEquals(NaN, Math.pow(NaN, 2.2)); + assertEquals(NaN, Math.pow(NaN, 1)); + assertEquals(NaN, Math.pow(NaN, -1)); + assertEquals(NaN, Math.pow(NaN, -2.2)); + assertEquals(NaN, Math.pow(NaN, Infinity)); + assertEquals(NaN, Math.pow(NaN, -Infinity)); + + assertEquals(Infinity, Math.pow(1.1, Infinity)); + assertEquals(Infinity, Math.pow(-1.1, Infinity)); + assertEquals(Infinity, Math.pow(2, Infinity)); + assertEquals(Infinity, Math.pow(-2, Infinity)); + + // Because +0 == -0, we need to compare 1/{+,-}0 to {+,-}Infinity + assertEquals(+Infinity, 1/Math.pow(1.1, -Infinity)); + assertEquals(+Infinity, 1/Math.pow(-1.1, -Infinity)); + assertEquals(+Infinity, 1/Math.pow(2, -Infinity)); + assertEquals(+Infinity, 1/Math.pow(-2, -Infinity)); + + assertEquals(NaN, Math.pow(1, Infinity)); + assertEquals(NaN, Math.pow(1, -Infinity)); + assertEquals(NaN, Math.pow(-1, Infinity)); + assertEquals(NaN, Math.pow(-1, -Infinity)); + + assertEquals(+0, Math.pow(0.1, Infinity)); + assertEquals(+0, Math.pow(-0.1, Infinity)); + assertEquals(+0, Math.pow(0.999, Infinity)); + assertEquals(+0, Math.pow(-0.999, Infinity)); + + assertEquals(Infinity, Math.pow(0.1, -Infinity)); + assertEquals(Infinity, Math.pow(-0.1, -Infinity)); + assertEquals(Infinity, Math.pow(0.999, -Infinity)); + assertEquals(Infinity, Math.pow(-0.999, -Infinity)); + + assertEquals(Infinity, Math.pow(Infinity, 0.1)); + assertEquals(Infinity, Math.pow(Infinity, 2)); + + assertEquals(+Infinity, 1/Math.pow(Infinity, -0.1)); + assertEquals(+Infinity, 1/Math.pow(Infinity, -2)); + + assertEquals(-Infinity, Math.pow(-Infinity, 3)); + assertEquals(-Infinity, Math.pow(-Infinity, 13)); + + assertEquals(Infinity, Math.pow(-Infinity, 3.1)); + assertEquals(Infinity, Math.pow(-Infinity, 2)); + + assertEquals(-Infinity, 1/Math.pow(-Infinity, -3)); + assertEquals(-Infinity, 1/Math.pow(-Infinity, -13)); + + assertEquals(+Infinity, 1/Math.pow(-Infinity, -3.1)); + assertEquals(+Infinity, 1/Math.pow(-Infinity, -2)); + + assertEquals(+Infinity, 1/Math.pow(+0, 1.1)); + assertEquals(+Infinity, 1/Math.pow(+0, 2)); + + assertEquals(Infinity, Math.pow(+0, -1.1)); + assertEquals(Infinity, Math.pow(+0, -2)); + + assertEquals(-Infinity, 1/Math.pow(-0, 3)); + assertEquals(-Infinity, 1/Math.pow(-0, 13)); + + assertEquals(+Infinity, 1/Math.pow(-0, 3.1)); + assertEquals(+Infinity, 1/Math.pow(-0, 2)); + + assertEquals(-Infinity, Math.pow(-0, -3)); + assertEquals(-Infinity, Math.pow(-0, -13)); + + assertEquals(Infinity, Math.pow(-0, -3.1)); + assertEquals(Infinity, Math.pow(-0, -2)); + + assertEquals(NaN, Math.pow(-0.00001, 1.1)); + assertEquals(NaN, Math.pow(-0.00001, -1.1)); + assertEquals(NaN, Math.pow(-1.1, 1.1)); + assertEquals(NaN, Math.pow(-1.1, -1.1)); + assertEquals(NaN, Math.pow(-2, 1.1)); + assertEquals(NaN, Math.pow(-2, -1.1)); + assertEquals(NaN, Math.pow(-1000, 1.1)); + assertEquals(NaN, Math.pow(-1000, -1.1)); + + assertEquals(+Infinity, 1/Math.pow(-0, 0.5)); + assertEquals(+Infinity, 1/Math.pow(-0, 0.6)); + assertEquals(-Infinity, 1/Math.pow(-0, 1)); + assertEquals(-Infinity, 1/Math.pow(-0, 10000000001)); + + assertEquals(+Infinity, Math.pow(-0, -0.5)); + assertEquals(+Infinity, Math.pow(-0, -0.6)); + assertEquals(-Infinity, Math.pow(-0, -1)); + assertEquals(-Infinity, Math.pow(-0, -10000000001)); + + assertEquals(4, Math.pow(16, 0.5)); + assertEquals(NaN, Math.pow(-16, 0.5)); + assertEquals(0.25, Math.pow(16, -0.5)); + assertEquals(NaN, Math.pow(-16, -0.5)); + + // Test detecting and converting integer value as double. + assertEquals(8, Math.pow(2, Math.sqrt(9))); + + // Tests from Mozilla 15.8.2.13. + assertEquals(2, Math.pow.length); + assertEquals(NaN, Math.pow()); + assertEquals(1, Math.pow(null, null)); + assertEquals(NaN, Math.pow(void 0, void 0)); + assertEquals(1, Math.pow(true, false)); + assertEquals(0, Math.pow(false, true)); + assertEquals(Infinity, Math.pow(-Infinity, Infinity)); + assertEquals(0, Math.pow(-Infinity, -Infinity)); + assertEquals(1, Math.pow(0, 0)); + assertEquals(0, Math.pow(0, Infinity)); + assertEquals(NaN, Math.pow(NaN, 0.5)); + assertEquals(NaN, Math.pow(NaN, -0.5)); + + // Tests from Sputnik S8.5_A13_T1. + assertTrue( + (1*((Math.pow(2,53))-1)*(Math.pow(2,-1074))) === 4.4501477170144023e-308); + assertTrue( + (1*(Math.pow(2,52))*(Math.pow(2,-1074))) === 2.2250738585072014e-308); + assertTrue( + (-1*(Math.pow(2,52))*(Math.pow(2,-1074))) === -2.2250738585072014e-308); +} + +test(); +test(); +%OptimizeFunctionOnNextCall(test); +test();
\ No newline at end of file diff --git a/test/mjsunit/mjsunit.js b/test/mjsunit/mjsunit.js index faa5a438..033c78f4 100644 --- a/test/mjsunit/mjsunit.js +++ b/test/mjsunit/mjsunit.js @@ -221,9 +221,11 @@ var assertUnreachable; assertSame = function assertSame(expected, found, name_opt) { + // TODO(mstarzinger): We should think about using Harmony's egal operator + // or the function equivalent Object.is() here. if (found === expected) { if (expected !== 0 || (1 / expected) == (1 / found)) return; - } else if (isNaN(expected) && isNaN(found)) { + } else if ((expected !== expected) && (found !== found)) { return; } fail(PrettyPrint(expected), found, name_opt); diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status index bae09b4e..a1b92709 100644 --- a/test/mjsunit/mjsunit.status +++ b/test/mjsunit/mjsunit.status @@ -1,4 +1,4 @@ -# Copyright 2011 the V8 project authors. All rights reserved. +# 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: @@ -34,9 +34,10 @@ bugs: FAIL # Fails. regress/regress-1119: FAIL -############################################################################# -# Fails due to r10102 which reverts precise stepping on the 3.6 branch. -debug-step-2: FAIL +############################################################################## + +# NewGC: BUG(1719) slow to collect arrays over several contexts. +regress/regress-524: SKIP ############################################################################## # Too slow in debug mode with --stress-opt @@ -46,16 +47,16 @@ regress/regress-create-exception: PASS, SKIP if $mode == debug ############################################################################## # This one uses a built-in that's only present in debug mode. It takes -# too long to run in debug mode on ARM. -fuzz-natives: PASS, SKIP if ($mode == release || $arch == arm) +# too long to run in debug mode on ARM and MIPS. +fuzz-natives: PASS, SKIP if ($mode == release || $arch == arm || $arch == mips) big-object-literal: PASS, SKIP if ($arch == arm) # Issue 488: this test sometimes times out. array-constructor: PASS || TIMEOUT -# Very slow on ARM, contains no architecture dependent code. -unicode-case-overoptimization: PASS, TIMEOUT if ($arch == arm) +# Very slow on ARM and MIPS, contains no architecture dependent code. +unicode-case-overoptimization: PASS, TIMEOUT if ($arch == arm || $arch == mips) # Skip long running test in debug and allow it to timeout in release mode. regress/regress-524: (PASS || TIMEOUT), SKIP if $mode == debug @@ -64,6 +65,15 @@ regress/regress-524: (PASS || TIMEOUT), SKIP if $mode == debug debug-liveedit-check-stack: SKIP debug-liveedit-patch-positions-replace: SKIP +# Test Crankshaft compilation time. Expected to take too long in debug mode. +regress/regress-1969: PASS, SKIP if $mode == debug + +############################################################################## +[ $isolates ] + +# This test sets the umask on a per-process basis and hence cannot be +# used in multi-threaded runs. +d8-os: SKIP ############################################################################## [ $arch == arm ] @@ -119,11 +129,23 @@ regress/regress-1132: SKIP ############################################################################## [ $arch == mips ] -# Run those tests, but expect them to time out. -array-sort: PASS || TIMEOUT + +# Slow tests which times out in debug mode. +try: PASS, SKIP if $mode == debug +debug-scripts-request: PASS, SKIP if $mode == debug +array-constructor: PASS, SKIP if $mode == debug + +# Times out often in release mode on MIPS. +compiler/regress-stacktrace-methods: PASS, PASS || TIMEOUT if $mode == release +array-splice: PASS || TIMEOUT + +# Long running test. mirror-object: PASS || TIMEOUT +string-indexof-2: PASS || TIMEOUT -# Skip long-running tests. +# BUG(3251035): Timeouts in long looping crankshaft optimization +# tests. Skipping because having them timeout takes too long on the +# buildbot. compiler/alloc-number: SKIP compiler/array-length: SKIP compiler/assignment-deopt: SKIP @@ -148,12 +170,8 @@ regress/regress-634: SKIP regress/regress-create-exception: SKIP regress/regress-3218915: SKIP regress/regress-3247124: SKIP -regress/regress-1132: SKIP -regress/regress-1257: SKIP -regress/regress-91008: SKIP -############################################################################## -[ $isolates ] -# d8-os writes temporary files that might interfer with each other when running -# in multible threads. Skip this if running with isolates testing. -d8-os: SKIP +# Requires bigger stack size in the Genesis and if stack size is increased, +# the test requires too much time to run. However, the problem test covers +# should be platform-independent. +regress/regress-1132: SKIP diff --git a/test/mjsunit/number-is.js b/test/mjsunit/number-is.js new file mode 100644 index 00000000..1589fc64 --- /dev/null +++ b/test/mjsunit/number-is.js @@ -0,0 +1,58 @@ +// 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. + +// Test Harmony Number.isFinite() and Number.isNaN() functions. + +assertTrue(Number.isFinite(0)); +assertTrue(Number.isFinite(Number.MIN_VALUE)); +assertTrue(Number.isFinite(Number.MAX_VALUE)); +assertFalse(Number.isFinite(Number.NaN)); +assertFalse(Number.isFinite(Number.POSITIVE_INFINITY)); +assertFalse(Number.isFinite(Number.NEGATIVE_INFINITY)); +assertFalse(Number.isFinite(new Number(0))); +assertFalse(Number.isFinite(1/0)); +assertFalse(Number.isFinite(-1/0)); +assertFalse(Number.isFinite({})); +assertFalse(Number.isFinite([])); +assertFalse(Number.isFinite("s")); +assertFalse(Number.isFinite(null)); +assertFalse(Number.isFinite(undefined)); + +assertFalse(Number.isNaN(0)); +assertFalse(Number.isNaN(Number.MIN_VALUE)); +assertFalse(Number.isNaN(Number.MAX_VALUE)); +assertTrue(Number.isNaN(Number.NaN)); +assertFalse(Number.isNaN(Number.POSITIVE_INFINITY)); +assertFalse(Number.isNaN(Number.NEGATIVE_INFINITY)); +assertFalse(Number.isNaN(new Number(0))); +assertFalse(Number.isNaN(1/0)); +assertFalse(Number.isNaN(-1/0)); +assertFalse(Number.isNaN({})); +assertFalse(Number.isNaN([])); +assertFalse(Number.isNaN("s")); +assertFalse(Number.isNaN(null)); +assertFalse(Number.isNaN(undefined)); diff --git a/test/mjsunit/object-define-properties.js b/test/mjsunit/object-define-properties.js index 128df694..6d5032e0 100644 --- a/test/mjsunit/object-define-properties.js +++ b/test/mjsunit/object-define-properties.js @@ -54,3 +54,19 @@ var x = Object.defineProperties(obj, desc); assertEquals(x.foo, 10); assertEquals(x.bar, 42); + + +// Make sure that all property descriptors are calculated before any +// modifications are done. + +var object = {}; + +assertThrows(function() { + Object.defineProperties(object, { + foo: { value: 1 }, + bar: { value: 2, get: function() { return 3; } } + }); + }, TypeError); + +assertEquals(undefined, object.foo); +assertEquals(undefined, object.bar); diff --git a/test/mjsunit/object-define-property.js b/test/mjsunit/object-define-property.js index ee6083a8..fdaf82d1 100644 --- a/test/mjsunit/object-define-property.js +++ b/test/mjsunit/object-define-property.js @@ -1,4 +1,4 @@ -// Copyright 2010 the V8 project authors. All rights reserved. +// 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: @@ -503,7 +503,7 @@ try { // Defining properties null should fail even when we have // other allowed values try { - %DefineOrRedefineAccessorProperty(null, 'foo', 0, func, 0); + %DefineOrRedefineAccessorProperty(null, 'foo', func, null, 0); } catch (e) { assertTrue(/illegal access/.test(e)); } @@ -1053,4 +1053,35 @@ for (var i = 0; i < 1000; i++) { // Non-enumerable property forces dictionary mode. Object.defineProperty(o, i, {value: i, enumerable: false}); } -assertEquals(999, o[999]);
\ No newline at end of file +assertEquals(999, o[999]); + + +// Regression test: Bizzare behavior on non-strict arguments object. +(function test(arg0) { + // Here arguments[0] is a fast alias on arg0. + Object.defineProperty(arguments, "0", { + value:1, + enumerable:false + }); + // Here arguments[0] is a slow alias on arg0. + Object.defineProperty(arguments, "0", { + value:2, + writable:false + }); + // Here arguments[0] is no alias at all. + Object.defineProperty(arguments, "0", { + value:3 + }); + assertEquals(2, arg0); + assertEquals(3, arguments[0]); +})(0); + + +// Regression test: We should never observe the hole value. +var objectWithGetter = {}; +objectWithGetter.__defineGetter__('foo', function() {}); +assertEquals(undefined, objectWithGetter.__lookupSetter__('foo')); + +var objectWithSetter = {}; +objectWithSetter.__defineSetter__('foo', function(x) {}); +assertEquals(undefined, objectWithSetter.__lookupGetter__('foo')); diff --git a/test/mjsunit/object-is.js b/test/mjsunit/object-is.js new file mode 100644 index 00000000..b9fdc844 --- /dev/null +++ b/test/mjsunit/object-is.js @@ -0,0 +1,47 @@ +// 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. + +// Test both the Harmony egal operator and it's function equivalent. + +function TestEgal(expected, x, y) { + // TODO(mstarzinger): Once we have the egal operator, we can test it here. + assertSame(expected, Object.is(x, y)); +} + +var test_set = [ {}, [], 1/0, -1/0, "s", 0, 0/-1, null, undefined ]; +print(test_set); +for (var i = 0; i < test_set.length; i++) { + for (var j = 0; j < test_set.length; j++) { + if (i == j) { + assertSame(test_set[i], test_set[j]); + TestEgal(true, test_set[i], test_set[j]); + } else { + TestEgal(false, test_set[i], test_set[j]); + TestEgal(false, test_set[j], test_set[i]); + } + } +} diff --git a/test/mjsunit/object-prevent-extensions.js b/test/mjsunit/object-prevent-extensions.js index 322a2cb5..6b9184d8 100644 --- a/test/mjsunit/object-prevent-extensions.js +++ b/test/mjsunit/object-prevent-extensions.js @@ -114,3 +114,15 @@ Object.preventExtensions(foo); foo.x = 29; assertEquals(undefined, foo.x); + +// when Object.isExtensible(o) === false +// assignment should return right hand side value +var o = Object.preventExtensions({}); +var v = o.v = 50; +assertEquals(undefined, o.v); +assertEquals(50, v); + +// test same behavior as above, but for integer properties +var n = o[0] = 100; +assertEquals(undefined, o[0]); +assertEquals(100, n); diff --git a/test/mjsunit/optimized-typeof.js b/test/mjsunit/optimized-typeof.js new file mode 100644 index 00000000..b0c0725c --- /dev/null +++ b/test/mjsunit/optimized-typeof.js @@ -0,0 +1,47 @@ +// Copyright 2011 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 + +function typeofDirectly() { + return typeof({}) === "undefined"; +} + +typeofDirectly(); +typeofDirectly(); +%OptimizeFunctionOnNextCall(typeofDirectly); +typeofDirectly(); + +function typeofViaVariable() { + var foo = typeof({}) + return foo === "undefined"; +} + +typeofViaVariable(); +typeofViaVariable(); +%OptimizeFunctionOnNextCall(typeofViaVariable); +typeofViaVariable(); diff --git a/test/mjsunit/pixel-array-rounding.js b/test/mjsunit/pixel-array-rounding.js new file mode 100644 index 00000000..ef5a10bd --- /dev/null +++ b/test/mjsunit/pixel-array-rounding.js @@ -0,0 +1,44 @@ +// 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 + +var pixels = new PixelArray(8); + +function f() { + for (var i = 0; i < 8; i++) { + pixels[i] = (i * 1.1); + } + return pixels[1] + pixels[6]; +} + +f(); +f(); +assertEquals(6, pixels[5]); +%OptimizeFunctionOnNextCall(f); +f(); +assertEquals(6, pixels[5]); diff --git a/test/mjsunit/regexp-capture-3.js b/test/mjsunit/regexp-capture-3.js new file mode 100644 index 00000000..50e423ff --- /dev/null +++ b/test/mjsunit/regexp-capture-3.js @@ -0,0 +1,30 @@ +// 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. + +"abcd".replace(/b/g, function() { }); + +assertEquals("cd", RegExp.rightContext); diff --git a/test/mjsunit/regexp-static.js b/test/mjsunit/regexp-static.js index 0f849687..8f283f6c 100644 --- a/test/mjsunit/regexp-static.js +++ b/test/mjsunit/regexp-static.js @@ -25,18 +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. -// Test that we throw exceptions when calling test and exec with no -// input. This is not part of the spec, but we do it for -// compatibility with JSC. -assertThrows("/a/.test()"); -assertThrows("/a/.exec()"); - -// Test that we do not throw exceptions once the static RegExp.input -// field has been set. -RegExp.input = "a"; -assertDoesNotThrow("/a/.test()"); -assertDoesNotThrow("/a/.exec()"); - // Test the (deprecated as of JS 1.5) properties of the RegExp function. var re = /((\d+)\.(\d+))/; var s = 'abc123.456def'; @@ -166,3 +154,8 @@ assertTrue(typeof RegExp.input == typeof String(), "RegExp.input coerces values var foo = "lsdfj sldkfj sdklfj læsdfjl sdkfjlsdk fjsdl fjsdljskdj flsj flsdkj flskd regexp: /foobar/\nldkfj sdlkfj sdkl"; assertTrue(/^([a-z]+): (.*)/.test(foo.substring(foo.indexOf("regexp:"))), "regexp: setup"); assertEquals("regexp", RegExp.$1, "RegExp.$1"); + + +// Check that calling with no argument is the same as calling with undefined. +assertTrue(/^undefined$/.test()); +assertEquals(["undefined"], /^undefined$/.exec()); diff --git a/test/mjsunit/regexp.js b/test/mjsunit/regexp.js index 3c4f883b..ec82c96e 100644 --- a/test/mjsunit/regexp.js +++ b/test/mjsunit/regexp.js @@ -1,4 +1,4 @@ -// Copyright 2008 the V8 project authors. All rights reserved. +// 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: @@ -127,6 +127,17 @@ assertTrue(re.test("$")); assertTrue(/^[Z-\c-e]*$/.test("Z[\\cde")); +// Test that we handle \s and \S correctly on special Unicode characters. +re = /\s/; +assertTrue(re.test("\u2028")); +assertTrue(re.test("\u2029")); +assertTrue(re.test("\uFEFF")); + +re = /\S/; +assertFalse(re.test("\u2028")); +assertFalse(re.test("\u2029")); +assertFalse(re.test("\uFEFF")); + // Test that we handle \s and \S correctly inside some bizarre // character classes. re = /[\s-:]/; @@ -690,3 +701,7 @@ assertThrows("RegExp('(*)')"); assertThrows("RegExp('(?:*)')"); assertThrows("RegExp('(?=*)')"); assertThrows("RegExp('(?!*)')"); + +// Test trimmed regular expression for RegExp.test(). +assertTrue(/.*abc/.test("abc")); +assertFalse(/.*\d+/.test("q")); diff --git a/test/mjsunit/regress/regress-100702.js b/test/mjsunit/regress/regress-100702.js new file mode 100644 index 00000000..46494ab7 --- /dev/null +++ b/test/mjsunit/regress/regress-100702.js @@ -0,0 +1,44 @@ +// Copyright 2011 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. + +// Regression test for correct handling of non-object receiver values +// passed to built-in array functions. + +String.prototype.isThatMe = function () { + assertFalse(this === str); +}; + +var str = "abc"; +str.isThatMe(); +str.isThatMe.call(str); + +var arr = [1]; +arr.forEach("".isThatMe, str); +arr.filter("".isThatMe, str); +arr.some("".isThatMe, str); +arr.every("".isThatMe, str); +arr.map("".isThatMe, str); diff --git a/test/mjsunit/regress/regress-102153.js b/test/mjsunit/regress/regress-102153.js new file mode 100644 index 00000000..0f67656b --- /dev/null +++ b/test/mjsunit/regress/regress-102153.js @@ -0,0 +1,57 @@ +// 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: --expose-debug-as debug + +// Test that the break point is set before initializing the loop variable +// so that we break before any iteration has been run. + +Debug = debug.Debug; + +var break_hit = false; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + break_hit = true; + } +} + +Debug.setListener(listener); + +function test() { + for (var i = 0; i < 3; i++) { // Break here. + if (i == 0) break; + } +} + +Debug.setBreakPoint(test, 1, 0); + +assertTrue(Debug.showBreakPoints(test).indexOf("// Break here.") >= 0); + +test(); + +assertTrue(break_hit); diff --git a/test/mjsunit/regress/regress-108296.js b/test/mjsunit/regress/regress-108296.js new file mode 100644 index 00000000..38ecda77 --- /dev/null +++ b/test/mjsunit/regress/regress-108296.js @@ -0,0 +1,52 @@ +// Copyright 2011 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 + +// This test checks that young immediates embedded into code objects +// are referenced through a cell. + +function f (k, a, b) { + // Create control flow for a.foo. Control flow resolution will + // be generated as a part of a gap move. Gap move operate on immediates as + // a.foo is a CONSTANT_FUNCTION. + var x = k ? a.foo : a.foo; + return x.prototype; +} + +var a = { }; + +// Make sure that foo is a CONSTANT_FUNCTION but not be pretenured. +a.foo = (function () { return function () {}; })(); + +// Ensure that both branches of ternary operator have monomorphic type feedback. +f(true, a, a); +f(true, a, a); +f(false, a, a); +f(false, a, a); +%OptimizeFunctionOnNextCall(f); +f(true, a, a); diff --git a/test/mjsunit/regress/regress-109195.js b/test/mjsunit/regress/regress-109195.js new file mode 100644 index 00000000..97538aa1 --- /dev/null +++ b/test/mjsunit/regress/regress-109195.js @@ -0,0 +1,65 @@ +// 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: --expose-debug-as debug +var Debug = debug.Debug; + +function listener(event, exec_state, event_data, data) { + for (var i = 0, n = exec_state.frameCount(); i < n; i++) { + exec_state.frame().scopeCount(i); + } + exec_state.prepareStep(Debug.StepAction.Continue, 1); +} + +Debug.setListener(listener); + +var F = function () { + 1, function () { + var d = 0; + (function () { d; }); + debugger; + }(); +}; + +var src = "(" + F.toString() + ")()"; +eval(src); + +Function.prototype.__defineGetter__("f", function () { + debugger; + return 0; +}); + +var G = function () { + 1, function () { + var d = 0; + (function () { d; }); + debugger; + }['f']; +}; + +var src = "(" + G.toString() + ")()"; +eval(src); diff --git a/test/mjsunit/regress/regress-110509.js b/test/mjsunit/regress/regress-110509.js new file mode 100644 index 00000000..132bd233 --- /dev/null +++ b/test/mjsunit/regress/regress-110509.js @@ -0,0 +1,41 @@ +// 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 + +// Verify that LRandom preserves rsi correctly. + +function foo() { + Math.random(); + new Function(""); +} + +foo(); +foo(); +foo(); +%OptimizeFunctionOnNextCall(foo); +foo(); diff --git a/test/mjsunit/regress/regress-1110.js b/test/mjsunit/regress/regress-1110.js index 43b8d77a..124f520c 100644 --- a/test/mjsunit/regress/regress-1110.js +++ b/test/mjsunit/regress/regress-1110.js @@ -28,10 +28,9 @@ // Test that the illegal continue is thrown at parse time. try { - function Crash() { continue;if (Crash) { - } } + eval("function Crash() { assertUnreachable(); continue;if (Crash) { } }"); Crash(); - assertTrue(false); + assertUnreachable(); } catch (e) { assertTrue(e instanceof SyntaxError); assertTrue(/continue/.test(e.message)); diff --git a/test/mjsunit/regress/regress-113924.js b/test/mjsunit/regress/regress-113924.js new file mode 100644 index 00000000..3ecdec48 --- /dev/null +++ b/test/mjsunit/regress/regress-113924.js @@ -0,0 +1,31 @@ +// 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. + +var count=12000; +while(count--) { + eval("var a = new Object(10); a[2] += 7;"); +} diff --git a/test/mjsunit/regress/regress-115452.js b/test/mjsunit/regress/regress-115452.js new file mode 100644 index 00000000..7e424ed8 --- /dev/null +++ b/test/mjsunit/regress/regress-115452.js @@ -0,0 +1,48 @@ +// 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. + +// Test that a function declaration cannot overwrite a read-only property. + +print(0) +function foobl() {} +assertTrue(typeof this.foobl == "function"); +assertTrue(Object.getOwnPropertyDescriptor(this, "foobl").writable); + +print(1) +Object.defineProperty(this, "foobl", {value: 1, writable: false}); +assertSame(1, this.foobl); +assertFalse(Object.getOwnPropertyDescriptor(this, "foobl").writable); + +print(2) +eval("function foobl() {}"); +assertSame(1, this.foobl); +assertFalse(Object.getOwnPropertyDescriptor(this, "foobl").writable); + +print(3) +eval("function foobl() {}"); +assertSame(1, this.foobl); +assertFalse(Object.getOwnPropertyDescriptor(this, "foobl").writable); diff --git a/test/mjsunit/regress/regress-1170.js b/test/mjsunit/regress/regress-1170.js index 95684c54..66ed9f29 100644 --- a/test/mjsunit/regress/regress-1170.js +++ b/test/mjsunit/regress/regress-1170.js @@ -49,7 +49,7 @@ try { exception = true; assertTrue(/TypeError/.test(e)); } -assertTrue(exception); +assertFalse(exception); exception = false; try { diff --git a/test/mjsunit/regress/regress-117794.js b/test/mjsunit/regress/regress-117794.js new file mode 100644 index 00000000..5e11b400 --- /dev/null +++ b/test/mjsunit/regress/regress-117794.js @@ -0,0 +1,57 @@ +// 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. + +// Loads specialized to be from the global object should not omit the +// smi check on the receiver. The code below should not crash. + +print = function() {} + +function constructor() {}; + +function assertHasOwnProperties(object, limit) { + for (var i = 0; i < limit; i++) { } +} + +try { + Object.keys(); +} catch(exc2) { + print(exc2.stack); +} + +var x1 = new Object(); + +try { + new Function("A Man Called Horse", x1.d); +} catch(exc3) { + print(exc3.stack); +} + +try { + (-(true)).toPrecision(0x30, 'lib1-f1'); +} catch(exc1) { + print(exc1.stack); +} diff --git a/test/mjsunit/regress/regress-119429.js b/test/mjsunit/regress/regress-119429.js new file mode 100644 index 00000000..a8764875 --- /dev/null +++ b/test/mjsunit/regress/regress-119429.js @@ -0,0 +1,37 @@ +// 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 + +var d = 0; +function recurse() { + if (++d == 25135) { // A magic number just below stack overflow on ia32 + %DebugBreak(); + } + recurse(); +} +assertThrows(function() { recurse();} ); diff --git a/test/mjsunit/regress/regress-119925.js b/test/mjsunit/regress/regress-119925.js new file mode 100644 index 00000000..67127548 --- /dev/null +++ b/test/mjsunit/regress/regress-119925.js @@ -0,0 +1,34 @@ +// 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. + +// Test that the throw is not inlined if object literals cannot be +// inlined. +Array.prototype.__proto__ = { 77e4 : null }; +function continueWithinLoop() { + for (var key in [(1.2)]) { } +}; +continueWithinLoop(); diff --git a/test/mjsunit/regress/regress-1213575.js b/test/mjsunit/regress/regress-1213575.js index 9d82064e..f3a11dba 100644 --- a/test/mjsunit/regress/regress-1213575.js +++ b/test/mjsunit/regress/regress-1213575.js @@ -25,17 +25,16 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Make sure that a const definition always -// conflicts with a defined setter. This avoid -// trying to pass 'the hole' to the setter. +// Make sure that a const definition does not try +// to pass 'the hole' to a defined setter. -this.__defineSetter__('x', function(value) { assertTrue(false); }); +this.__defineSetter__('x', function(value) { assertTrue(value === 1); }); var caught = false; try { - eval('const x'); + eval('const x = 1'); } catch(e) { assertTrue(e instanceof TypeError); caught = true; } -assertTrue(caught); +assertFalse(caught); diff --git a/test/mjsunit/regress/regress-121407.js b/test/mjsunit/regress/regress-121407.js new file mode 100644 index 00000000..25033fb5 --- /dev/null +++ b/test/mjsunit/regress/regress-121407.js @@ -0,0 +1,40 @@ +// 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. + +var a = [0,1,2,3]; +a[2000000] = 2000000; +a.length=2000; +for (var i = 0; i <= 256; i++) { + a[i] = new Object(); +} + +a = [0.5,1.5,2.5,3.5,4.5,5.5]; +a[2000000] = 2000000; +a.length=2000; +for (var i = 0; i <= 256; i++) { + a[i] = new Object(); +}
\ No newline at end of file diff --git a/test/mjsunit/regress/regress-1217.js b/test/mjsunit/regress/regress-1217.js new file mode 100644 index 00000000..65305498 --- /dev/null +++ b/test/mjsunit/regress/regress-1217.js @@ -0,0 +1,50 @@ +// Copyright 2011 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. + +// Check that RegExp.prototype is itself a RegExp object. + +var proto = RegExp.prototype; +assertEquals("[object RegExp]", Object.prototype.toString.call(proto)); + +assertEquals("", proto.source); +assertEquals(false, proto.global); +assertEquals(false, proto.multiline); +assertEquals(false, proto.ignoreCase); +assertEquals(0, proto.lastIndex); + +assertEquals("/(?:)/", proto.toString()); + +var execResult = proto.exec("argle"); +assertEquals(1, execResult.length); +assertEquals("", execResult[0]); +assertEquals("argle", execResult.input); +assertEquals(0, execResult.index); + +assertTrue(proto.test("argle")); + +// We disallow re-compiling the RegExp.prototype object. +assertThrows(function(){ proto.compile("something"); }, TypeError); diff --git a/test/mjsunit/regress/regress-1229.js b/test/mjsunit/regress/regress-1229.js index e16d278b..5447f3f7 100644 --- a/test/mjsunit/regress/regress-1229.js +++ b/test/mjsunit/regress/regress-1229.js @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// 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: @@ -29,59 +29,118 @@ // Check that %NewObjectFromBound works correctly when called from optimized // frame. -function foo(x, y, z) { +function foo1(x, y, z) { assertEquals(1, x); assertEquals(2, y); assertEquals(3, z); } -var bound_arg = [1]; +function foo2(x, y, z) { + assertEquals(1, x); + assertEquals(2, y); + assertEquals(undefined, z); +} + +function foo3(x, y, z) { + assertEquals(1, x); + assertEquals(2, y); + assertEquals(3, z); +} -function f(y, z) { - return %NewObjectFromBound(foo, bound_arg); + +var foob1 = foo1.bind({}, 1); +var foob2 = foo2.bind({}, 1); +var foob3 = foo3.bind({}, 1); + + +function f1(y, z) { + return %NewObjectFromBound(foob1); +} + +function f2(y, z) { + return %NewObjectFromBound(foob2); +} + +function f3(y, z) { + return %NewObjectFromBound(foob3); } // Check that %NewObjectFromBound looks at correct frame for inlined function. -function g(z, y) { - return f(y, z); /* f should be inlined into g, note rotated arguments */ +function g1(z, y) { + return f1(y, z); /* f should be inlined into g, note rotated arguments */ +} + +function g2(z, y, x) { + return f2(y); /* f should be inlined into g, note argument count mismatch */ +} + +function g3(z, y, x) { + return f3(x, y, z); /* f should be inlined into g, note argument count mismatch */ } // Check that %NewObjectFromBound looks at correct frame for inlined function. function ff(x) { } -function h(z2, y2) { +function h1(z2, y2) { + var local_z = z2 >> 1; + ff(local_z); + var local_y = y2 >> 1; + ff(local_y); + return f1(local_y, local_z); /* f should be inlined into h */ +} + +function h2(z2, y2, x2) { + var local_z = z2 >> 1; + ff(local_z); + var local_y = y2 >> 1; + ff(local_y); + return f2(local_y); /* f should be inlined into h */ +} + +function h3(z2, y2, x2) { var local_z = z2 >> 1; ff(local_z); var local_y = y2 >> 1; ff(local_y); - return f(local_y, local_z); /* f should be inlined into h */ + var local_x = x2 >> 1; + ff(local_x); + return f3(local_x, local_y, local_z); /* f should be inlined into h */ } -for (var i = 0; i < 5; i++) f(2, 3); -%OptimizeFunctionOnNextCall(f); -f(2, 3); -for (var i = 0; i < 5; i++) g(3, 2); -%OptimizeFunctionOnNextCall(g); -g(3, 2); +function invoke(f, args) { + for (var i = 0; i < 5; i++) f.apply(this, args); + %OptimizeFunctionOnNextCall(f); + f.apply(this, args); +} -for (var i = 0; i < 5; i++) h(6, 4); -%OptimizeFunctionOnNextCall(h); -h(6, 4); +invoke(f1, [2, 3]); +invoke(f2, [2]); +invoke(f3, [2, 3, 4]); +invoke(g1, [3, 2]); +invoke(g2, [3, 2, 4]); +invoke(g3, [4, 3, 2]); +invoke(h1, [6, 4]); +invoke(h2, [6, 4, 8]); +invoke(h3, [8, 6, 4]); // Check that %_IsConstructCall returns correct value when inlined var NON_CONSTRUCT_MARKER = {}; var CONSTRUCT_MARKER = {}; -function baz() { +function baz(x) { return (!%_IsConstructCall()) ? NON_CONSTRUCT_MARKER : CONSTRUCT_MARKER; } function bar(x, y, z) { + var non_construct = baz(0); /* baz should be inlined */ + assertSame(non_construct, NON_CONSTRUCT_MARKER); var non_construct = baz(); /* baz should be inlined */ - assertEquals(non_construct, NON_CONSTRUCT_MARKER); - var construct = new baz(); - assertEquals(construct, CONSTRUCT_MARKER); + assertSame(non_construct, NON_CONSTRUCT_MARKER); + var non_construct = baz(0, 0); /* baz should be inlined */ + assertSame(non_construct, NON_CONSTRUCT_MARKER); + var construct = new baz(0); + assertSame(construct, CONSTRUCT_MARKER); + var construct = new baz(0, 0); + assertSame(construct, CONSTRUCT_MARKER); } -for (var i = 0; i < 5; i++) new bar(1, 2, 3); -%OptimizeFunctionOnNextCall(bar); -bar(1, 2, 3); +invoke(bar, [1, 2, 3]); diff --git a/test/mjsunit/regress/regress-1415.js b/test/mjsunit/regress/regress-1415.js new file mode 100644 index 00000000..f993e9b3 --- /dev/null +++ b/test/mjsunit/regress/regress-1415.js @@ -0,0 +1,42 @@ +// Copyright 2011 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. + +// Surrogate pair range. +// U+D800 +assertThrows(function(){ decodeURIComponent("%ED%A0%80"); }, URIError); +// U+DBFF +assertThrows(function(){ decodeURIComponent("%ED%AF%BF"); }, URIError); +// U+DC00 +assertThrows(function(){ decodeURIComponent("%ED%B0%80"); }, URIError); +// U+DFFF +assertThrows(function(){ decodeURIComponent("%ED%BF%BF"); }, URIError); + +// Overlong encodings +// U+007F in two bytes. +assertThrows(function(){ decodeURIComponent("%C1%BF"); }, URIError); +// U+07FF in three bytes. +assertThrows(function(){ decodeURIComponent("%E0%9F%BF"); }, URIError); diff --git a/test/mjsunit/regress/regress-1530.js b/test/mjsunit/regress/regress-1530.js new file mode 100644 index 00000000..db211445 --- /dev/null +++ b/test/mjsunit/regress/regress-1530.js @@ -0,0 +1,69 @@ +// Copyright 2011 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 that redefining the 'prototype' property of a function object +// does actually set the internal value and does not screw up any +// shadowing between said property and the internal value. + +var f = function() {}; + +// Verify that normal assignment of 'prototype' property works properly +// and updates the internal value. +var x = { foo: 'bar' }; +f.prototype = x; +assertSame(f.prototype, x); +assertSame(f.prototype.foo, 'bar'); +assertSame(new f().foo, 'bar'); +assertSame(Object.getPrototypeOf(new f()), x); +assertSame(Object.getOwnPropertyDescriptor(f, 'prototype').value, x); + +// Verify that 'prototype' behaves like a data property when it comes to +// redefining with Object.defineProperty() and the internal value gets +// updated. +var y = { foo: 'baz' }; +Object.defineProperty(f, 'prototype', { value: y, writable: true }); +assertSame(f.prototype, y); +assertSame(f.prototype.foo, 'baz'); +assertSame(new f().foo, 'baz'); +assertSame(Object.getPrototypeOf(new f()), y); +assertSame(Object.getOwnPropertyDescriptor(f, 'prototype').value, y); + +// Verify that the previous redefinition didn't screw up callbacks and +// the internal value still gets updated. +var z = { foo: 'other' }; +f.prototype = z; +assertSame(f.prototype, z); +assertSame(f.prototype.foo, 'other'); +assertSame(new f().foo, 'other'); +assertSame(Object.getPrototypeOf(new f()), z); +assertSame(Object.getOwnPropertyDescriptor(f, 'prototype').value, z); + +// Verify that non-writability of other properties is respected. +assertThrows("Object.defineProperty(f, 'name', { value: {} })"); +assertThrows("Object.defineProperty(f, 'length', { value: {} })"); +assertThrows("Object.defineProperty(f, 'caller', { value: {} })"); +assertThrows("Object.defineProperty(f, 'arguments', { value: {} })"); diff --git a/test/mjsunit/regress/regress-1624-strict.js b/test/mjsunit/regress/regress-1624-strict.js new file mode 100644 index 00000000..8bc58d5a --- /dev/null +++ b/test/mjsunit/regress/regress-1624-strict.js @@ -0,0 +1,140 @@ +// 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. + +// Test that global eval calls of strict code (independent from whether being +// direct or indirect) have their own lexical and variable environment. + +"use strict"; +var evil = eval; + +// Test global direct strict eval in strict script. +// Expects new environment. +var no_touch = 0; +eval('"use strict"; var no_touch = 1;'); +assertSame(0, no_touch); + +// Test global indirect strict eval in strict script. +// Expects new environment. +var no_touch = 0; +evil('"use strict"; var no_touch = 2;'); +assertSame(0, no_touch); + +// Test global direct non-strict eval in strict script. +// Expects new environment. +var no_touch = 0; +eval('var no_touch = 3;'); +assertSame(0, no_touch); + +// Test global indirect non-strict eval in strict script. +// Expects global environment. +var no_touch = 0; +evil('var no_touch = 4;'); +assertSame(4, no_touch); + +// Test non-global direct strict eval in strict script. +// Expects new environment. +var no_touch = 0; +(function() { + var no_touch = 0; + eval('"use strict"; var no_touch = 5;'); + assertSame(0, no_touch); +})() +assertSame(0, no_touch); + +// Test non-global indirect strict eval in strict script. +// Expects new environment. +var no_touch = 0; +(function() { + var no_touch = 0; + evil('"use strict"; var no_touch = 6;'); + assertSame(0, no_touch); +})() +assertSame(0, no_touch); + +// Test non-global direct non-strict eval in strict script. +// Expects new environment. +var no_touch = 0; +(function() { + var no_touch = 0; + eval('var no_touch = 7;'); + assertSame(0, no_touch); +})() +assertSame(0, no_touch); + +// Test non-global indirect non-strict eval in strict script. +// Expects global environment. +var no_touch = 0; +(function() { + var no_touch = 0; + evil('var no_touch = 8;'); + assertSame(0, no_touch); +})() +assertSame(8, no_touch); + +// Test non-global direct strict eval in strict script. +// Expects new environment. +var no_touch = 0; +(function() { + "use strict"; + var no_touch = 0; + eval('"use strict"; var no_touch = 9;'); + assertSame(0, no_touch); +})() +assertSame(0, no_touch); + +// Test non-global indirect strict eval in strict script. +// Expects new environment. +var no_touch = 0; +(function() { + "use strict"; + var no_touch = 0; + evil('"use strict"; var no_touch = 10;'); + assertSame(0, no_touch); +})() +assertSame(0, no_touch); + +// Test non-global direct non-strict eval in strict script. +// Expects new environment. +var no_touch = 0; +(function() { + "use strict"; + var no_touch = 0; + eval('var no_touch = 11;'); + assertSame(0, no_touch); +})() +assertSame(0, no_touch); + +// Test non-global indirect non-strict eval in strict script. +// Expects global environment. +var no_touch = 0; +(function() { + "use strict"; + var no_touch = 0; + evil('var no_touch = 12;'); + assertSame(0, no_touch); +})() +assertSame(12, no_touch); diff --git a/test/mjsunit/regress/regress-1624.js b/test/mjsunit/regress/regress-1624.js new file mode 100644 index 00000000..987e036d --- /dev/null +++ b/test/mjsunit/regress/regress-1624.js @@ -0,0 +1,139 @@ +// 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. + +// Test that global eval calls of strict code (independent from whether being +// direct or indirect) have their own lexical and variable environment. + +var evil = eval; + +// Test global direct strict eval. +// Expects new environment. +var no_touch = 0; +eval('"use strict"; var no_touch = 1;'); +assertSame(0, no_touch); + +// Test global indirect strict eval. +// Expects new environment. +var no_touch = 0; +evil('"use strict"; var no_touch = 2;'); +assertSame(0, no_touch); + +// Test global direct non-strict eval. +// Expects global environment. +var no_touch = 0; +eval('var no_touch = 3;'); +assertSame(3, no_touch); + +// Test global indirect non-strict eval. +// Expects global environment. +var no_touch = 0; +evil('var no_touch = 4;'); +assertSame(4, no_touch); + +// Test non-global direct strict eval in non-strict function. +// Expects new environment. +var no_touch = 0; +(function() { + var no_touch = 0; + eval('"use strict"; var no_touch = 5;'); + assertSame(0, no_touch); +})() +assertSame(0, no_touch); + +// Test non-global indirect strict eval in non-strict function. +// Expects new environment. +var no_touch = 0; +(function() { + var no_touch = 0; + evil('"use strict"; var no_touch = 6;'); + assertSame(0, no_touch); +})() +assertSame(0, no_touch); + +// Test non-global direct non-strict eval in non-strict function. +// Expects function environment. +var no_touch = 0; +(function() { + var no_touch = 0; + eval('var no_touch = 7;'); + assertSame(7, no_touch); +})() +assertSame(0, no_touch); + +// Test non-global indirect non-strict eval in non-strict function. +// Expects global environment. +var no_touch = 0; +(function() { + var no_touch = 0; + evil('var no_touch = 8;'); + assertSame(0, no_touch); +})() +assertSame(8, no_touch); + +// Test non-global direct strict eval in strict function. +// Expects new environment. +var no_touch = 0; +(function() { + "use strict"; + var no_touch = 0; + eval('"use strict"; var no_touch = 9;'); + assertSame(0, no_touch); +})() +assertSame(0, no_touch); + +// Test non-global indirect strict eval in strict function. +// Expects new environment. +var no_touch = 0; +(function() { + "use strict"; + var no_touch = 0; + evil('"use strict"; var no_touch = 10;'); + assertSame(0, no_touch); +})() +assertSame(0, no_touch); + +// Test non-global direct non-strict eval in strict function. +// Expects new environment. +var no_touch = 0; +(function() { + "use strict"; + var no_touch = 0; + eval('var no_touch = 11;'); + assertSame(0, no_touch); +})() +assertSame(0, no_touch); + +// Test non-global indirect non-strict eval in strict function. +// Expects global environment. +var no_touch = 0; +(function() { + "use strict"; + var no_touch = 0; + evil('var no_touch = 12;'); + assertSame(0, no_touch); +})() +assertSame(12, no_touch); diff --git a/test/mjsunit/regress/regress-1639-2.js b/test/mjsunit/regress/regress-1639-2.js new file mode 100644 index 00000000..c439dd8f --- /dev/null +++ b/test/mjsunit/regress/regress-1639-2.js @@ -0,0 +1,93 @@ +// Copyright 2011 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: --expose-debug-as debug +// Get the Debug object exposed from the debug context global object. +Debug = debug.Debug + +function sendCommand(state, cmd) { + // Get the debug command processor in paused state. + var dcp = state.debugCommandProcessor(false); + var request = JSON.stringify(cmd); + var response = dcp.processDebugJSONRequest(request); +} + +var state = 0; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + var line = event_data.sourceLineText(); + print('break: ' + line); + print('event data: ' + event_data.toJSONProtocol()); + print(); + assertEquals('// BREAK', line.substr(-8), + "should not break outside evaluate"); + + switch (state) { + case 0: + state = 1; + // While in the debugger and stepping through a set of instructions + // executed in the evaluate command, the stepping must stop at the end + // of the said set of instructions and not step further into native + // debugger code. + sendCommand(exec_state, { + seq : 0, + type : "request", + command : "evaluate", + arguments : { + 'expression' : 'print("A"); debugger; print("B"); // BREAK', + 'global' : true + } + }); + break; + case 1: + sendCommand(exec_state, { + seq : 0, + type : "request", + command : "continue", + arguments : { + stepaction : "next" + } + }); + break; + } + } + } catch (e) { + print(e); + } +} + +// Add the debug event listener. +Debug.setListener(listener); + +function a() { +} // BREAK + +// Set a break point and call to invoke the debug event listener. +Debug.setBreakPoint(a, 0, 0); +a(); diff --git a/test/mjsunit/regress/regress-1692.js b/test/mjsunit/regress/regress-1692.js new file mode 100644 index 00000000..06bd66cf --- /dev/null +++ b/test/mjsunit/regress/regress-1692.js @@ -0,0 +1,89 @@ +// Copyright 2011 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 that Object.prototype.propertyIsEnumerable handles array indices +// correctly. + +var p = Object.create({}, { + a : { value : 42, enumerable : true }, + b : { value : 42, enumerable : false }, + 1 : { value : 42, enumerable : true }, + 2 : { value : 42, enumerable : false }, + f : { get: function(){}, enumerable: true }, + g : { get: function(){}, enumerable: false }, + 11 : { get: function(){}, enumerable: true }, + 12 : { get: function(){}, enumerable: false } +}); +var o = Object.create(p, { + c : { value : 42, enumerable : true }, + d : { value : 42, enumerable : false }, + 3 : { value : 42, enumerable : true }, + 4 : { value : 42, enumerable : false }, + h : { get: function(){}, enumerable: true }, + k : { get: function(){}, enumerable: false }, + 13 : { get: function(){}, enumerable: true }, + 14 : { get: function(){}, enumerable: false } +}); + +// Inherited properties are ignored. +assertFalse(o.propertyIsEnumerable("a")); +assertFalse(o.propertyIsEnumerable("b")); +assertFalse(o.propertyIsEnumerable("1")); +assertFalse(o.propertyIsEnumerable("2")); + +// Own properties. +assertTrue(o.propertyIsEnumerable("c")); +assertFalse(o.propertyIsEnumerable("d")); +assertTrue(o.propertyIsEnumerable("3")); +assertFalse(o.propertyIsEnumerable("4")); + +// Inherited accessors. +assertFalse(o.propertyIsEnumerable("f")); +assertFalse(o.propertyIsEnumerable("g")); +assertFalse(o.propertyIsEnumerable("11")); +assertFalse(o.propertyIsEnumerable("12")); + +// Own accessors. +assertTrue(o.propertyIsEnumerable("h")); +assertFalse(o.propertyIsEnumerable("k")); +assertTrue(o.propertyIsEnumerable("13")); +assertFalse(o.propertyIsEnumerable("14")); + +// Nonexisting properties. +assertFalse(o.propertyIsEnumerable("xxx")); +assertFalse(o.propertyIsEnumerable("999")); + +// String object properties. +var o = Object("string"); +// Non-string property on String object. +o[10] = 42; +assertTrue(o.propertyIsEnumerable(10)); +assertFalse(o.propertyIsEnumerable(0)); + +// Fast elements. +var o = [1,2,3,4,5]; +assertTrue(o.propertyIsEnumerable(3)); diff --git a/test/mjsunit/regress/regress-1708.js b/test/mjsunit/regress/regress-1708.js new file mode 100644 index 00000000..ab50e078 --- /dev/null +++ b/test/mjsunit/regress/regress-1708.js @@ -0,0 +1,63 @@ +// Copyright 2011 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. + +// Regression test of a very rare corner case where left-trimming an +// array caused invalid marking bit patterns on lazily swept pages. + +// Flags: --expose-gc --noincremental-marking --max-new-space-size 1000 + +(function() { + var head = new Array(1); + var tail = head; + + // Fill heap to increase old-space size and trigger lazy sweeping on + // some of the old-space pages. + for (var i = 0; i < 200; i++) { + tail[1] = new Array(1000); + tail = tail[1]; + } + array = new Array(100); + gc(); gc(); + + // At this point "array" should have been promoted to old-space and be + // located in a lazy swept page with intact marking bits. Now shift + // the array to trigger left-trimming operations. + assertEquals(100, array.length); + for (var i = 0; i < 50; i++) { + array.shift(); + } + assertEquals(50, array.length); + + // At this point "array" should have been trimmed from the left with + // marking bits being correctly transfered to the new object start. + // Scavenging operations cause lazy sweeping to advance and verify + // that marking bit patterns are still sane. + for (var i = 0; i < 200; i++) { + tail[1] = new Array(1000); + tail = tail[1]; + } +})(); diff --git a/test/mjsunit/regress/regress-1711.js b/test/mjsunit/regress/regress-1711.js new file mode 100644 index 00000000..15591b1e --- /dev/null +++ b/test/mjsunit/regress/regress-1711.js @@ -0,0 +1,38 @@ +// Copyright 2011 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. + +// string.split needs to evaluate the separator's toString even if limit +// is 0 because toString may have side effects. + +var side_effect = false; +var separator = new Object(); +separator.toString = function() { + side_effect = true; + return undefined; +} +'subject'.split(separator, 0); +assertTrue(side_effect); diff --git a/test/mjsunit/regress/regress-1713.js b/test/mjsunit/regress/regress-1713.js new file mode 100644 index 00000000..0af1144a --- /dev/null +++ b/test/mjsunit/regress/regress-1713.js @@ -0,0 +1,127 @@ +// Copyright 2011 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 --always-compact --expose-gc + +var O = { get f() { return 0; } }; + +var CODE = []; + +var R = []; + +function Allocate4Kb(N) { + var arr = []; + do {arr.push(new Array(1024));} while (--N > 0); + return arr; +} + +function AllocateXMb(X) { + return Allocate4Kb((1024 * X) / 4); +} + +function Node(v, next) { this.v = v; this.next = next; } + +Node.prototype.execute = function (O) { + var n = this; + while (n.next !== null) n = n.next; + n.v(O); +}; + +function LongList(N, x) { + if (N == 0) return new Node(x, null); + return new Node(new Array(1024), LongList(N - 1, x)); +} + +var L = LongList(1024, function (O) { + for (var i = 0; i < 5; i++) O.f; +}); + + + +function Incremental(O, x) { + if (!x) { + return; + } + function CreateCode(i) { + var f = new Function("return O.f_" + i); + CODE.push(f); + f(); // compile + f(); // compile + f(); // compile + } + + for (var i = 0; i < 1e4; i++) CreateCode(i); + gc(); + gc(); + gc(); + + print(">>> 1 <<<"); + + L.execute(O); + + try {} catch (e) {} + + L = null; + print(">>> 2 <<<"); + AllocateXMb(8); + //rint("1"); + //llocateXMb(8); + //rint("1"); + //llocateXMb(8); + +} + +function foo(O, x) { + Incremental(O, x); + + print('f'); + + for (var i = 0; i < 5; i++) O.f; + + + print('g'); + + bar(x); +} + +function bar(x) { + if (!x) return; + %DeoptimizeFunction(foo); + AllocateXMb(8); + AllocateXMb(8); +} + +var O1 = {}; +var O2 = {}; +var O3 = {}; +var O4 = {f:0}; + +foo(O1, false); +foo(O2, false); +foo(O3, false); +%OptimizeFunctionOnNextCall(foo); +foo(O4, true); diff --git a/test/mjsunit/regress/regress-1748.js b/test/mjsunit/regress/regress-1748.js new file mode 100644 index 00000000..e287e554 --- /dev/null +++ b/test/mjsunit/regress/regress-1748.js @@ -0,0 +1,35 @@ +// Copyright 2011 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 that /^/ only matches at beginning of string. +// Bug in x64 caused it to match when executing the RegExp on a part +// of a string that starts at a multiplum of 256. + +var str = Array(10000).join("X"); +str.replace(/^|X/g, function(m, i, s) { + if (i > 0) assertEquals("X", m, "at position 0x" + i.toString(16)); +});
\ No newline at end of file diff --git a/test/mjsunit/regress/regress-1757.js b/test/mjsunit/regress/regress-1757.js new file mode 100644 index 00000000..f7a5516c --- /dev/null +++ b/test/mjsunit/regress/regress-1757.js @@ -0,0 +1,32 @@ +// Copyright 2011 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: --string-slices --expose-externalize-string + +var a = "abcdefghijklmnopqrstuvqxy"+"z"; +externalizeString(a, true); +assertEquals('b', a.substring(1).charAt(0));
\ No newline at end of file diff --git a/test/mjsunit/regress/regress-1790.js b/test/mjsunit/regress/regress-1790.js new file mode 100644 index 00000000..8848eeaf --- /dev/null +++ b/test/mjsunit/regress/regress-1790.js @@ -0,0 +1,58 @@ +// 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. + +// Regression test checking that the sequence of element access in built-in +// array functions is specification conform (i.e. [[HasProperty]] might return +// bogus result after [[Get]] has been called). + +function CheckSequence(builtin, callback) { + var array = [1,2,3]; + var callback_count = 0; + var callback_wrapper = function() { + callback_count++; + return callback() + } + + // Define getter that will delete itself upon first invocation. + Object.defineProperty(array, '1', { + get: function () { delete array[1]; }, + configurable: true + }); + + assertTrue(array.hasOwnProperty('1')); + builtin.apply(array, [callback_wrapper, 'argument']); + assertFalse(array.hasOwnProperty('1')); + assertEquals(3, callback_count); +} + +CheckSequence(Array.prototype.every, function() { return true; }); +CheckSequence(Array.prototype.filter, function() { return true; }); +CheckSequence(Array.prototype.forEach, function() { return 0; }); +CheckSequence(Array.prototype.map, function() { return 0; }); +CheckSequence(Array.prototype.reduce, function() { return 0; }); +CheckSequence(Array.prototype.reduceRight, function() { return 0; }); +CheckSequence(Array.prototype.some, function() { return false; }); diff --git a/test/mjsunit/regress/regress-1849.js b/test/mjsunit/regress/regress-1849.js new file mode 100644 index 00000000..176f918b --- /dev/null +++ b/test/mjsunit/regress/regress-1849.js @@ -0,0 +1,39 @@ +// Copyright 2011 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. + +// See: http://code.google.com/p/v8/issues/detail?id=1878 + +// Flags: --allow-natives-syntax + +var count = 1e5; +var arr = new Array(count); +assertFalse(%HasFastDoubleElements(arr)); +for (var i = 0; i < count; i++) { + arr[i] = 0; +} +assertFalse(%HasFastDoubleElements(arr)); +assertTrue(%HasFastSmiOnlyElements(arr)); diff --git a/test/mjsunit/regress/regress-1853.js b/test/mjsunit/regress/regress-1853.js new file mode 100644 index 00000000..f80badec --- /dev/null +++ b/test/mjsunit/regress/regress-1853.js @@ -0,0 +1,116 @@ +// 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: --expose-debug-as debug + +// Test whether scripts compiled after setting the break point are +// updated correctly. + +Debug = debug.Debug; + +var break_count = 0; +var test_break_1 = false; +var test_break_2 = false; + +function sendCommand(state, cmd) { + // Get the debug command processor in paused state. + var dcp = state.debugCommandProcessor(false); + var request = JSON.stringify(cmd); + var response = dcp.processDebugJSONRequest(request); + return JSON.parse(response); +} + +function setBreakPointByName(state) { + sendCommand(state, { + seq: 0, + type: "request", + command: "setbreakpoint", + arguments: { + type: "script", + target: "testScriptOne", + line: 2 + } + }); +} + +function setBreakPointByRegExp(state) { + sendCommand(state, { + seq: 0, + type: "request", + command: "setbreakpoint", + arguments: { + type: "scriptRegExp", + target: "Scrip.Two", + line: 2 + } + }); +} + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + switch (break_count) { + case 0: + // Set break points before the code has been compiled. + setBreakPointByName(exec_state); + setBreakPointByRegExp(exec_state); + break; + case 1: + // Set the flag to prove that we hit the first break point. + test_break_1 = true; + break; + case 2: + // Set the flag to prove that we hit the second break point. + test_break_2 = true; + break; + } + break_count++; + } + } catch (e) { + print(e); + } +} + +Debug.setListener(listener); +debugger; + +eval('function test1() { \n' + + ' assertFalse(test_break_1); \n' + + ' assertTrue(test_break_1); \n' + + '} \n' + + '//@ sourceURL=testScriptOne'); + +eval('function test2() { \n' + + ' assertFalse(test_break_2); \n' + + ' assertTrue(test_break_2); \n' + + '} \n' + + '//@ sourceURL=testScriptTwo'); + +test1(); +test2(); +assertEquals(3, break_count); + diff --git a/test/mjsunit/regress/regress-1878.js b/test/mjsunit/regress/regress-1878.js new file mode 100644 index 00000000..a1648b12 --- /dev/null +++ b/test/mjsunit/regress/regress-1878.js @@ -0,0 +1,44 @@ +// 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. + +// See: http://code.google.com/p/v8/issues/detail?id=1878 + +// Flags: --allow-natives-syntax --expose_natives_as=natives + +var a = Array(); + +for (var i = 0; i < 1000; i++) { + var ai = natives.InternalArray(10000); + assertFalse(%HaveSameMap(ai, a)); + assertTrue(%HasFastElements(ai)); +} + +for (var i = 0; i < 1000; i++) { + var ai = new natives.InternalArray(10000); + assertFalse(%HaveSameMap(ai, a)); + assertTrue(%HasFastElements(ai)); +} diff --git a/test/mjsunit/regress/regress-1898.js b/test/mjsunit/regress/regress-1898.js new file mode 100644 index 00000000..5440446f --- /dev/null +++ b/test/mjsunit/regress/regress-1898.js @@ -0,0 +1,37 @@ +// 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 + +function f(x) { + Math.log(Math.min(0.1, Math.abs(x))); +} + +f(0.1); +f(0.1); +%OptimizeFunctionOnNextCall(f); +f(0.1); diff --git a/test/mjsunit/regress/regress-1924.js b/test/mjsunit/regress/regress-1924.js new file mode 100644 index 00000000..80395414 --- /dev/null +++ b/test/mjsunit/regress/regress-1924.js @@ -0,0 +1,42 @@ +// 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. + +// For http://code.google.com/p/v8/issues/detail?id=1924 + +a: break a; +a: b: break a; +a: b: break b; +assertThrows("a: break a a", SyntaxError) +assertThrows("a: break a 1", SyntaxError) +assertThrows("a: break a ''", SyntaxError) +assertThrows("a: break a var b", SyntaxError) +assertThrows("a: break a {}", SyntaxError) + +a: if (0) break a; +b: if (0) {break b;} else {} +c: if (0) break c; else {} +d: if (0) break d; else break d; diff --git a/test/mjsunit/regress/regress-1945.js b/test/mjsunit/regress/regress-1945.js new file mode 100644 index 00000000..bffc775f --- /dev/null +++ b/test/mjsunit/regress/regress-1945.js @@ -0,0 +1,34 @@ +// 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 + +var _d = new Date(); +_d.setHours(0,0,0,0); +_d.setHours(0,0,0,0); +%OptimizeFunctionOnNextCall(_d.setHours); +_d.setHours(0,0,0,0); diff --git a/test/mjsunit/regress/regress-1969.js b/test/mjsunit/regress/regress-1969.js new file mode 100644 index 00000000..2728c2ca --- /dev/null +++ b/test/mjsunit/regress/regress-1969.js @@ -0,0 +1,5045 @@ +// 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 + +f(); +f(); +%OptimizeFunctionOnNextCall(f); +var start = (new Date()).getTime(); +var array = f(); +var end = (new Date()).getTime(); + +// Assert that recompiling and executing f() takes less than a second. +assertTrue((end - start) < 1000); + +for (var i = 0; i < 5000; i++) assertEquals(0, array[i]); + +function f() { + var a = new Array(5000); + a[0]=0; + a[1]=0; + a[2]=0; + a[3]=0; + a[4]=0; + a[5]=0; + a[6]=0; + a[7]=0; + a[8]=0; + a[9]=0; + a[10]=0; + a[11]=0; + a[12]=0; + a[13]=0; + a[14]=0; + a[15]=0; + a[16]=0; + a[17]=0; + a[18]=0; + a[19]=0; + a[20]=0; + a[21]=0; + a[22]=0; + a[23]=0; + a[24]=0; + a[25]=0; + a[26]=0; + a[27]=0; + a[28]=0; + a[29]=0; + a[30]=0; + a[31]=0; + a[32]=0; + a[33]=0; + a[34]=0; + a[35]=0; + a[36]=0; + a[37]=0; + a[38]=0; + a[39]=0; + a[40]=0; + a[41]=0; + a[42]=0; + a[43]=0; + a[44]=0; + a[45]=0; + a[46]=0; + a[47]=0; + a[48]=0; + a[49]=0; + a[50]=0; + a[51]=0; + a[52]=0; + a[53]=0; + a[54]=0; + a[55]=0; + a[56]=0; + a[57]=0; + a[58]=0; + a[59]=0; + a[60]=0; + a[61]=0; + a[62]=0; + a[63]=0; + a[64]=0; + a[65]=0; + a[66]=0; + a[67]=0; + a[68]=0; + a[69]=0; + a[70]=0; + a[71]=0; + a[72]=0; + a[73]=0; + a[74]=0; + a[75]=0; + a[76]=0; + a[77]=0; + a[78]=0; + a[79]=0; + a[80]=0; + a[81]=0; + a[82]=0; + a[83]=0; + a[84]=0; + a[85]=0; + a[86]=0; + a[87]=0; + a[88]=0; + a[89]=0; + a[90]=0; + a[91]=0; + a[92]=0; + a[93]=0; + a[94]=0; + a[95]=0; + a[96]=0; + a[97]=0; + a[98]=0; + a[99]=0; + a[100]=0; + a[101]=0; + a[102]=0; + a[103]=0; + a[104]=0; + a[105]=0; + a[106]=0; + a[107]=0; + a[108]=0; + a[109]=0; + a[110]=0; + a[111]=0; + a[112]=0; + a[113]=0; + a[114]=0; + a[115]=0; + a[116]=0; + a[117]=0; + a[118]=0; + a[119]=0; + a[120]=0; + a[121]=0; + a[122]=0; + a[123]=0; + a[124]=0; + a[125]=0; + a[126]=0; + a[127]=0; + a[128]=0; + a[129]=0; + a[130]=0; + a[131]=0; + a[132]=0; + a[133]=0; + a[134]=0; + a[135]=0; + a[136]=0; + a[137]=0; + a[138]=0; + a[139]=0; + a[140]=0; + a[141]=0; + a[142]=0; + a[143]=0; + a[144]=0; + a[145]=0; + a[146]=0; + a[147]=0; + a[148]=0; + a[149]=0; + a[150]=0; + a[151]=0; + a[152]=0; + a[153]=0; + a[154]=0; + a[155]=0; + a[156]=0; + a[157]=0; + a[158]=0; + a[159]=0; + a[160]=0; + a[161]=0; + a[162]=0; + a[163]=0; + a[164]=0; + a[165]=0; + a[166]=0; + a[167]=0; + a[168]=0; + a[169]=0; + a[170]=0; + a[171]=0; + a[172]=0; + a[173]=0; + a[174]=0; + a[175]=0; + a[176]=0; + a[177]=0; + a[178]=0; + a[179]=0; + a[180]=0; + a[181]=0; + a[182]=0; + a[183]=0; + a[184]=0; + a[185]=0; + a[186]=0; + a[187]=0; + a[188]=0; + a[189]=0; + a[190]=0; + a[191]=0; + a[192]=0; + a[193]=0; + a[194]=0; + a[195]=0; + a[196]=0; + a[197]=0; + a[198]=0; + a[199]=0; + a[200]=0; + a[201]=0; + a[202]=0; + a[203]=0; + a[204]=0; + a[205]=0; + a[206]=0; + a[207]=0; + a[208]=0; + a[209]=0; + a[210]=0; + a[211]=0; + a[212]=0; + a[213]=0; + a[214]=0; + a[215]=0; + a[216]=0; + a[217]=0; + a[218]=0; + a[219]=0; + a[220]=0; + a[221]=0; + a[222]=0; + a[223]=0; + a[224]=0; + a[225]=0; + a[226]=0; + a[227]=0; + a[228]=0; + a[229]=0; + a[230]=0; + a[231]=0; + a[232]=0; + a[233]=0; + a[234]=0; + a[235]=0; + a[236]=0; + a[237]=0; + a[238]=0; + a[239]=0; + a[240]=0; + a[241]=0; + a[242]=0; + a[243]=0; + a[244]=0; + a[245]=0; + a[246]=0; + a[247]=0; + a[248]=0; + a[249]=0; + a[250]=0; + a[251]=0; + a[252]=0; + a[253]=0; + a[254]=0; + a[255]=0; + a[256]=0; + a[257]=0; + a[258]=0; + a[259]=0; + a[260]=0; + a[261]=0; + a[262]=0; + a[263]=0; + a[264]=0; + a[265]=0; + a[266]=0; + a[267]=0; + a[268]=0; + a[269]=0; + a[270]=0; + a[271]=0; + a[272]=0; + a[273]=0; + a[274]=0; + a[275]=0; + a[276]=0; + a[277]=0; + a[278]=0; + a[279]=0; + a[280]=0; + a[281]=0; + a[282]=0; + a[283]=0; + a[284]=0; + a[285]=0; + a[286]=0; + a[287]=0; + a[288]=0; + a[289]=0; + a[290]=0; + a[291]=0; + a[292]=0; + a[293]=0; + a[294]=0; + a[295]=0; + a[296]=0; + a[297]=0; + a[298]=0; + a[299]=0; + a[300]=0; + a[301]=0; + a[302]=0; + a[303]=0; + a[304]=0; + a[305]=0; + a[306]=0; + a[307]=0; + a[308]=0; + a[309]=0; + a[310]=0; + a[311]=0; + a[312]=0; + a[313]=0; + a[314]=0; + a[315]=0; + a[316]=0; + a[317]=0; + a[318]=0; + a[319]=0; + a[320]=0; + a[321]=0; + a[322]=0; + a[323]=0; + a[324]=0; + a[325]=0; + a[326]=0; + a[327]=0; + a[328]=0; + a[329]=0; + a[330]=0; + a[331]=0; + a[332]=0; + a[333]=0; + a[334]=0; + a[335]=0; + a[336]=0; + a[337]=0; + a[338]=0; + a[339]=0; + a[340]=0; + a[341]=0; + a[342]=0; + a[343]=0; + a[344]=0; + a[345]=0; + a[346]=0; + a[347]=0; + a[348]=0; + a[349]=0; + a[350]=0; + a[351]=0; + a[352]=0; + a[353]=0; + a[354]=0; + a[355]=0; + a[356]=0; + a[357]=0; + a[358]=0; + a[359]=0; + a[360]=0; + a[361]=0; + a[362]=0; + a[363]=0; + a[364]=0; + a[365]=0; + a[366]=0; + a[367]=0; + a[368]=0; + a[369]=0; + a[370]=0; + a[371]=0; + a[372]=0; + a[373]=0; + a[374]=0; + a[375]=0; + a[376]=0; + a[377]=0; + a[378]=0; + a[379]=0; + a[380]=0; + a[381]=0; + a[382]=0; + a[383]=0; + a[384]=0; + a[385]=0; + a[386]=0; + a[387]=0; + a[388]=0; + a[389]=0; + a[390]=0; + a[391]=0; + a[392]=0; + a[393]=0; + a[394]=0; + a[395]=0; + a[396]=0; + a[397]=0; + a[398]=0; + a[399]=0; + a[400]=0; + a[401]=0; + a[402]=0; + a[403]=0; + a[404]=0; + a[405]=0; + a[406]=0; + a[407]=0; + a[408]=0; + a[409]=0; + a[410]=0; + a[411]=0; + a[412]=0; + a[413]=0; + a[414]=0; + a[415]=0; + a[416]=0; + a[417]=0; + a[418]=0; + a[419]=0; + a[420]=0; + a[421]=0; + a[422]=0; + a[423]=0; + a[424]=0; + a[425]=0; + a[426]=0; + a[427]=0; + a[428]=0; + a[429]=0; + a[430]=0; + a[431]=0; + a[432]=0; + a[433]=0; + a[434]=0; + a[435]=0; + a[436]=0; + a[437]=0; + a[438]=0; + a[439]=0; + a[440]=0; + a[441]=0; + a[442]=0; + a[443]=0; + a[444]=0; + a[445]=0; + a[446]=0; + a[447]=0; + a[448]=0; + a[449]=0; + a[450]=0; + a[451]=0; + a[452]=0; + a[453]=0; + a[454]=0; + a[455]=0; + a[456]=0; + a[457]=0; + a[458]=0; + a[459]=0; + a[460]=0; + a[461]=0; + a[462]=0; + a[463]=0; + a[464]=0; + a[465]=0; + a[466]=0; + a[467]=0; + a[468]=0; + a[469]=0; + a[470]=0; + a[471]=0; + a[472]=0; + a[473]=0; + a[474]=0; + a[475]=0; + a[476]=0; + a[477]=0; + a[478]=0; + a[479]=0; + a[480]=0; + a[481]=0; + a[482]=0; + a[483]=0; + a[484]=0; + a[485]=0; + a[486]=0; + a[487]=0; + a[488]=0; + a[489]=0; + a[490]=0; + a[491]=0; + a[492]=0; + a[493]=0; + a[494]=0; + a[495]=0; + a[496]=0; + a[497]=0; + a[498]=0; + a[499]=0; + a[500]=0; + a[501]=0; + a[502]=0; + a[503]=0; + a[504]=0; + a[505]=0; + a[506]=0; + a[507]=0; + a[508]=0; + a[509]=0; + a[510]=0; + a[511]=0; + a[512]=0; + a[513]=0; + a[514]=0; + a[515]=0; + a[516]=0; + a[517]=0; + a[518]=0; + a[519]=0; + a[520]=0; + a[521]=0; + a[522]=0; + a[523]=0; + a[524]=0; + a[525]=0; + a[526]=0; + a[527]=0; + a[528]=0; + a[529]=0; + a[530]=0; + a[531]=0; + a[532]=0; + a[533]=0; + a[534]=0; + a[535]=0; + a[536]=0; + a[537]=0; + a[538]=0; + a[539]=0; + a[540]=0; + a[541]=0; + a[542]=0; + a[543]=0; + a[544]=0; + a[545]=0; + a[546]=0; + a[547]=0; + a[548]=0; + a[549]=0; + a[550]=0; + a[551]=0; + a[552]=0; + a[553]=0; + a[554]=0; + a[555]=0; + a[556]=0; + a[557]=0; + a[558]=0; + a[559]=0; + a[560]=0; + a[561]=0; + a[562]=0; + a[563]=0; + a[564]=0; + a[565]=0; + a[566]=0; + a[567]=0; + a[568]=0; + a[569]=0; + a[570]=0; + a[571]=0; + a[572]=0; + a[573]=0; + a[574]=0; + a[575]=0; + a[576]=0; + a[577]=0; + a[578]=0; + a[579]=0; + a[580]=0; + a[581]=0; + a[582]=0; + a[583]=0; + a[584]=0; + a[585]=0; + a[586]=0; + a[587]=0; + a[588]=0; + a[589]=0; + a[590]=0; + a[591]=0; + a[592]=0; + a[593]=0; + a[594]=0; + a[595]=0; + a[596]=0; + a[597]=0; + a[598]=0; + a[599]=0; + a[600]=0; + a[601]=0; + a[602]=0; + a[603]=0; + a[604]=0; + a[605]=0; + a[606]=0; + a[607]=0; + a[608]=0; + a[609]=0; + a[610]=0; + a[611]=0; + a[612]=0; + a[613]=0; + a[614]=0; + a[615]=0; + a[616]=0; + a[617]=0; + a[618]=0; + a[619]=0; + a[620]=0; + a[621]=0; + a[622]=0; + a[623]=0; + a[624]=0; + a[625]=0; + a[626]=0; + a[627]=0; + a[628]=0; + a[629]=0; + a[630]=0; + a[631]=0; + a[632]=0; + a[633]=0; + a[634]=0; + a[635]=0; + a[636]=0; + a[637]=0; + a[638]=0; + a[639]=0; + a[640]=0; + a[641]=0; + a[642]=0; + a[643]=0; + a[644]=0; + a[645]=0; + a[646]=0; + a[647]=0; + a[648]=0; + a[649]=0; + a[650]=0; + a[651]=0; + a[652]=0; + a[653]=0; + a[654]=0; + a[655]=0; + a[656]=0; + a[657]=0; + a[658]=0; + a[659]=0; + a[660]=0; + a[661]=0; + a[662]=0; + a[663]=0; + a[664]=0; + a[665]=0; + a[666]=0; + a[667]=0; + a[668]=0; + a[669]=0; + a[670]=0; + a[671]=0; + a[672]=0; + a[673]=0; + a[674]=0; + a[675]=0; + a[676]=0; + a[677]=0; + a[678]=0; + a[679]=0; + a[680]=0; + a[681]=0; + a[682]=0; + a[683]=0; + a[684]=0; + a[685]=0; + a[686]=0; + a[687]=0; + a[688]=0; + a[689]=0; + a[690]=0; + a[691]=0; + a[692]=0; + a[693]=0; + a[694]=0; + a[695]=0; + a[696]=0; + a[697]=0; + a[698]=0; + a[699]=0; + a[700]=0; + a[701]=0; + a[702]=0; + a[703]=0; + a[704]=0; + a[705]=0; + a[706]=0; + a[707]=0; + a[708]=0; + a[709]=0; + a[710]=0; + a[711]=0; + a[712]=0; + a[713]=0; + a[714]=0; + a[715]=0; + a[716]=0; + a[717]=0; + a[718]=0; + a[719]=0; + a[720]=0; + a[721]=0; + a[722]=0; + a[723]=0; + a[724]=0; + a[725]=0; + a[726]=0; + a[727]=0; + a[728]=0; + a[729]=0; + a[730]=0; + a[731]=0; + a[732]=0; + a[733]=0; + a[734]=0; + a[735]=0; + a[736]=0; + a[737]=0; + a[738]=0; + a[739]=0; + a[740]=0; + a[741]=0; + a[742]=0; + a[743]=0; + a[744]=0; + a[745]=0; + a[746]=0; + a[747]=0; + a[748]=0; + a[749]=0; + a[750]=0; + a[751]=0; + a[752]=0; + a[753]=0; + a[754]=0; + a[755]=0; + a[756]=0; + a[757]=0; + a[758]=0; + a[759]=0; + a[760]=0; + a[761]=0; + a[762]=0; + a[763]=0; + a[764]=0; + a[765]=0; + a[766]=0; + a[767]=0; + a[768]=0; + a[769]=0; + a[770]=0; + a[771]=0; + a[772]=0; + a[773]=0; + a[774]=0; + a[775]=0; + a[776]=0; + a[777]=0; + a[778]=0; + a[779]=0; + a[780]=0; + a[781]=0; + a[782]=0; + a[783]=0; + a[784]=0; + a[785]=0; + a[786]=0; + a[787]=0; + a[788]=0; + a[789]=0; + a[790]=0; + a[791]=0; + a[792]=0; + a[793]=0; + a[794]=0; + a[795]=0; + a[796]=0; + a[797]=0; + a[798]=0; + a[799]=0; + a[800]=0; + a[801]=0; + a[802]=0; + a[803]=0; + a[804]=0; + a[805]=0; + a[806]=0; + a[807]=0; + a[808]=0; + a[809]=0; + a[810]=0; + a[811]=0; + a[812]=0; + a[813]=0; + a[814]=0; + a[815]=0; + a[816]=0; + a[817]=0; + a[818]=0; + a[819]=0; + a[820]=0; + a[821]=0; + a[822]=0; + a[823]=0; + a[824]=0; + a[825]=0; + a[826]=0; + a[827]=0; + a[828]=0; + a[829]=0; + a[830]=0; + a[831]=0; + a[832]=0; + a[833]=0; + a[834]=0; + a[835]=0; + a[836]=0; + a[837]=0; + a[838]=0; + a[839]=0; + a[840]=0; + a[841]=0; + a[842]=0; + a[843]=0; + a[844]=0; + a[845]=0; + a[846]=0; + a[847]=0; + a[848]=0; + a[849]=0; + a[850]=0; + a[851]=0; + a[852]=0; + a[853]=0; + a[854]=0; + a[855]=0; + a[856]=0; + a[857]=0; + a[858]=0; + a[859]=0; + a[860]=0; + a[861]=0; + a[862]=0; + a[863]=0; + a[864]=0; + a[865]=0; + a[866]=0; + a[867]=0; + a[868]=0; + a[869]=0; + a[870]=0; + a[871]=0; + a[872]=0; + a[873]=0; + a[874]=0; + a[875]=0; + a[876]=0; + a[877]=0; + a[878]=0; + a[879]=0; + a[880]=0; + a[881]=0; + a[882]=0; + a[883]=0; + a[884]=0; + a[885]=0; + a[886]=0; + a[887]=0; + a[888]=0; + a[889]=0; + a[890]=0; + a[891]=0; + a[892]=0; + a[893]=0; + a[894]=0; + a[895]=0; + a[896]=0; + a[897]=0; + a[898]=0; + a[899]=0; + a[900]=0; + a[901]=0; + a[902]=0; + a[903]=0; + a[904]=0; + a[905]=0; + a[906]=0; + a[907]=0; + a[908]=0; + a[909]=0; + a[910]=0; + a[911]=0; + a[912]=0; + a[913]=0; + a[914]=0; + a[915]=0; + a[916]=0; + a[917]=0; + a[918]=0; + a[919]=0; + a[920]=0; + a[921]=0; + a[922]=0; + a[923]=0; + a[924]=0; + a[925]=0; + a[926]=0; + a[927]=0; + a[928]=0; + a[929]=0; + a[930]=0; + a[931]=0; + a[932]=0; + a[933]=0; + a[934]=0; + a[935]=0; + a[936]=0; + a[937]=0; + a[938]=0; + a[939]=0; + a[940]=0; + a[941]=0; + a[942]=0; + a[943]=0; + a[944]=0; + a[945]=0; + a[946]=0; + a[947]=0; + a[948]=0; + a[949]=0; + a[950]=0; + a[951]=0; + a[952]=0; + a[953]=0; + a[954]=0; + a[955]=0; + a[956]=0; + a[957]=0; + a[958]=0; + a[959]=0; + a[960]=0; + a[961]=0; + a[962]=0; + a[963]=0; + a[964]=0; + a[965]=0; + a[966]=0; + a[967]=0; + a[968]=0; + a[969]=0; + a[970]=0; + a[971]=0; + a[972]=0; + a[973]=0; + a[974]=0; + a[975]=0; + a[976]=0; + a[977]=0; + a[978]=0; + a[979]=0; + a[980]=0; + a[981]=0; + a[982]=0; + a[983]=0; + a[984]=0; + a[985]=0; + a[986]=0; + a[987]=0; + a[988]=0; + a[989]=0; + a[990]=0; + a[991]=0; + a[992]=0; + a[993]=0; + a[994]=0; + a[995]=0; + a[996]=0; + a[997]=0; + a[998]=0; + a[999]=0; + a[1000]=0; + a[1001]=0; + a[1002]=0; + a[1003]=0; + a[1004]=0; + a[1005]=0; + a[1006]=0; + a[1007]=0; + a[1008]=0; + a[1009]=0; + a[1010]=0; + a[1011]=0; + a[1012]=0; + a[1013]=0; + a[1014]=0; + a[1015]=0; + a[1016]=0; + a[1017]=0; + a[1018]=0; + a[1019]=0; + a[1020]=0; + a[1021]=0; + a[1022]=0; + a[1023]=0; + a[1024]=0; + a[1025]=0; + a[1026]=0; + a[1027]=0; + a[1028]=0; + a[1029]=0; + a[1030]=0; + a[1031]=0; + a[1032]=0; + a[1033]=0; + a[1034]=0; + a[1035]=0; + a[1036]=0; + a[1037]=0; + a[1038]=0; + a[1039]=0; + a[1040]=0; + a[1041]=0; + a[1042]=0; + a[1043]=0; + a[1044]=0; + a[1045]=0; + a[1046]=0; + a[1047]=0; + a[1048]=0; + a[1049]=0; + a[1050]=0; + a[1051]=0; + a[1052]=0; + a[1053]=0; + a[1054]=0; + a[1055]=0; + a[1056]=0; + a[1057]=0; + a[1058]=0; + a[1059]=0; + a[1060]=0; + a[1061]=0; + a[1062]=0; + a[1063]=0; + a[1064]=0; + a[1065]=0; + a[1066]=0; + a[1067]=0; + a[1068]=0; + a[1069]=0; + a[1070]=0; + a[1071]=0; + a[1072]=0; + a[1073]=0; + a[1074]=0; + a[1075]=0; + a[1076]=0; + a[1077]=0; + a[1078]=0; + a[1079]=0; + a[1080]=0; + a[1081]=0; + a[1082]=0; + a[1083]=0; + a[1084]=0; + a[1085]=0; + a[1086]=0; + a[1087]=0; + a[1088]=0; + a[1089]=0; + a[1090]=0; + a[1091]=0; + a[1092]=0; + a[1093]=0; + a[1094]=0; + a[1095]=0; + a[1096]=0; + a[1097]=0; + a[1098]=0; + a[1099]=0; + a[1100]=0; + a[1101]=0; + a[1102]=0; + a[1103]=0; + a[1104]=0; + a[1105]=0; + a[1106]=0; + a[1107]=0; + a[1108]=0; + a[1109]=0; + a[1110]=0; + a[1111]=0; + a[1112]=0; + a[1113]=0; + a[1114]=0; + a[1115]=0; + a[1116]=0; + a[1117]=0; + a[1118]=0; + a[1119]=0; + a[1120]=0; + a[1121]=0; + a[1122]=0; + a[1123]=0; + a[1124]=0; + a[1125]=0; + a[1126]=0; + a[1127]=0; + a[1128]=0; + a[1129]=0; + a[1130]=0; + a[1131]=0; + a[1132]=0; + a[1133]=0; + a[1134]=0; + a[1135]=0; + a[1136]=0; + a[1137]=0; + a[1138]=0; + a[1139]=0; + a[1140]=0; + a[1141]=0; + a[1142]=0; + a[1143]=0; + a[1144]=0; + a[1145]=0; + a[1146]=0; + a[1147]=0; + a[1148]=0; + a[1149]=0; + a[1150]=0; + a[1151]=0; + a[1152]=0; + a[1153]=0; + a[1154]=0; + a[1155]=0; + a[1156]=0; + a[1157]=0; + a[1158]=0; + a[1159]=0; + a[1160]=0; + a[1161]=0; + a[1162]=0; + a[1163]=0; + a[1164]=0; + a[1165]=0; + a[1166]=0; + a[1167]=0; + a[1168]=0; + a[1169]=0; + a[1170]=0; + a[1171]=0; + a[1172]=0; + a[1173]=0; + a[1174]=0; + a[1175]=0; + a[1176]=0; + a[1177]=0; + a[1178]=0; + a[1179]=0; + a[1180]=0; + a[1181]=0; + a[1182]=0; + a[1183]=0; + a[1184]=0; + a[1185]=0; + a[1186]=0; + a[1187]=0; + a[1188]=0; + a[1189]=0; + a[1190]=0; + a[1191]=0; + a[1192]=0; + a[1193]=0; + a[1194]=0; + a[1195]=0; + a[1196]=0; + a[1197]=0; + a[1198]=0; + a[1199]=0; + a[1200]=0; + a[1201]=0; + a[1202]=0; + a[1203]=0; + a[1204]=0; + a[1205]=0; + a[1206]=0; + a[1207]=0; + a[1208]=0; + a[1209]=0; + a[1210]=0; + a[1211]=0; + a[1212]=0; + a[1213]=0; + a[1214]=0; + a[1215]=0; + a[1216]=0; + a[1217]=0; + a[1218]=0; + a[1219]=0; + a[1220]=0; + a[1221]=0; + a[1222]=0; + a[1223]=0; + a[1224]=0; + a[1225]=0; + a[1226]=0; + a[1227]=0; + a[1228]=0; + a[1229]=0; + a[1230]=0; + a[1231]=0; + a[1232]=0; + a[1233]=0; + a[1234]=0; + a[1235]=0; + a[1236]=0; + a[1237]=0; + a[1238]=0; + a[1239]=0; + a[1240]=0; + a[1241]=0; + a[1242]=0; + a[1243]=0; + a[1244]=0; + a[1245]=0; + a[1246]=0; + a[1247]=0; + a[1248]=0; + a[1249]=0; + a[1250]=0; + a[1251]=0; + a[1252]=0; + a[1253]=0; + a[1254]=0; + a[1255]=0; + a[1256]=0; + a[1257]=0; + a[1258]=0; + a[1259]=0; + a[1260]=0; + a[1261]=0; + a[1262]=0; + a[1263]=0; + a[1264]=0; + a[1265]=0; + a[1266]=0; + a[1267]=0; + a[1268]=0; + a[1269]=0; + a[1270]=0; + a[1271]=0; + a[1272]=0; + a[1273]=0; + a[1274]=0; + a[1275]=0; + a[1276]=0; + a[1277]=0; + a[1278]=0; + a[1279]=0; + a[1280]=0; + a[1281]=0; + a[1282]=0; + a[1283]=0; + a[1284]=0; + a[1285]=0; + a[1286]=0; + a[1287]=0; + a[1288]=0; + a[1289]=0; + a[1290]=0; + a[1291]=0; + a[1292]=0; + a[1293]=0; + a[1294]=0; + a[1295]=0; + a[1296]=0; + a[1297]=0; + a[1298]=0; + a[1299]=0; + a[1300]=0; + a[1301]=0; + a[1302]=0; + a[1303]=0; + a[1304]=0; + a[1305]=0; + a[1306]=0; + a[1307]=0; + a[1308]=0; + a[1309]=0; + a[1310]=0; + a[1311]=0; + a[1312]=0; + a[1313]=0; + a[1314]=0; + a[1315]=0; + a[1316]=0; + a[1317]=0; + a[1318]=0; + a[1319]=0; + a[1320]=0; + a[1321]=0; + a[1322]=0; + a[1323]=0; + a[1324]=0; + a[1325]=0; + a[1326]=0; + a[1327]=0; + a[1328]=0; + a[1329]=0; + a[1330]=0; + a[1331]=0; + a[1332]=0; + a[1333]=0; + a[1334]=0; + a[1335]=0; + a[1336]=0; + a[1337]=0; + a[1338]=0; + a[1339]=0; + a[1340]=0; + a[1341]=0; + a[1342]=0; + a[1343]=0; + a[1344]=0; + a[1345]=0; + a[1346]=0; + a[1347]=0; + a[1348]=0; + a[1349]=0; + a[1350]=0; + a[1351]=0; + a[1352]=0; + a[1353]=0; + a[1354]=0; + a[1355]=0; + a[1356]=0; + a[1357]=0; + a[1358]=0; + a[1359]=0; + a[1360]=0; + a[1361]=0; + a[1362]=0; + a[1363]=0; + a[1364]=0; + a[1365]=0; + a[1366]=0; + a[1367]=0; + a[1368]=0; + a[1369]=0; + a[1370]=0; + a[1371]=0; + a[1372]=0; + a[1373]=0; + a[1374]=0; + a[1375]=0; + a[1376]=0; + a[1377]=0; + a[1378]=0; + a[1379]=0; + a[1380]=0; + a[1381]=0; + a[1382]=0; + a[1383]=0; + a[1384]=0; + a[1385]=0; + a[1386]=0; + a[1387]=0; + a[1388]=0; + a[1389]=0; + a[1390]=0; + a[1391]=0; + a[1392]=0; + a[1393]=0; + a[1394]=0; + a[1395]=0; + a[1396]=0; + a[1397]=0; + a[1398]=0; + a[1399]=0; + a[1400]=0; + a[1401]=0; + a[1402]=0; + a[1403]=0; + a[1404]=0; + a[1405]=0; + a[1406]=0; + a[1407]=0; + a[1408]=0; + a[1409]=0; + a[1410]=0; + a[1411]=0; + a[1412]=0; + a[1413]=0; + a[1414]=0; + a[1415]=0; + a[1416]=0; + a[1417]=0; + a[1418]=0; + a[1419]=0; + a[1420]=0; + a[1421]=0; + a[1422]=0; + a[1423]=0; + a[1424]=0; + a[1425]=0; + a[1426]=0; + a[1427]=0; + a[1428]=0; + a[1429]=0; + a[1430]=0; + a[1431]=0; + a[1432]=0; + a[1433]=0; + a[1434]=0; + a[1435]=0; + a[1436]=0; + a[1437]=0; + a[1438]=0; + a[1439]=0; + a[1440]=0; + a[1441]=0; + a[1442]=0; + a[1443]=0; + a[1444]=0; + a[1445]=0; + a[1446]=0; + a[1447]=0; + a[1448]=0; + a[1449]=0; + a[1450]=0; + a[1451]=0; + a[1452]=0; + a[1453]=0; + a[1454]=0; + a[1455]=0; + a[1456]=0; + a[1457]=0; + a[1458]=0; + a[1459]=0; + a[1460]=0; + a[1461]=0; + a[1462]=0; + a[1463]=0; + a[1464]=0; + a[1465]=0; + a[1466]=0; + a[1467]=0; + a[1468]=0; + a[1469]=0; + a[1470]=0; + a[1471]=0; + a[1472]=0; + a[1473]=0; + a[1474]=0; + a[1475]=0; + a[1476]=0; + a[1477]=0; + a[1478]=0; + a[1479]=0; + a[1480]=0; + a[1481]=0; + a[1482]=0; + a[1483]=0; + a[1484]=0; + a[1485]=0; + a[1486]=0; + a[1487]=0; + a[1488]=0; + a[1489]=0; + a[1490]=0; + a[1491]=0; + a[1492]=0; + a[1493]=0; + a[1494]=0; + a[1495]=0; + a[1496]=0; + a[1497]=0; + a[1498]=0; + a[1499]=0; + a[1500]=0; + a[1501]=0; + a[1502]=0; + a[1503]=0; + a[1504]=0; + a[1505]=0; + a[1506]=0; + a[1507]=0; + a[1508]=0; + a[1509]=0; + a[1510]=0; + a[1511]=0; + a[1512]=0; + a[1513]=0; + a[1514]=0; + a[1515]=0; + a[1516]=0; + a[1517]=0; + a[1518]=0; + a[1519]=0; + a[1520]=0; + a[1521]=0; + a[1522]=0; + a[1523]=0; + a[1524]=0; + a[1525]=0; + a[1526]=0; + a[1527]=0; + a[1528]=0; + a[1529]=0; + a[1530]=0; + a[1531]=0; + a[1532]=0; + a[1533]=0; + a[1534]=0; + a[1535]=0; + a[1536]=0; + a[1537]=0; + a[1538]=0; + a[1539]=0; + a[1540]=0; + a[1541]=0; + a[1542]=0; + a[1543]=0; + a[1544]=0; + a[1545]=0; + a[1546]=0; + a[1547]=0; + a[1548]=0; + a[1549]=0; + a[1550]=0; + a[1551]=0; + a[1552]=0; + a[1553]=0; + a[1554]=0; + a[1555]=0; + a[1556]=0; + a[1557]=0; + a[1558]=0; + a[1559]=0; + a[1560]=0; + a[1561]=0; + a[1562]=0; + a[1563]=0; + a[1564]=0; + a[1565]=0; + a[1566]=0; + a[1567]=0; + a[1568]=0; + a[1569]=0; + a[1570]=0; + a[1571]=0; + a[1572]=0; + a[1573]=0; + a[1574]=0; + a[1575]=0; + a[1576]=0; + a[1577]=0; + a[1578]=0; + a[1579]=0; + a[1580]=0; + a[1581]=0; + a[1582]=0; + a[1583]=0; + a[1584]=0; + a[1585]=0; + a[1586]=0; + a[1587]=0; + a[1588]=0; + a[1589]=0; + a[1590]=0; + a[1591]=0; + a[1592]=0; + a[1593]=0; + a[1594]=0; + a[1595]=0; + a[1596]=0; + a[1597]=0; + a[1598]=0; + a[1599]=0; + a[1600]=0; + a[1601]=0; + a[1602]=0; + a[1603]=0; + a[1604]=0; + a[1605]=0; + a[1606]=0; + a[1607]=0; + a[1608]=0; + a[1609]=0; + a[1610]=0; + a[1611]=0; + a[1612]=0; + a[1613]=0; + a[1614]=0; + a[1615]=0; + a[1616]=0; + a[1617]=0; + a[1618]=0; + a[1619]=0; + a[1620]=0; + a[1621]=0; + a[1622]=0; + a[1623]=0; + a[1624]=0; + a[1625]=0; + a[1626]=0; + a[1627]=0; + a[1628]=0; + a[1629]=0; + a[1630]=0; + a[1631]=0; + a[1632]=0; + a[1633]=0; + a[1634]=0; + a[1635]=0; + a[1636]=0; + a[1637]=0; + a[1638]=0; + a[1639]=0; + a[1640]=0; + a[1641]=0; + a[1642]=0; + a[1643]=0; + a[1644]=0; + a[1645]=0; + a[1646]=0; + a[1647]=0; + a[1648]=0; + a[1649]=0; + a[1650]=0; + a[1651]=0; + a[1652]=0; + a[1653]=0; + a[1654]=0; + a[1655]=0; + a[1656]=0; + a[1657]=0; + a[1658]=0; + a[1659]=0; + a[1660]=0; + a[1661]=0; + a[1662]=0; + a[1663]=0; + a[1664]=0; + a[1665]=0; + a[1666]=0; + a[1667]=0; + a[1668]=0; + a[1669]=0; + a[1670]=0; + a[1671]=0; + a[1672]=0; + a[1673]=0; + a[1674]=0; + a[1675]=0; + a[1676]=0; + a[1677]=0; + a[1678]=0; + a[1679]=0; + a[1680]=0; + a[1681]=0; + a[1682]=0; + a[1683]=0; + a[1684]=0; + a[1685]=0; + a[1686]=0; + a[1687]=0; + a[1688]=0; + a[1689]=0; + a[1690]=0; + a[1691]=0; + a[1692]=0; + a[1693]=0; + a[1694]=0; + a[1695]=0; + a[1696]=0; + a[1697]=0; + a[1698]=0; + a[1699]=0; + a[1700]=0; + a[1701]=0; + a[1702]=0; + a[1703]=0; + a[1704]=0; + a[1705]=0; + a[1706]=0; + a[1707]=0; + a[1708]=0; + a[1709]=0; + a[1710]=0; + a[1711]=0; + a[1712]=0; + a[1713]=0; + a[1714]=0; + a[1715]=0; + a[1716]=0; + a[1717]=0; + a[1718]=0; + a[1719]=0; + a[1720]=0; + a[1721]=0; + a[1722]=0; + a[1723]=0; + a[1724]=0; + a[1725]=0; + a[1726]=0; + a[1727]=0; + a[1728]=0; + a[1729]=0; + a[1730]=0; + a[1731]=0; + a[1732]=0; + a[1733]=0; + a[1734]=0; + a[1735]=0; + a[1736]=0; + a[1737]=0; + a[1738]=0; + a[1739]=0; + a[1740]=0; + a[1741]=0; + a[1742]=0; + a[1743]=0; + a[1744]=0; + a[1745]=0; + a[1746]=0; + a[1747]=0; + a[1748]=0; + a[1749]=0; + a[1750]=0; + a[1751]=0; + a[1752]=0; + a[1753]=0; + a[1754]=0; + a[1755]=0; + a[1756]=0; + a[1757]=0; + a[1758]=0; + a[1759]=0; + a[1760]=0; + a[1761]=0; + a[1762]=0; + a[1763]=0; + a[1764]=0; + a[1765]=0; + a[1766]=0; + a[1767]=0; + a[1768]=0; + a[1769]=0; + a[1770]=0; + a[1771]=0; + a[1772]=0; + a[1773]=0; + a[1774]=0; + a[1775]=0; + a[1776]=0; + a[1777]=0; + a[1778]=0; + a[1779]=0; + a[1780]=0; + a[1781]=0; + a[1782]=0; + a[1783]=0; + a[1784]=0; + a[1785]=0; + a[1786]=0; + a[1787]=0; + a[1788]=0; + a[1789]=0; + a[1790]=0; + a[1791]=0; + a[1792]=0; + a[1793]=0; + a[1794]=0; + a[1795]=0; + a[1796]=0; + a[1797]=0; + a[1798]=0; + a[1799]=0; + a[1800]=0; + a[1801]=0; + a[1802]=0; + a[1803]=0; + a[1804]=0; + a[1805]=0; + a[1806]=0; + a[1807]=0; + a[1808]=0; + a[1809]=0; + a[1810]=0; + a[1811]=0; + a[1812]=0; + a[1813]=0; + a[1814]=0; + a[1815]=0; + a[1816]=0; + a[1817]=0; + a[1818]=0; + a[1819]=0; + a[1820]=0; + a[1821]=0; + a[1822]=0; + a[1823]=0; + a[1824]=0; + a[1825]=0; + a[1826]=0; + a[1827]=0; + a[1828]=0; + a[1829]=0; + a[1830]=0; + a[1831]=0; + a[1832]=0; + a[1833]=0; + a[1834]=0; + a[1835]=0; + a[1836]=0; + a[1837]=0; + a[1838]=0; + a[1839]=0; + a[1840]=0; + a[1841]=0; + a[1842]=0; + a[1843]=0; + a[1844]=0; + a[1845]=0; + a[1846]=0; + a[1847]=0; + a[1848]=0; + a[1849]=0; + a[1850]=0; + a[1851]=0; + a[1852]=0; + a[1853]=0; + a[1854]=0; + a[1855]=0; + a[1856]=0; + a[1857]=0; + a[1858]=0; + a[1859]=0; + a[1860]=0; + a[1861]=0; + a[1862]=0; + a[1863]=0; + a[1864]=0; + a[1865]=0; + a[1866]=0; + a[1867]=0; + a[1868]=0; + a[1869]=0; + a[1870]=0; + a[1871]=0; + a[1872]=0; + a[1873]=0; + a[1874]=0; + a[1875]=0; + a[1876]=0; + a[1877]=0; + a[1878]=0; + a[1879]=0; + a[1880]=0; + a[1881]=0; + a[1882]=0; + a[1883]=0; + a[1884]=0; + a[1885]=0; + a[1886]=0; + a[1887]=0; + a[1888]=0; + a[1889]=0; + a[1890]=0; + a[1891]=0; + a[1892]=0; + a[1893]=0; + a[1894]=0; + a[1895]=0; + a[1896]=0; + a[1897]=0; + a[1898]=0; + a[1899]=0; + a[1900]=0; + a[1901]=0; + a[1902]=0; + a[1903]=0; + a[1904]=0; + a[1905]=0; + a[1906]=0; + a[1907]=0; + a[1908]=0; + a[1909]=0; + a[1910]=0; + a[1911]=0; + a[1912]=0; + a[1913]=0; + a[1914]=0; + a[1915]=0; + a[1916]=0; + a[1917]=0; + a[1918]=0; + a[1919]=0; + a[1920]=0; + a[1921]=0; + a[1922]=0; + a[1923]=0; + a[1924]=0; + a[1925]=0; + a[1926]=0; + a[1927]=0; + a[1928]=0; + a[1929]=0; + a[1930]=0; + a[1931]=0; + a[1932]=0; + a[1933]=0; + a[1934]=0; + a[1935]=0; + a[1936]=0; + a[1937]=0; + a[1938]=0; + a[1939]=0; + a[1940]=0; + a[1941]=0; + a[1942]=0; + a[1943]=0; + a[1944]=0; + a[1945]=0; + a[1946]=0; + a[1947]=0; + a[1948]=0; + a[1949]=0; + a[1950]=0; + a[1951]=0; + a[1952]=0; + a[1953]=0; + a[1954]=0; + a[1955]=0; + a[1956]=0; + a[1957]=0; + a[1958]=0; + a[1959]=0; + a[1960]=0; + a[1961]=0; + a[1962]=0; + a[1963]=0; + a[1964]=0; + a[1965]=0; + a[1966]=0; + a[1967]=0; + a[1968]=0; + a[1969]=0; + a[1970]=0; + a[1971]=0; + a[1972]=0; + a[1973]=0; + a[1974]=0; + a[1975]=0; + a[1976]=0; + a[1977]=0; + a[1978]=0; + a[1979]=0; + a[1980]=0; + a[1981]=0; + a[1982]=0; + a[1983]=0; + a[1984]=0; + a[1985]=0; + a[1986]=0; + a[1987]=0; + a[1988]=0; + a[1989]=0; + a[1990]=0; + a[1991]=0; + a[1992]=0; + a[1993]=0; + a[1994]=0; + a[1995]=0; + a[1996]=0; + a[1997]=0; + a[1998]=0; + a[1999]=0; + a[2000]=0; + a[2001]=0; + a[2002]=0; + a[2003]=0; + a[2004]=0; + a[2005]=0; + a[2006]=0; + a[2007]=0; + a[2008]=0; + a[2009]=0; + a[2010]=0; + a[2011]=0; + a[2012]=0; + a[2013]=0; + a[2014]=0; + a[2015]=0; + a[2016]=0; + a[2017]=0; + a[2018]=0; + a[2019]=0; + a[2020]=0; + a[2021]=0; + a[2022]=0; + a[2023]=0; + a[2024]=0; + a[2025]=0; + a[2026]=0; + a[2027]=0; + a[2028]=0; + a[2029]=0; + a[2030]=0; + a[2031]=0; + a[2032]=0; + a[2033]=0; + a[2034]=0; + a[2035]=0; + a[2036]=0; + a[2037]=0; + a[2038]=0; + a[2039]=0; + a[2040]=0; + a[2041]=0; + a[2042]=0; + a[2043]=0; + a[2044]=0; + a[2045]=0; + a[2046]=0; + a[2047]=0; + a[2048]=0; + a[2049]=0; + a[2050]=0; + a[2051]=0; + a[2052]=0; + a[2053]=0; + a[2054]=0; + a[2055]=0; + a[2056]=0; + a[2057]=0; + a[2058]=0; + a[2059]=0; + a[2060]=0; + a[2061]=0; + a[2062]=0; + a[2063]=0; + a[2064]=0; + a[2065]=0; + a[2066]=0; + a[2067]=0; + a[2068]=0; + a[2069]=0; + a[2070]=0; + a[2071]=0; + a[2072]=0; + a[2073]=0; + a[2074]=0; + a[2075]=0; + a[2076]=0; + a[2077]=0; + a[2078]=0; + a[2079]=0; + a[2080]=0; + a[2081]=0; + a[2082]=0; + a[2083]=0; + a[2084]=0; + a[2085]=0; + a[2086]=0; + a[2087]=0; + a[2088]=0; + a[2089]=0; + a[2090]=0; + a[2091]=0; + a[2092]=0; + a[2093]=0; + a[2094]=0; + a[2095]=0; + a[2096]=0; + a[2097]=0; + a[2098]=0; + a[2099]=0; + a[2100]=0; + a[2101]=0; + a[2102]=0; + a[2103]=0; + a[2104]=0; + a[2105]=0; + a[2106]=0; + a[2107]=0; + a[2108]=0; + a[2109]=0; + a[2110]=0; + a[2111]=0; + a[2112]=0; + a[2113]=0; + a[2114]=0; + a[2115]=0; + a[2116]=0; + a[2117]=0; + a[2118]=0; + a[2119]=0; + a[2120]=0; + a[2121]=0; + a[2122]=0; + a[2123]=0; + a[2124]=0; + a[2125]=0; + a[2126]=0; + a[2127]=0; + a[2128]=0; + a[2129]=0; + a[2130]=0; + a[2131]=0; + a[2132]=0; + a[2133]=0; + a[2134]=0; + a[2135]=0; + a[2136]=0; + a[2137]=0; + a[2138]=0; + a[2139]=0; + a[2140]=0; + a[2141]=0; + a[2142]=0; + a[2143]=0; + a[2144]=0; + a[2145]=0; + a[2146]=0; + a[2147]=0; + a[2148]=0; + a[2149]=0; + a[2150]=0; + a[2151]=0; + a[2152]=0; + a[2153]=0; + a[2154]=0; + a[2155]=0; + a[2156]=0; + a[2157]=0; + a[2158]=0; + a[2159]=0; + a[2160]=0; + a[2161]=0; + a[2162]=0; + a[2163]=0; + a[2164]=0; + a[2165]=0; + a[2166]=0; + a[2167]=0; + a[2168]=0; + a[2169]=0; + a[2170]=0; + a[2171]=0; + a[2172]=0; + a[2173]=0; + a[2174]=0; + a[2175]=0; + a[2176]=0; + a[2177]=0; + a[2178]=0; + a[2179]=0; + a[2180]=0; + a[2181]=0; + a[2182]=0; + a[2183]=0; + a[2184]=0; + a[2185]=0; + a[2186]=0; + a[2187]=0; + a[2188]=0; + a[2189]=0; + a[2190]=0; + a[2191]=0; + a[2192]=0; + a[2193]=0; + a[2194]=0; + a[2195]=0; + a[2196]=0; + a[2197]=0; + a[2198]=0; + a[2199]=0; + a[2200]=0; + a[2201]=0; + a[2202]=0; + a[2203]=0; + a[2204]=0; + a[2205]=0; + a[2206]=0; + a[2207]=0; + a[2208]=0; + a[2209]=0; + a[2210]=0; + a[2211]=0; + a[2212]=0; + a[2213]=0; + a[2214]=0; + a[2215]=0; + a[2216]=0; + a[2217]=0; + a[2218]=0; + a[2219]=0; + a[2220]=0; + a[2221]=0; + a[2222]=0; + a[2223]=0; + a[2224]=0; + a[2225]=0; + a[2226]=0; + a[2227]=0; + a[2228]=0; + a[2229]=0; + a[2230]=0; + a[2231]=0; + a[2232]=0; + a[2233]=0; + a[2234]=0; + a[2235]=0; + a[2236]=0; + a[2237]=0; + a[2238]=0; + a[2239]=0; + a[2240]=0; + a[2241]=0; + a[2242]=0; + a[2243]=0; + a[2244]=0; + a[2245]=0; + a[2246]=0; + a[2247]=0; + a[2248]=0; + a[2249]=0; + a[2250]=0; + a[2251]=0; + a[2252]=0; + a[2253]=0; + a[2254]=0; + a[2255]=0; + a[2256]=0; + a[2257]=0; + a[2258]=0; + a[2259]=0; + a[2260]=0; + a[2261]=0; + a[2262]=0; + a[2263]=0; + a[2264]=0; + a[2265]=0; + a[2266]=0; + a[2267]=0; + a[2268]=0; + a[2269]=0; + a[2270]=0; + a[2271]=0; + a[2272]=0; + a[2273]=0; + a[2274]=0; + a[2275]=0; + a[2276]=0; + a[2277]=0; + a[2278]=0; + a[2279]=0; + a[2280]=0; + a[2281]=0; + a[2282]=0; + a[2283]=0; + a[2284]=0; + a[2285]=0; + a[2286]=0; + a[2287]=0; + a[2288]=0; + a[2289]=0; + a[2290]=0; + a[2291]=0; + a[2292]=0; + a[2293]=0; + a[2294]=0; + a[2295]=0; + a[2296]=0; + a[2297]=0; + a[2298]=0; + a[2299]=0; + a[2300]=0; + a[2301]=0; + a[2302]=0; + a[2303]=0; + a[2304]=0; + a[2305]=0; + a[2306]=0; + a[2307]=0; + a[2308]=0; + a[2309]=0; + a[2310]=0; + a[2311]=0; + a[2312]=0; + a[2313]=0; + a[2314]=0; + a[2315]=0; + a[2316]=0; + a[2317]=0; + a[2318]=0; + a[2319]=0; + a[2320]=0; + a[2321]=0; + a[2322]=0; + a[2323]=0; + a[2324]=0; + a[2325]=0; + a[2326]=0; + a[2327]=0; + a[2328]=0; + a[2329]=0; + a[2330]=0; + a[2331]=0; + a[2332]=0; + a[2333]=0; + a[2334]=0; + a[2335]=0; + a[2336]=0; + a[2337]=0; + a[2338]=0; + a[2339]=0; + a[2340]=0; + a[2341]=0; + a[2342]=0; + a[2343]=0; + a[2344]=0; + a[2345]=0; + a[2346]=0; + a[2347]=0; + a[2348]=0; + a[2349]=0; + a[2350]=0; + a[2351]=0; + a[2352]=0; + a[2353]=0; + a[2354]=0; + a[2355]=0; + a[2356]=0; + a[2357]=0; + a[2358]=0; + a[2359]=0; + a[2360]=0; + a[2361]=0; + a[2362]=0; + a[2363]=0; + a[2364]=0; + a[2365]=0; + a[2366]=0; + a[2367]=0; + a[2368]=0; + a[2369]=0; + a[2370]=0; + a[2371]=0; + a[2372]=0; + a[2373]=0; + a[2374]=0; + a[2375]=0; + a[2376]=0; + a[2377]=0; + a[2378]=0; + a[2379]=0; + a[2380]=0; + a[2381]=0; + a[2382]=0; + a[2383]=0; + a[2384]=0; + a[2385]=0; + a[2386]=0; + a[2387]=0; + a[2388]=0; + a[2389]=0; + a[2390]=0; + a[2391]=0; + a[2392]=0; + a[2393]=0; + a[2394]=0; + a[2395]=0; + a[2396]=0; + a[2397]=0; + a[2398]=0; + a[2399]=0; + a[2400]=0; + a[2401]=0; + a[2402]=0; + a[2403]=0; + a[2404]=0; + a[2405]=0; + a[2406]=0; + a[2407]=0; + a[2408]=0; + a[2409]=0; + a[2410]=0; + a[2411]=0; + a[2412]=0; + a[2413]=0; + a[2414]=0; + a[2415]=0; + a[2416]=0; + a[2417]=0; + a[2418]=0; + a[2419]=0; + a[2420]=0; + a[2421]=0; + a[2422]=0; + a[2423]=0; + a[2424]=0; + a[2425]=0; + a[2426]=0; + a[2427]=0; + a[2428]=0; + a[2429]=0; + a[2430]=0; + a[2431]=0; + a[2432]=0; + a[2433]=0; + a[2434]=0; + a[2435]=0; + a[2436]=0; + a[2437]=0; + a[2438]=0; + a[2439]=0; + a[2440]=0; + a[2441]=0; + a[2442]=0; + a[2443]=0; + a[2444]=0; + a[2445]=0; + a[2446]=0; + a[2447]=0; + a[2448]=0; + a[2449]=0; + a[2450]=0; + a[2451]=0; + a[2452]=0; + a[2453]=0; + a[2454]=0; + a[2455]=0; + a[2456]=0; + a[2457]=0; + a[2458]=0; + a[2459]=0; + a[2460]=0; + a[2461]=0; + a[2462]=0; + a[2463]=0; + a[2464]=0; + a[2465]=0; + a[2466]=0; + a[2467]=0; + a[2468]=0; + a[2469]=0; + a[2470]=0; + a[2471]=0; + a[2472]=0; + a[2473]=0; + a[2474]=0; + a[2475]=0; + a[2476]=0; + a[2477]=0; + a[2478]=0; + a[2479]=0; + a[2480]=0; + a[2481]=0; + a[2482]=0; + a[2483]=0; + a[2484]=0; + a[2485]=0; + a[2486]=0; + a[2487]=0; + a[2488]=0; + a[2489]=0; + a[2490]=0; + a[2491]=0; + a[2492]=0; + a[2493]=0; + a[2494]=0; + a[2495]=0; + a[2496]=0; + a[2497]=0; + a[2498]=0; + a[2499]=0; + a[2500]=0; + a[2501]=0; + a[2502]=0; + a[2503]=0; + a[2504]=0; + a[2505]=0; + a[2506]=0; + a[2507]=0; + a[2508]=0; + a[2509]=0; + a[2510]=0; + a[2511]=0; + a[2512]=0; + a[2513]=0; + a[2514]=0; + a[2515]=0; + a[2516]=0; + a[2517]=0; + a[2518]=0; + a[2519]=0; + a[2520]=0; + a[2521]=0; + a[2522]=0; + a[2523]=0; + a[2524]=0; + a[2525]=0; + a[2526]=0; + a[2527]=0; + a[2528]=0; + a[2529]=0; + a[2530]=0; + a[2531]=0; + a[2532]=0; + a[2533]=0; + a[2534]=0; + a[2535]=0; + a[2536]=0; + a[2537]=0; + a[2538]=0; + a[2539]=0; + a[2540]=0; + a[2541]=0; + a[2542]=0; + a[2543]=0; + a[2544]=0; + a[2545]=0; + a[2546]=0; + a[2547]=0; + a[2548]=0; + a[2549]=0; + a[2550]=0; + a[2551]=0; + a[2552]=0; + a[2553]=0; + a[2554]=0; + a[2555]=0; + a[2556]=0; + a[2557]=0; + a[2558]=0; + a[2559]=0; + a[2560]=0; + a[2561]=0; + a[2562]=0; + a[2563]=0; + a[2564]=0; + a[2565]=0; + a[2566]=0; + a[2567]=0; + a[2568]=0; + a[2569]=0; + a[2570]=0; + a[2571]=0; + a[2572]=0; + a[2573]=0; + a[2574]=0; + a[2575]=0; + a[2576]=0; + a[2577]=0; + a[2578]=0; + a[2579]=0; + a[2580]=0; + a[2581]=0; + a[2582]=0; + a[2583]=0; + a[2584]=0; + a[2585]=0; + a[2586]=0; + a[2587]=0; + a[2588]=0; + a[2589]=0; + a[2590]=0; + a[2591]=0; + a[2592]=0; + a[2593]=0; + a[2594]=0; + a[2595]=0; + a[2596]=0; + a[2597]=0; + a[2598]=0; + a[2599]=0; + a[2600]=0; + a[2601]=0; + a[2602]=0; + a[2603]=0; + a[2604]=0; + a[2605]=0; + a[2606]=0; + a[2607]=0; + a[2608]=0; + a[2609]=0; + a[2610]=0; + a[2611]=0; + a[2612]=0; + a[2613]=0; + a[2614]=0; + a[2615]=0; + a[2616]=0; + a[2617]=0; + a[2618]=0; + a[2619]=0; + a[2620]=0; + a[2621]=0; + a[2622]=0; + a[2623]=0; + a[2624]=0; + a[2625]=0; + a[2626]=0; + a[2627]=0; + a[2628]=0; + a[2629]=0; + a[2630]=0; + a[2631]=0; + a[2632]=0; + a[2633]=0; + a[2634]=0; + a[2635]=0; + a[2636]=0; + a[2637]=0; + a[2638]=0; + a[2639]=0; + a[2640]=0; + a[2641]=0; + a[2642]=0; + a[2643]=0; + a[2644]=0; + a[2645]=0; + a[2646]=0; + a[2647]=0; + a[2648]=0; + a[2649]=0; + a[2650]=0; + a[2651]=0; + a[2652]=0; + a[2653]=0; + a[2654]=0; + a[2655]=0; + a[2656]=0; + a[2657]=0; + a[2658]=0; + a[2659]=0; + a[2660]=0; + a[2661]=0; + a[2662]=0; + a[2663]=0; + a[2664]=0; + a[2665]=0; + a[2666]=0; + a[2667]=0; + a[2668]=0; + a[2669]=0; + a[2670]=0; + a[2671]=0; + a[2672]=0; + a[2673]=0; + a[2674]=0; + a[2675]=0; + a[2676]=0; + a[2677]=0; + a[2678]=0; + a[2679]=0; + a[2680]=0; + a[2681]=0; + a[2682]=0; + a[2683]=0; + a[2684]=0; + a[2685]=0; + a[2686]=0; + a[2687]=0; + a[2688]=0; + a[2689]=0; + a[2690]=0; + a[2691]=0; + a[2692]=0; + a[2693]=0; + a[2694]=0; + a[2695]=0; + a[2696]=0; + a[2697]=0; + a[2698]=0; + a[2699]=0; + a[2700]=0; + a[2701]=0; + a[2702]=0; + a[2703]=0; + a[2704]=0; + a[2705]=0; + a[2706]=0; + a[2707]=0; + a[2708]=0; + a[2709]=0; + a[2710]=0; + a[2711]=0; + a[2712]=0; + a[2713]=0; + a[2714]=0; + a[2715]=0; + a[2716]=0; + a[2717]=0; + a[2718]=0; + a[2719]=0; + a[2720]=0; + a[2721]=0; + a[2722]=0; + a[2723]=0; + a[2724]=0; + a[2725]=0; + a[2726]=0; + a[2727]=0; + a[2728]=0; + a[2729]=0; + a[2730]=0; + a[2731]=0; + a[2732]=0; + a[2733]=0; + a[2734]=0; + a[2735]=0; + a[2736]=0; + a[2737]=0; + a[2738]=0; + a[2739]=0; + a[2740]=0; + a[2741]=0; + a[2742]=0; + a[2743]=0; + a[2744]=0; + a[2745]=0; + a[2746]=0; + a[2747]=0; + a[2748]=0; + a[2749]=0; + a[2750]=0; + a[2751]=0; + a[2752]=0; + a[2753]=0; + a[2754]=0; + a[2755]=0; + a[2756]=0; + a[2757]=0; + a[2758]=0; + a[2759]=0; + a[2760]=0; + a[2761]=0; + a[2762]=0; + a[2763]=0; + a[2764]=0; + a[2765]=0; + a[2766]=0; + a[2767]=0; + a[2768]=0; + a[2769]=0; + a[2770]=0; + a[2771]=0; + a[2772]=0; + a[2773]=0; + a[2774]=0; + a[2775]=0; + a[2776]=0; + a[2777]=0; + a[2778]=0; + a[2779]=0; + a[2780]=0; + a[2781]=0; + a[2782]=0; + a[2783]=0; + a[2784]=0; + a[2785]=0; + a[2786]=0; + a[2787]=0; + a[2788]=0; + a[2789]=0; + a[2790]=0; + a[2791]=0; + a[2792]=0; + a[2793]=0; + a[2794]=0; + a[2795]=0; + a[2796]=0; + a[2797]=0; + a[2798]=0; + a[2799]=0; + a[2800]=0; + a[2801]=0; + a[2802]=0; + a[2803]=0; + a[2804]=0; + a[2805]=0; + a[2806]=0; + a[2807]=0; + a[2808]=0; + a[2809]=0; + a[2810]=0; + a[2811]=0; + a[2812]=0; + a[2813]=0; + a[2814]=0; + a[2815]=0; + a[2816]=0; + a[2817]=0; + a[2818]=0; + a[2819]=0; + a[2820]=0; + a[2821]=0; + a[2822]=0; + a[2823]=0; + a[2824]=0; + a[2825]=0; + a[2826]=0; + a[2827]=0; + a[2828]=0; + a[2829]=0; + a[2830]=0; + a[2831]=0; + a[2832]=0; + a[2833]=0; + a[2834]=0; + a[2835]=0; + a[2836]=0; + a[2837]=0; + a[2838]=0; + a[2839]=0; + a[2840]=0; + a[2841]=0; + a[2842]=0; + a[2843]=0; + a[2844]=0; + a[2845]=0; + a[2846]=0; + a[2847]=0; + a[2848]=0; + a[2849]=0; + a[2850]=0; + a[2851]=0; + a[2852]=0; + a[2853]=0; + a[2854]=0; + a[2855]=0; + a[2856]=0; + a[2857]=0; + a[2858]=0; + a[2859]=0; + a[2860]=0; + a[2861]=0; + a[2862]=0; + a[2863]=0; + a[2864]=0; + a[2865]=0; + a[2866]=0; + a[2867]=0; + a[2868]=0; + a[2869]=0; + a[2870]=0; + a[2871]=0; + a[2872]=0; + a[2873]=0; + a[2874]=0; + a[2875]=0; + a[2876]=0; + a[2877]=0; + a[2878]=0; + a[2879]=0; + a[2880]=0; + a[2881]=0; + a[2882]=0; + a[2883]=0; + a[2884]=0; + a[2885]=0; + a[2886]=0; + a[2887]=0; + a[2888]=0; + a[2889]=0; + a[2890]=0; + a[2891]=0; + a[2892]=0; + a[2893]=0; + a[2894]=0; + a[2895]=0; + a[2896]=0; + a[2897]=0; + a[2898]=0; + a[2899]=0; + a[2900]=0; + a[2901]=0; + a[2902]=0; + a[2903]=0; + a[2904]=0; + a[2905]=0; + a[2906]=0; + a[2907]=0; + a[2908]=0; + a[2909]=0; + a[2910]=0; + a[2911]=0; + a[2912]=0; + a[2913]=0; + a[2914]=0; + a[2915]=0; + a[2916]=0; + a[2917]=0; + a[2918]=0; + a[2919]=0; + a[2920]=0; + a[2921]=0; + a[2922]=0; + a[2923]=0; + a[2924]=0; + a[2925]=0; + a[2926]=0; + a[2927]=0; + a[2928]=0; + a[2929]=0; + a[2930]=0; + a[2931]=0; + a[2932]=0; + a[2933]=0; + a[2934]=0; + a[2935]=0; + a[2936]=0; + a[2937]=0; + a[2938]=0; + a[2939]=0; + a[2940]=0; + a[2941]=0; + a[2942]=0; + a[2943]=0; + a[2944]=0; + a[2945]=0; + a[2946]=0; + a[2947]=0; + a[2948]=0; + a[2949]=0; + a[2950]=0; + a[2951]=0; + a[2952]=0; + a[2953]=0; + a[2954]=0; + a[2955]=0; + a[2956]=0; + a[2957]=0; + a[2958]=0; + a[2959]=0; + a[2960]=0; + a[2961]=0; + a[2962]=0; + a[2963]=0; + a[2964]=0; + a[2965]=0; + a[2966]=0; + a[2967]=0; + a[2968]=0; + a[2969]=0; + a[2970]=0; + a[2971]=0; + a[2972]=0; + a[2973]=0; + a[2974]=0; + a[2975]=0; + a[2976]=0; + a[2977]=0; + a[2978]=0; + a[2979]=0; + a[2980]=0; + a[2981]=0; + a[2982]=0; + a[2983]=0; + a[2984]=0; + a[2985]=0; + a[2986]=0; + a[2987]=0; + a[2988]=0; + a[2989]=0; + a[2990]=0; + a[2991]=0; + a[2992]=0; + a[2993]=0; + a[2994]=0; + a[2995]=0; + a[2996]=0; + a[2997]=0; + a[2998]=0; + a[2999]=0; + a[3000]=0; + a[3001]=0; + a[3002]=0; + a[3003]=0; + a[3004]=0; + a[3005]=0; + a[3006]=0; + a[3007]=0; + a[3008]=0; + a[3009]=0; + a[3010]=0; + a[3011]=0; + a[3012]=0; + a[3013]=0; + a[3014]=0; + a[3015]=0; + a[3016]=0; + a[3017]=0; + a[3018]=0; + a[3019]=0; + a[3020]=0; + a[3021]=0; + a[3022]=0; + a[3023]=0; + a[3024]=0; + a[3025]=0; + a[3026]=0; + a[3027]=0; + a[3028]=0; + a[3029]=0; + a[3030]=0; + a[3031]=0; + a[3032]=0; + a[3033]=0; + a[3034]=0; + a[3035]=0; + a[3036]=0; + a[3037]=0; + a[3038]=0; + a[3039]=0; + a[3040]=0; + a[3041]=0; + a[3042]=0; + a[3043]=0; + a[3044]=0; + a[3045]=0; + a[3046]=0; + a[3047]=0; + a[3048]=0; + a[3049]=0; + a[3050]=0; + a[3051]=0; + a[3052]=0; + a[3053]=0; + a[3054]=0; + a[3055]=0; + a[3056]=0; + a[3057]=0; + a[3058]=0; + a[3059]=0; + a[3060]=0; + a[3061]=0; + a[3062]=0; + a[3063]=0; + a[3064]=0; + a[3065]=0; + a[3066]=0; + a[3067]=0; + a[3068]=0; + a[3069]=0; + a[3070]=0; + a[3071]=0; + a[3072]=0; + a[3073]=0; + a[3074]=0; + a[3075]=0; + a[3076]=0; + a[3077]=0; + a[3078]=0; + a[3079]=0; + a[3080]=0; + a[3081]=0; + a[3082]=0; + a[3083]=0; + a[3084]=0; + a[3085]=0; + a[3086]=0; + a[3087]=0; + a[3088]=0; + a[3089]=0; + a[3090]=0; + a[3091]=0; + a[3092]=0; + a[3093]=0; + a[3094]=0; + a[3095]=0; + a[3096]=0; + a[3097]=0; + a[3098]=0; + a[3099]=0; + a[3100]=0; + a[3101]=0; + a[3102]=0; + a[3103]=0; + a[3104]=0; + a[3105]=0; + a[3106]=0; + a[3107]=0; + a[3108]=0; + a[3109]=0; + a[3110]=0; + a[3111]=0; + a[3112]=0; + a[3113]=0; + a[3114]=0; + a[3115]=0; + a[3116]=0; + a[3117]=0; + a[3118]=0; + a[3119]=0; + a[3120]=0; + a[3121]=0; + a[3122]=0; + a[3123]=0; + a[3124]=0; + a[3125]=0; + a[3126]=0; + a[3127]=0; + a[3128]=0; + a[3129]=0; + a[3130]=0; + a[3131]=0; + a[3132]=0; + a[3133]=0; + a[3134]=0; + a[3135]=0; + a[3136]=0; + a[3137]=0; + a[3138]=0; + a[3139]=0; + a[3140]=0; + a[3141]=0; + a[3142]=0; + a[3143]=0; + a[3144]=0; + a[3145]=0; + a[3146]=0; + a[3147]=0; + a[3148]=0; + a[3149]=0; + a[3150]=0; + a[3151]=0; + a[3152]=0; + a[3153]=0; + a[3154]=0; + a[3155]=0; + a[3156]=0; + a[3157]=0; + a[3158]=0; + a[3159]=0; + a[3160]=0; + a[3161]=0; + a[3162]=0; + a[3163]=0; + a[3164]=0; + a[3165]=0; + a[3166]=0; + a[3167]=0; + a[3168]=0; + a[3169]=0; + a[3170]=0; + a[3171]=0; + a[3172]=0; + a[3173]=0; + a[3174]=0; + a[3175]=0; + a[3176]=0; + a[3177]=0; + a[3178]=0; + a[3179]=0; + a[3180]=0; + a[3181]=0; + a[3182]=0; + a[3183]=0; + a[3184]=0; + a[3185]=0; + a[3186]=0; + a[3187]=0; + a[3188]=0; + a[3189]=0; + a[3190]=0; + a[3191]=0; + a[3192]=0; + a[3193]=0; + a[3194]=0; + a[3195]=0; + a[3196]=0; + a[3197]=0; + a[3198]=0; + a[3199]=0; + a[3200]=0; + a[3201]=0; + a[3202]=0; + a[3203]=0; + a[3204]=0; + a[3205]=0; + a[3206]=0; + a[3207]=0; + a[3208]=0; + a[3209]=0; + a[3210]=0; + a[3211]=0; + a[3212]=0; + a[3213]=0; + a[3214]=0; + a[3215]=0; + a[3216]=0; + a[3217]=0; + a[3218]=0; + a[3219]=0; + a[3220]=0; + a[3221]=0; + a[3222]=0; + a[3223]=0; + a[3224]=0; + a[3225]=0; + a[3226]=0; + a[3227]=0; + a[3228]=0; + a[3229]=0; + a[3230]=0; + a[3231]=0; + a[3232]=0; + a[3233]=0; + a[3234]=0; + a[3235]=0; + a[3236]=0; + a[3237]=0; + a[3238]=0; + a[3239]=0; + a[3240]=0; + a[3241]=0; + a[3242]=0; + a[3243]=0; + a[3244]=0; + a[3245]=0; + a[3246]=0; + a[3247]=0; + a[3248]=0; + a[3249]=0; + a[3250]=0; + a[3251]=0; + a[3252]=0; + a[3253]=0; + a[3254]=0; + a[3255]=0; + a[3256]=0; + a[3257]=0; + a[3258]=0; + a[3259]=0; + a[3260]=0; + a[3261]=0; + a[3262]=0; + a[3263]=0; + a[3264]=0; + a[3265]=0; + a[3266]=0; + a[3267]=0; + a[3268]=0; + a[3269]=0; + a[3270]=0; + a[3271]=0; + a[3272]=0; + a[3273]=0; + a[3274]=0; + a[3275]=0; + a[3276]=0; + a[3277]=0; + a[3278]=0; + a[3279]=0; + a[3280]=0; + a[3281]=0; + a[3282]=0; + a[3283]=0; + a[3284]=0; + a[3285]=0; + a[3286]=0; + a[3287]=0; + a[3288]=0; + a[3289]=0; + a[3290]=0; + a[3291]=0; + a[3292]=0; + a[3293]=0; + a[3294]=0; + a[3295]=0; + a[3296]=0; + a[3297]=0; + a[3298]=0; + a[3299]=0; + a[3300]=0; + a[3301]=0; + a[3302]=0; + a[3303]=0; + a[3304]=0; + a[3305]=0; + a[3306]=0; + a[3307]=0; + a[3308]=0; + a[3309]=0; + a[3310]=0; + a[3311]=0; + a[3312]=0; + a[3313]=0; + a[3314]=0; + a[3315]=0; + a[3316]=0; + a[3317]=0; + a[3318]=0; + a[3319]=0; + a[3320]=0; + a[3321]=0; + a[3322]=0; + a[3323]=0; + a[3324]=0; + a[3325]=0; + a[3326]=0; + a[3327]=0; + a[3328]=0; + a[3329]=0; + a[3330]=0; + a[3331]=0; + a[3332]=0; + a[3333]=0; + a[3334]=0; + a[3335]=0; + a[3336]=0; + a[3337]=0; + a[3338]=0; + a[3339]=0; + a[3340]=0; + a[3341]=0; + a[3342]=0; + a[3343]=0; + a[3344]=0; + a[3345]=0; + a[3346]=0; + a[3347]=0; + a[3348]=0; + a[3349]=0; + a[3350]=0; + a[3351]=0; + a[3352]=0; + a[3353]=0; + a[3354]=0; + a[3355]=0; + a[3356]=0; + a[3357]=0; + a[3358]=0; + a[3359]=0; + a[3360]=0; + a[3361]=0; + a[3362]=0; + a[3363]=0; + a[3364]=0; + a[3365]=0; + a[3366]=0; + a[3367]=0; + a[3368]=0; + a[3369]=0; + a[3370]=0; + a[3371]=0; + a[3372]=0; + a[3373]=0; + a[3374]=0; + a[3375]=0; + a[3376]=0; + a[3377]=0; + a[3378]=0; + a[3379]=0; + a[3380]=0; + a[3381]=0; + a[3382]=0; + a[3383]=0; + a[3384]=0; + a[3385]=0; + a[3386]=0; + a[3387]=0; + a[3388]=0; + a[3389]=0; + a[3390]=0; + a[3391]=0; + a[3392]=0; + a[3393]=0; + a[3394]=0; + a[3395]=0; + a[3396]=0; + a[3397]=0; + a[3398]=0; + a[3399]=0; + a[3400]=0; + a[3401]=0; + a[3402]=0; + a[3403]=0; + a[3404]=0; + a[3405]=0; + a[3406]=0; + a[3407]=0; + a[3408]=0; + a[3409]=0; + a[3410]=0; + a[3411]=0; + a[3412]=0; + a[3413]=0; + a[3414]=0; + a[3415]=0; + a[3416]=0; + a[3417]=0; + a[3418]=0; + a[3419]=0; + a[3420]=0; + a[3421]=0; + a[3422]=0; + a[3423]=0; + a[3424]=0; + a[3425]=0; + a[3426]=0; + a[3427]=0; + a[3428]=0; + a[3429]=0; + a[3430]=0; + a[3431]=0; + a[3432]=0; + a[3433]=0; + a[3434]=0; + a[3435]=0; + a[3436]=0; + a[3437]=0; + a[3438]=0; + a[3439]=0; + a[3440]=0; + a[3441]=0; + a[3442]=0; + a[3443]=0; + a[3444]=0; + a[3445]=0; + a[3446]=0; + a[3447]=0; + a[3448]=0; + a[3449]=0; + a[3450]=0; + a[3451]=0; + a[3452]=0; + a[3453]=0; + a[3454]=0; + a[3455]=0; + a[3456]=0; + a[3457]=0; + a[3458]=0; + a[3459]=0; + a[3460]=0; + a[3461]=0; + a[3462]=0; + a[3463]=0; + a[3464]=0; + a[3465]=0; + a[3466]=0; + a[3467]=0; + a[3468]=0; + a[3469]=0; + a[3470]=0; + a[3471]=0; + a[3472]=0; + a[3473]=0; + a[3474]=0; + a[3475]=0; + a[3476]=0; + a[3477]=0; + a[3478]=0; + a[3479]=0; + a[3480]=0; + a[3481]=0; + a[3482]=0; + a[3483]=0; + a[3484]=0; + a[3485]=0; + a[3486]=0; + a[3487]=0; + a[3488]=0; + a[3489]=0; + a[3490]=0; + a[3491]=0; + a[3492]=0; + a[3493]=0; + a[3494]=0; + a[3495]=0; + a[3496]=0; + a[3497]=0; + a[3498]=0; + a[3499]=0; + a[3500]=0; + a[3501]=0; + a[3502]=0; + a[3503]=0; + a[3504]=0; + a[3505]=0; + a[3506]=0; + a[3507]=0; + a[3508]=0; + a[3509]=0; + a[3510]=0; + a[3511]=0; + a[3512]=0; + a[3513]=0; + a[3514]=0; + a[3515]=0; + a[3516]=0; + a[3517]=0; + a[3518]=0; + a[3519]=0; + a[3520]=0; + a[3521]=0; + a[3522]=0; + a[3523]=0; + a[3524]=0; + a[3525]=0; + a[3526]=0; + a[3527]=0; + a[3528]=0; + a[3529]=0; + a[3530]=0; + a[3531]=0; + a[3532]=0; + a[3533]=0; + a[3534]=0; + a[3535]=0; + a[3536]=0; + a[3537]=0; + a[3538]=0; + a[3539]=0; + a[3540]=0; + a[3541]=0; + a[3542]=0; + a[3543]=0; + a[3544]=0; + a[3545]=0; + a[3546]=0; + a[3547]=0; + a[3548]=0; + a[3549]=0; + a[3550]=0; + a[3551]=0; + a[3552]=0; + a[3553]=0; + a[3554]=0; + a[3555]=0; + a[3556]=0; + a[3557]=0; + a[3558]=0; + a[3559]=0; + a[3560]=0; + a[3561]=0; + a[3562]=0; + a[3563]=0; + a[3564]=0; + a[3565]=0; + a[3566]=0; + a[3567]=0; + a[3568]=0; + a[3569]=0; + a[3570]=0; + a[3571]=0; + a[3572]=0; + a[3573]=0; + a[3574]=0; + a[3575]=0; + a[3576]=0; + a[3577]=0; + a[3578]=0; + a[3579]=0; + a[3580]=0; + a[3581]=0; + a[3582]=0; + a[3583]=0; + a[3584]=0; + a[3585]=0; + a[3586]=0; + a[3587]=0; + a[3588]=0; + a[3589]=0; + a[3590]=0; + a[3591]=0; + a[3592]=0; + a[3593]=0; + a[3594]=0; + a[3595]=0; + a[3596]=0; + a[3597]=0; + a[3598]=0; + a[3599]=0; + a[3600]=0; + a[3601]=0; + a[3602]=0; + a[3603]=0; + a[3604]=0; + a[3605]=0; + a[3606]=0; + a[3607]=0; + a[3608]=0; + a[3609]=0; + a[3610]=0; + a[3611]=0; + a[3612]=0; + a[3613]=0; + a[3614]=0; + a[3615]=0; + a[3616]=0; + a[3617]=0; + a[3618]=0; + a[3619]=0; + a[3620]=0; + a[3621]=0; + a[3622]=0; + a[3623]=0; + a[3624]=0; + a[3625]=0; + a[3626]=0; + a[3627]=0; + a[3628]=0; + a[3629]=0; + a[3630]=0; + a[3631]=0; + a[3632]=0; + a[3633]=0; + a[3634]=0; + a[3635]=0; + a[3636]=0; + a[3637]=0; + a[3638]=0; + a[3639]=0; + a[3640]=0; + a[3641]=0; + a[3642]=0; + a[3643]=0; + a[3644]=0; + a[3645]=0; + a[3646]=0; + a[3647]=0; + a[3648]=0; + a[3649]=0; + a[3650]=0; + a[3651]=0; + a[3652]=0; + a[3653]=0; + a[3654]=0; + a[3655]=0; + a[3656]=0; + a[3657]=0; + a[3658]=0; + a[3659]=0; + a[3660]=0; + a[3661]=0; + a[3662]=0; + a[3663]=0; + a[3664]=0; + a[3665]=0; + a[3666]=0; + a[3667]=0; + a[3668]=0; + a[3669]=0; + a[3670]=0; + a[3671]=0; + a[3672]=0; + a[3673]=0; + a[3674]=0; + a[3675]=0; + a[3676]=0; + a[3677]=0; + a[3678]=0; + a[3679]=0; + a[3680]=0; + a[3681]=0; + a[3682]=0; + a[3683]=0; + a[3684]=0; + a[3685]=0; + a[3686]=0; + a[3687]=0; + a[3688]=0; + a[3689]=0; + a[3690]=0; + a[3691]=0; + a[3692]=0; + a[3693]=0; + a[3694]=0; + a[3695]=0; + a[3696]=0; + a[3697]=0; + a[3698]=0; + a[3699]=0; + a[3700]=0; + a[3701]=0; + a[3702]=0; + a[3703]=0; + a[3704]=0; + a[3705]=0; + a[3706]=0; + a[3707]=0; + a[3708]=0; + a[3709]=0; + a[3710]=0; + a[3711]=0; + a[3712]=0; + a[3713]=0; + a[3714]=0; + a[3715]=0; + a[3716]=0; + a[3717]=0; + a[3718]=0; + a[3719]=0; + a[3720]=0; + a[3721]=0; + a[3722]=0; + a[3723]=0; + a[3724]=0; + a[3725]=0; + a[3726]=0; + a[3727]=0; + a[3728]=0; + a[3729]=0; + a[3730]=0; + a[3731]=0; + a[3732]=0; + a[3733]=0; + a[3734]=0; + a[3735]=0; + a[3736]=0; + a[3737]=0; + a[3738]=0; + a[3739]=0; + a[3740]=0; + a[3741]=0; + a[3742]=0; + a[3743]=0; + a[3744]=0; + a[3745]=0; + a[3746]=0; + a[3747]=0; + a[3748]=0; + a[3749]=0; + a[3750]=0; + a[3751]=0; + a[3752]=0; + a[3753]=0; + a[3754]=0; + a[3755]=0; + a[3756]=0; + a[3757]=0; + a[3758]=0; + a[3759]=0; + a[3760]=0; + a[3761]=0; + a[3762]=0; + a[3763]=0; + a[3764]=0; + a[3765]=0; + a[3766]=0; + a[3767]=0; + a[3768]=0; + a[3769]=0; + a[3770]=0; + a[3771]=0; + a[3772]=0; + a[3773]=0; + a[3774]=0; + a[3775]=0; + a[3776]=0; + a[3777]=0; + a[3778]=0; + a[3779]=0; + a[3780]=0; + a[3781]=0; + a[3782]=0; + a[3783]=0; + a[3784]=0; + a[3785]=0; + a[3786]=0; + a[3787]=0; + a[3788]=0; + a[3789]=0; + a[3790]=0; + a[3791]=0; + a[3792]=0; + a[3793]=0; + a[3794]=0; + a[3795]=0; + a[3796]=0; + a[3797]=0; + a[3798]=0; + a[3799]=0; + a[3800]=0; + a[3801]=0; + a[3802]=0; + a[3803]=0; + a[3804]=0; + a[3805]=0; + a[3806]=0; + a[3807]=0; + a[3808]=0; + a[3809]=0; + a[3810]=0; + a[3811]=0; + a[3812]=0; + a[3813]=0; + a[3814]=0; + a[3815]=0; + a[3816]=0; + a[3817]=0; + a[3818]=0; + a[3819]=0; + a[3820]=0; + a[3821]=0; + a[3822]=0; + a[3823]=0; + a[3824]=0; + a[3825]=0; + a[3826]=0; + a[3827]=0; + a[3828]=0; + a[3829]=0; + a[3830]=0; + a[3831]=0; + a[3832]=0; + a[3833]=0; + a[3834]=0; + a[3835]=0; + a[3836]=0; + a[3837]=0; + a[3838]=0; + a[3839]=0; + a[3840]=0; + a[3841]=0; + a[3842]=0; + a[3843]=0; + a[3844]=0; + a[3845]=0; + a[3846]=0; + a[3847]=0; + a[3848]=0; + a[3849]=0; + a[3850]=0; + a[3851]=0; + a[3852]=0; + a[3853]=0; + a[3854]=0; + a[3855]=0; + a[3856]=0; + a[3857]=0; + a[3858]=0; + a[3859]=0; + a[3860]=0; + a[3861]=0; + a[3862]=0; + a[3863]=0; + a[3864]=0; + a[3865]=0; + a[3866]=0; + a[3867]=0; + a[3868]=0; + a[3869]=0; + a[3870]=0; + a[3871]=0; + a[3872]=0; + a[3873]=0; + a[3874]=0; + a[3875]=0; + a[3876]=0; + a[3877]=0; + a[3878]=0; + a[3879]=0; + a[3880]=0; + a[3881]=0; + a[3882]=0; + a[3883]=0; + a[3884]=0; + a[3885]=0; + a[3886]=0; + a[3887]=0; + a[3888]=0; + a[3889]=0; + a[3890]=0; + a[3891]=0; + a[3892]=0; + a[3893]=0; + a[3894]=0; + a[3895]=0; + a[3896]=0; + a[3897]=0; + a[3898]=0; + a[3899]=0; + a[3900]=0; + a[3901]=0; + a[3902]=0; + a[3903]=0; + a[3904]=0; + a[3905]=0; + a[3906]=0; + a[3907]=0; + a[3908]=0; + a[3909]=0; + a[3910]=0; + a[3911]=0; + a[3912]=0; + a[3913]=0; + a[3914]=0; + a[3915]=0; + a[3916]=0; + a[3917]=0; + a[3918]=0; + a[3919]=0; + a[3920]=0; + a[3921]=0; + a[3922]=0; + a[3923]=0; + a[3924]=0; + a[3925]=0; + a[3926]=0; + a[3927]=0; + a[3928]=0; + a[3929]=0; + a[3930]=0; + a[3931]=0; + a[3932]=0; + a[3933]=0; + a[3934]=0; + a[3935]=0; + a[3936]=0; + a[3937]=0; + a[3938]=0; + a[3939]=0; + a[3940]=0; + a[3941]=0; + a[3942]=0; + a[3943]=0; + a[3944]=0; + a[3945]=0; + a[3946]=0; + a[3947]=0; + a[3948]=0; + a[3949]=0; + a[3950]=0; + a[3951]=0; + a[3952]=0; + a[3953]=0; + a[3954]=0; + a[3955]=0; + a[3956]=0; + a[3957]=0; + a[3958]=0; + a[3959]=0; + a[3960]=0; + a[3961]=0; + a[3962]=0; + a[3963]=0; + a[3964]=0; + a[3965]=0; + a[3966]=0; + a[3967]=0; + a[3968]=0; + a[3969]=0; + a[3970]=0; + a[3971]=0; + a[3972]=0; + a[3973]=0; + a[3974]=0; + a[3975]=0; + a[3976]=0; + a[3977]=0; + a[3978]=0; + a[3979]=0; + a[3980]=0; + a[3981]=0; + a[3982]=0; + a[3983]=0; + a[3984]=0; + a[3985]=0; + a[3986]=0; + a[3987]=0; + a[3988]=0; + a[3989]=0; + a[3990]=0; + a[3991]=0; + a[3992]=0; + a[3993]=0; + a[3994]=0; + a[3995]=0; + a[3996]=0; + a[3997]=0; + a[3998]=0; + a[3999]=0; + a[4000]=0; + a[4001]=0; + a[4002]=0; + a[4003]=0; + a[4004]=0; + a[4005]=0; + a[4006]=0; + a[4007]=0; + a[4008]=0; + a[4009]=0; + a[4010]=0; + a[4011]=0; + a[4012]=0; + a[4013]=0; + a[4014]=0; + a[4015]=0; + a[4016]=0; + a[4017]=0; + a[4018]=0; + a[4019]=0; + a[4020]=0; + a[4021]=0; + a[4022]=0; + a[4023]=0; + a[4024]=0; + a[4025]=0; + a[4026]=0; + a[4027]=0; + a[4028]=0; + a[4029]=0; + a[4030]=0; + a[4031]=0; + a[4032]=0; + a[4033]=0; + a[4034]=0; + a[4035]=0; + a[4036]=0; + a[4037]=0; + a[4038]=0; + a[4039]=0; + a[4040]=0; + a[4041]=0; + a[4042]=0; + a[4043]=0; + a[4044]=0; + a[4045]=0; + a[4046]=0; + a[4047]=0; + a[4048]=0; + a[4049]=0; + a[4050]=0; + a[4051]=0; + a[4052]=0; + a[4053]=0; + a[4054]=0; + a[4055]=0; + a[4056]=0; + a[4057]=0; + a[4058]=0; + a[4059]=0; + a[4060]=0; + a[4061]=0; + a[4062]=0; + a[4063]=0; + a[4064]=0; + a[4065]=0; + a[4066]=0; + a[4067]=0; + a[4068]=0; + a[4069]=0; + a[4070]=0; + a[4071]=0; + a[4072]=0; + a[4073]=0; + a[4074]=0; + a[4075]=0; + a[4076]=0; + a[4077]=0; + a[4078]=0; + a[4079]=0; + a[4080]=0; + a[4081]=0; + a[4082]=0; + a[4083]=0; + a[4084]=0; + a[4085]=0; + a[4086]=0; + a[4087]=0; + a[4088]=0; + a[4089]=0; + a[4090]=0; + a[4091]=0; + a[4092]=0; + a[4093]=0; + a[4094]=0; + a[4095]=0; + a[4096]=0; + a[4097]=0; + a[4098]=0; + a[4099]=0; + a[4100]=0; + a[4101]=0; + a[4102]=0; + a[4103]=0; + a[4104]=0; + a[4105]=0; + a[4106]=0; + a[4107]=0; + a[4108]=0; + a[4109]=0; + a[4110]=0; + a[4111]=0; + a[4112]=0; + a[4113]=0; + a[4114]=0; + a[4115]=0; + a[4116]=0; + a[4117]=0; + a[4118]=0; + a[4119]=0; + a[4120]=0; + a[4121]=0; + a[4122]=0; + a[4123]=0; + a[4124]=0; + a[4125]=0; + a[4126]=0; + a[4127]=0; + a[4128]=0; + a[4129]=0; + a[4130]=0; + a[4131]=0; + a[4132]=0; + a[4133]=0; + a[4134]=0; + a[4135]=0; + a[4136]=0; + a[4137]=0; + a[4138]=0; + a[4139]=0; + a[4140]=0; + a[4141]=0; + a[4142]=0; + a[4143]=0; + a[4144]=0; + a[4145]=0; + a[4146]=0; + a[4147]=0; + a[4148]=0; + a[4149]=0; + a[4150]=0; + a[4151]=0; + a[4152]=0; + a[4153]=0; + a[4154]=0; + a[4155]=0; + a[4156]=0; + a[4157]=0; + a[4158]=0; + a[4159]=0; + a[4160]=0; + a[4161]=0; + a[4162]=0; + a[4163]=0; + a[4164]=0; + a[4165]=0; + a[4166]=0; + a[4167]=0; + a[4168]=0; + a[4169]=0; + a[4170]=0; + a[4171]=0; + a[4172]=0; + a[4173]=0; + a[4174]=0; + a[4175]=0; + a[4176]=0; + a[4177]=0; + a[4178]=0; + a[4179]=0; + a[4180]=0; + a[4181]=0; + a[4182]=0; + a[4183]=0; + a[4184]=0; + a[4185]=0; + a[4186]=0; + a[4187]=0; + a[4188]=0; + a[4189]=0; + a[4190]=0; + a[4191]=0; + a[4192]=0; + a[4193]=0; + a[4194]=0; + a[4195]=0; + a[4196]=0; + a[4197]=0; + a[4198]=0; + a[4199]=0; + a[4200]=0; + a[4201]=0; + a[4202]=0; + a[4203]=0; + a[4204]=0; + a[4205]=0; + a[4206]=0; + a[4207]=0; + a[4208]=0; + a[4209]=0; + a[4210]=0; + a[4211]=0; + a[4212]=0; + a[4213]=0; + a[4214]=0; + a[4215]=0; + a[4216]=0; + a[4217]=0; + a[4218]=0; + a[4219]=0; + a[4220]=0; + a[4221]=0; + a[4222]=0; + a[4223]=0; + a[4224]=0; + a[4225]=0; + a[4226]=0; + a[4227]=0; + a[4228]=0; + a[4229]=0; + a[4230]=0; + a[4231]=0; + a[4232]=0; + a[4233]=0; + a[4234]=0; + a[4235]=0; + a[4236]=0; + a[4237]=0; + a[4238]=0; + a[4239]=0; + a[4240]=0; + a[4241]=0; + a[4242]=0; + a[4243]=0; + a[4244]=0; + a[4245]=0; + a[4246]=0; + a[4247]=0; + a[4248]=0; + a[4249]=0; + a[4250]=0; + a[4251]=0; + a[4252]=0; + a[4253]=0; + a[4254]=0; + a[4255]=0; + a[4256]=0; + a[4257]=0; + a[4258]=0; + a[4259]=0; + a[4260]=0; + a[4261]=0; + a[4262]=0; + a[4263]=0; + a[4264]=0; + a[4265]=0; + a[4266]=0; + a[4267]=0; + a[4268]=0; + a[4269]=0; + a[4270]=0; + a[4271]=0; + a[4272]=0; + a[4273]=0; + a[4274]=0; + a[4275]=0; + a[4276]=0; + a[4277]=0; + a[4278]=0; + a[4279]=0; + a[4280]=0; + a[4281]=0; + a[4282]=0; + a[4283]=0; + a[4284]=0; + a[4285]=0; + a[4286]=0; + a[4287]=0; + a[4288]=0; + a[4289]=0; + a[4290]=0; + a[4291]=0; + a[4292]=0; + a[4293]=0; + a[4294]=0; + a[4295]=0; + a[4296]=0; + a[4297]=0; + a[4298]=0; + a[4299]=0; + a[4300]=0; + a[4301]=0; + a[4302]=0; + a[4303]=0; + a[4304]=0; + a[4305]=0; + a[4306]=0; + a[4307]=0; + a[4308]=0; + a[4309]=0; + a[4310]=0; + a[4311]=0; + a[4312]=0; + a[4313]=0; + a[4314]=0; + a[4315]=0; + a[4316]=0; + a[4317]=0; + a[4318]=0; + a[4319]=0; + a[4320]=0; + a[4321]=0; + a[4322]=0; + a[4323]=0; + a[4324]=0; + a[4325]=0; + a[4326]=0; + a[4327]=0; + a[4328]=0; + a[4329]=0; + a[4330]=0; + a[4331]=0; + a[4332]=0; + a[4333]=0; + a[4334]=0; + a[4335]=0; + a[4336]=0; + a[4337]=0; + a[4338]=0; + a[4339]=0; + a[4340]=0; + a[4341]=0; + a[4342]=0; + a[4343]=0; + a[4344]=0; + a[4345]=0; + a[4346]=0; + a[4347]=0; + a[4348]=0; + a[4349]=0; + a[4350]=0; + a[4351]=0; + a[4352]=0; + a[4353]=0; + a[4354]=0; + a[4355]=0; + a[4356]=0; + a[4357]=0; + a[4358]=0; + a[4359]=0; + a[4360]=0; + a[4361]=0; + a[4362]=0; + a[4363]=0; + a[4364]=0; + a[4365]=0; + a[4366]=0; + a[4367]=0; + a[4368]=0; + a[4369]=0; + a[4370]=0; + a[4371]=0; + a[4372]=0; + a[4373]=0; + a[4374]=0; + a[4375]=0; + a[4376]=0; + a[4377]=0; + a[4378]=0; + a[4379]=0; + a[4380]=0; + a[4381]=0; + a[4382]=0; + a[4383]=0; + a[4384]=0; + a[4385]=0; + a[4386]=0; + a[4387]=0; + a[4388]=0; + a[4389]=0; + a[4390]=0; + a[4391]=0; + a[4392]=0; + a[4393]=0; + a[4394]=0; + a[4395]=0; + a[4396]=0; + a[4397]=0; + a[4398]=0; + a[4399]=0; + a[4400]=0; + a[4401]=0; + a[4402]=0; + a[4403]=0; + a[4404]=0; + a[4405]=0; + a[4406]=0; + a[4407]=0; + a[4408]=0; + a[4409]=0; + a[4410]=0; + a[4411]=0; + a[4412]=0; + a[4413]=0; + a[4414]=0; + a[4415]=0; + a[4416]=0; + a[4417]=0; + a[4418]=0; + a[4419]=0; + a[4420]=0; + a[4421]=0; + a[4422]=0; + a[4423]=0; + a[4424]=0; + a[4425]=0; + a[4426]=0; + a[4427]=0; + a[4428]=0; + a[4429]=0; + a[4430]=0; + a[4431]=0; + a[4432]=0; + a[4433]=0; + a[4434]=0; + a[4435]=0; + a[4436]=0; + a[4437]=0; + a[4438]=0; + a[4439]=0; + a[4440]=0; + a[4441]=0; + a[4442]=0; + a[4443]=0; + a[4444]=0; + a[4445]=0; + a[4446]=0; + a[4447]=0; + a[4448]=0; + a[4449]=0; + a[4450]=0; + a[4451]=0; + a[4452]=0; + a[4453]=0; + a[4454]=0; + a[4455]=0; + a[4456]=0; + a[4457]=0; + a[4458]=0; + a[4459]=0; + a[4460]=0; + a[4461]=0; + a[4462]=0; + a[4463]=0; + a[4464]=0; + a[4465]=0; + a[4466]=0; + a[4467]=0; + a[4468]=0; + a[4469]=0; + a[4470]=0; + a[4471]=0; + a[4472]=0; + a[4473]=0; + a[4474]=0; + a[4475]=0; + a[4476]=0; + a[4477]=0; + a[4478]=0; + a[4479]=0; + a[4480]=0; + a[4481]=0; + a[4482]=0; + a[4483]=0; + a[4484]=0; + a[4485]=0; + a[4486]=0; + a[4487]=0; + a[4488]=0; + a[4489]=0; + a[4490]=0; + a[4491]=0; + a[4492]=0; + a[4493]=0; + a[4494]=0; + a[4495]=0; + a[4496]=0; + a[4497]=0; + a[4498]=0; + a[4499]=0; + a[4500]=0; + a[4501]=0; + a[4502]=0; + a[4503]=0; + a[4504]=0; + a[4505]=0; + a[4506]=0; + a[4507]=0; + a[4508]=0; + a[4509]=0; + a[4510]=0; + a[4511]=0; + a[4512]=0; + a[4513]=0; + a[4514]=0; + a[4515]=0; + a[4516]=0; + a[4517]=0; + a[4518]=0; + a[4519]=0; + a[4520]=0; + a[4521]=0; + a[4522]=0; + a[4523]=0; + a[4524]=0; + a[4525]=0; + a[4526]=0; + a[4527]=0; + a[4528]=0; + a[4529]=0; + a[4530]=0; + a[4531]=0; + a[4532]=0; + a[4533]=0; + a[4534]=0; + a[4535]=0; + a[4536]=0; + a[4537]=0; + a[4538]=0; + a[4539]=0; + a[4540]=0; + a[4541]=0; + a[4542]=0; + a[4543]=0; + a[4544]=0; + a[4545]=0; + a[4546]=0; + a[4547]=0; + a[4548]=0; + a[4549]=0; + a[4550]=0; + a[4551]=0; + a[4552]=0; + a[4553]=0; + a[4554]=0; + a[4555]=0; + a[4556]=0; + a[4557]=0; + a[4558]=0; + a[4559]=0; + a[4560]=0; + a[4561]=0; + a[4562]=0; + a[4563]=0; + a[4564]=0; + a[4565]=0; + a[4566]=0; + a[4567]=0; + a[4568]=0; + a[4569]=0; + a[4570]=0; + a[4571]=0; + a[4572]=0; + a[4573]=0; + a[4574]=0; + a[4575]=0; + a[4576]=0; + a[4577]=0; + a[4578]=0; + a[4579]=0; + a[4580]=0; + a[4581]=0; + a[4582]=0; + a[4583]=0; + a[4584]=0; + a[4585]=0; + a[4586]=0; + a[4587]=0; + a[4588]=0; + a[4589]=0; + a[4590]=0; + a[4591]=0; + a[4592]=0; + a[4593]=0; + a[4594]=0; + a[4595]=0; + a[4596]=0; + a[4597]=0; + a[4598]=0; + a[4599]=0; + a[4600]=0; + a[4601]=0; + a[4602]=0; + a[4603]=0; + a[4604]=0; + a[4605]=0; + a[4606]=0; + a[4607]=0; + a[4608]=0; + a[4609]=0; + a[4610]=0; + a[4611]=0; + a[4612]=0; + a[4613]=0; + a[4614]=0; + a[4615]=0; + a[4616]=0; + a[4617]=0; + a[4618]=0; + a[4619]=0; + a[4620]=0; + a[4621]=0; + a[4622]=0; + a[4623]=0; + a[4624]=0; + a[4625]=0; + a[4626]=0; + a[4627]=0; + a[4628]=0; + a[4629]=0; + a[4630]=0; + a[4631]=0; + a[4632]=0; + a[4633]=0; + a[4634]=0; + a[4635]=0; + a[4636]=0; + a[4637]=0; + a[4638]=0; + a[4639]=0; + a[4640]=0; + a[4641]=0; + a[4642]=0; + a[4643]=0; + a[4644]=0; + a[4645]=0; + a[4646]=0; + a[4647]=0; + a[4648]=0; + a[4649]=0; + a[4650]=0; + a[4651]=0; + a[4652]=0; + a[4653]=0; + a[4654]=0; + a[4655]=0; + a[4656]=0; + a[4657]=0; + a[4658]=0; + a[4659]=0; + a[4660]=0; + a[4661]=0; + a[4662]=0; + a[4663]=0; + a[4664]=0; + a[4665]=0; + a[4666]=0; + a[4667]=0; + a[4668]=0; + a[4669]=0; + a[4670]=0; + a[4671]=0; + a[4672]=0; + a[4673]=0; + a[4674]=0; + a[4675]=0; + a[4676]=0; + a[4677]=0; + a[4678]=0; + a[4679]=0; + a[4680]=0; + a[4681]=0; + a[4682]=0; + a[4683]=0; + a[4684]=0; + a[4685]=0; + a[4686]=0; + a[4687]=0; + a[4688]=0; + a[4689]=0; + a[4690]=0; + a[4691]=0; + a[4692]=0; + a[4693]=0; + a[4694]=0; + a[4695]=0; + a[4696]=0; + a[4697]=0; + a[4698]=0; + a[4699]=0; + a[4700]=0; + a[4701]=0; + a[4702]=0; + a[4703]=0; + a[4704]=0; + a[4705]=0; + a[4706]=0; + a[4707]=0; + a[4708]=0; + a[4709]=0; + a[4710]=0; + a[4711]=0; + a[4712]=0; + a[4713]=0; + a[4714]=0; + a[4715]=0; + a[4716]=0; + a[4717]=0; + a[4718]=0; + a[4719]=0; + a[4720]=0; + a[4721]=0; + a[4722]=0; + a[4723]=0; + a[4724]=0; + a[4725]=0; + a[4726]=0; + a[4727]=0; + a[4728]=0; + a[4729]=0; + a[4730]=0; + a[4731]=0; + a[4732]=0; + a[4733]=0; + a[4734]=0; + a[4735]=0; + a[4736]=0; + a[4737]=0; + a[4738]=0; + a[4739]=0; + a[4740]=0; + a[4741]=0; + a[4742]=0; + a[4743]=0; + a[4744]=0; + a[4745]=0; + a[4746]=0; + a[4747]=0; + a[4748]=0; + a[4749]=0; + a[4750]=0; + a[4751]=0; + a[4752]=0; + a[4753]=0; + a[4754]=0; + a[4755]=0; + a[4756]=0; + a[4757]=0; + a[4758]=0; + a[4759]=0; + a[4760]=0; + a[4761]=0; + a[4762]=0; + a[4763]=0; + a[4764]=0; + a[4765]=0; + a[4766]=0; + a[4767]=0; + a[4768]=0; + a[4769]=0; + a[4770]=0; + a[4771]=0; + a[4772]=0; + a[4773]=0; + a[4774]=0; + a[4775]=0; + a[4776]=0; + a[4777]=0; + a[4778]=0; + a[4779]=0; + a[4780]=0; + a[4781]=0; + a[4782]=0; + a[4783]=0; + a[4784]=0; + a[4785]=0; + a[4786]=0; + a[4787]=0; + a[4788]=0; + a[4789]=0; + a[4790]=0; + a[4791]=0; + a[4792]=0; + a[4793]=0; + a[4794]=0; + a[4795]=0; + a[4796]=0; + a[4797]=0; + a[4798]=0; + a[4799]=0; + a[4800]=0; + a[4801]=0; + a[4802]=0; + a[4803]=0; + a[4804]=0; + a[4805]=0; + a[4806]=0; + a[4807]=0; + a[4808]=0; + a[4809]=0; + a[4810]=0; + a[4811]=0; + a[4812]=0; + a[4813]=0; + a[4814]=0; + a[4815]=0; + a[4816]=0; + a[4817]=0; + a[4818]=0; + a[4819]=0; + a[4820]=0; + a[4821]=0; + a[4822]=0; + a[4823]=0; + a[4824]=0; + a[4825]=0; + a[4826]=0; + a[4827]=0; + a[4828]=0; + a[4829]=0; + a[4830]=0; + a[4831]=0; + a[4832]=0; + a[4833]=0; + a[4834]=0; + a[4835]=0; + a[4836]=0; + a[4837]=0; + a[4838]=0; + a[4839]=0; + a[4840]=0; + a[4841]=0; + a[4842]=0; + a[4843]=0; + a[4844]=0; + a[4845]=0; + a[4846]=0; + a[4847]=0; + a[4848]=0; + a[4849]=0; + a[4850]=0; + a[4851]=0; + a[4852]=0; + a[4853]=0; + a[4854]=0; + a[4855]=0; + a[4856]=0; + a[4857]=0; + a[4858]=0; + a[4859]=0; + a[4860]=0; + a[4861]=0; + a[4862]=0; + a[4863]=0; + a[4864]=0; + a[4865]=0; + a[4866]=0; + a[4867]=0; + a[4868]=0; + a[4869]=0; + a[4870]=0; + a[4871]=0; + a[4872]=0; + a[4873]=0; + a[4874]=0; + a[4875]=0; + a[4876]=0; + a[4877]=0; + a[4878]=0; + a[4879]=0; + a[4880]=0; + a[4881]=0; + a[4882]=0; + a[4883]=0; + a[4884]=0; + a[4885]=0; + a[4886]=0; + a[4887]=0; + a[4888]=0; + a[4889]=0; + a[4890]=0; + a[4891]=0; + a[4892]=0; + a[4893]=0; + a[4894]=0; + a[4895]=0; + a[4896]=0; + a[4897]=0; + a[4898]=0; + a[4899]=0; + a[4900]=0; + a[4901]=0; + a[4902]=0; + a[4903]=0; + a[4904]=0; + a[4905]=0; + a[4906]=0; + a[4907]=0; + a[4908]=0; + a[4909]=0; + a[4910]=0; + a[4911]=0; + a[4912]=0; + a[4913]=0; + a[4914]=0; + a[4915]=0; + a[4916]=0; + a[4917]=0; + a[4918]=0; + a[4919]=0; + a[4920]=0; + a[4921]=0; + a[4922]=0; + a[4923]=0; + a[4924]=0; + a[4925]=0; + a[4926]=0; + a[4927]=0; + a[4928]=0; + a[4929]=0; + a[4930]=0; + a[4931]=0; + a[4932]=0; + a[4933]=0; + a[4934]=0; + a[4935]=0; + a[4936]=0; + a[4937]=0; + a[4938]=0; + a[4939]=0; + a[4940]=0; + a[4941]=0; + a[4942]=0; + a[4943]=0; + a[4944]=0; + a[4945]=0; + a[4946]=0; + a[4947]=0; + a[4948]=0; + a[4949]=0; + a[4950]=0; + a[4951]=0; + a[4952]=0; + a[4953]=0; + a[4954]=0; + a[4955]=0; + a[4956]=0; + a[4957]=0; + a[4958]=0; + a[4959]=0; + a[4960]=0; + a[4961]=0; + a[4962]=0; + a[4963]=0; + a[4964]=0; + a[4965]=0; + a[4966]=0; + a[4967]=0; + a[4968]=0; + a[4969]=0; + a[4970]=0; + a[4971]=0; + a[4972]=0; + a[4973]=0; + a[4974]=0; + a[4975]=0; + a[4976]=0; + a[4977]=0; + a[4978]=0; + a[4979]=0; + a[4980]=0; + a[4981]=0; + a[4982]=0; + a[4983]=0; + a[4984]=0; + a[4985]=0; + a[4986]=0; + a[4987]=0; + a[4988]=0; + a[4989]=0; + a[4990]=0; + a[4991]=0; + a[4992]=0; + a[4993]=0; + a[4994]=0; + a[4995]=0; + a[4996]=0; + a[4997]=0; + a[4998]=0; + a[4999]=0; + return a; +} diff --git a/test/mjsunit/regress/regress-1973.js b/test/mjsunit/regress/regress-1973.js new file mode 100644 index 00000000..8708bf12 --- /dev/null +++ b/test/mjsunit/regress/regress-1973.js @@ -0,0 +1,52 @@ +// 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. + +// Test that getters and setters pass unwrapped this values in strict mode +// and wrapped this values is non-strict mode. + +function TestAccessorWrapping(primitive) { + var prototype = Object.getPrototypeOf(Object(primitive)) + // Check that strict mode passes unwrapped this value. + var strict_type = typeof primitive; + Object.defineProperty(prototype, "strict", { + get: function() { "use strict"; assertSame(strict_type, typeof this); }, + set: function() { "use strict"; assertSame(strict_type, typeof this); } + }); + primitive.strict = primitive.strict; + // Check that non-strict mode passes wrapped this value. + var sloppy_type = typeof Object(primitive); + Object.defineProperty(prototype, "sloppy", { + get: function() { assertSame(sloppy_type, typeof this); }, + set: function() { assertSame(sloppy_type, typeof this); } + }); + primitive.sloppy = primitive.sloppy; +} + +TestAccessorWrapping(true); +TestAccessorWrapping(0); +TestAccessorWrapping({}); +TestAccessorWrapping(""); diff --git a/test/mjsunit/regress/regress-1980.js b/test/mjsunit/regress/regress-1980.js new file mode 100644 index 00000000..49dfd063 --- /dev/null +++ b/test/mjsunit/regress/regress-1980.js @@ -0,0 +1,40 @@ +// Copyright 2011 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. + +// See: http://code.google.com/p/v8/issues/detail?id=1980 + +var invalid_this = [ "invalid", 23, undefined, null ]; +for (var i = 0; i < invalid_this.length; i++) { + var exception = false; + try { + Error.prototype.toString.call(invalid_this[i]); + } catch (e) { + exception = true; + assertTrue("called_on_non_object" == e.type); + } + assertTrue(exception); +} diff --git a/test/mjsunit/regress/regress-2045.js b/test/mjsunit/regress/regress-2045.js new file mode 100644 index 00000000..822ee1fa --- /dev/null +++ b/test/mjsunit/regress/regress-2045.js @@ -0,0 +1,49 @@ +// 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 + +function foo() { + assertEquals(2, arguments.length); +} + +function bar() { + G.x; + return foo.apply(this, arguments); +} + +function baz() { + return bar(1, 2); +} + +G = {x: 0}; +baz(); +baz(); +%OptimizeFunctionOnNextCall(baz); +baz(); +delete G.x; +baz(); diff --git a/test/mjsunit/regress/regress-2056.js b/test/mjsunit/regress/regress-2056.js new file mode 100644 index 00000000..d34a7500 --- /dev/null +++ b/test/mjsunit/regress/regress-2056.js @@ -0,0 +1,66 @@ +// 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 + +var cases = [ + [0.0, 0.0, 0.0, 0,0], + [undefined, 0.0, NaN, NaN], + [0.0, undefined, NaN, NaN], + [NaN, 0.0, NaN, NaN], + [0.0, NaN, NaN, NaN], + [-NaN, 0.0, NaN, NaN], + [0.0, -NaN, NaN, NaN], + [Infinity, 0.0, Infinity, 0.0], + [0.0, Infinity, Infinity, 0.0], + [-Infinity, 0.0, 0.0, -Infinity], + [0.0, -Infinity, 0.0, -Infinity] +]; + +function do_min(a, b) { + return Math.min(a, b); +} + +function do_max(a, b) { + return Math.max(a, b); +} + +// Make sure that non-crankshaft results match expectations. +for (i = 0; i < cases.length; ++i) { + var c = cases[i]; + assertEquals(c[3], do_min(c[0], c[1])); + assertEquals(c[2], do_max(c[0], c[1])); +} + +// Make sure that crankshaft results match expectations. +for (i = 0; i < cases.length; ++i) { + var c = cases[i]; + %OptimizeFunctionOnNextCall(do_min); + %OptimizeFunctionOnNextCall(do_max); + assertEquals(c[3], do_min(c[0], c[1])); + assertEquals(c[2], do_max(c[0], c[1])); +} diff --git a/test/mjsunit/regress/regress-397.js b/test/mjsunit/regress/regress-397.js index 111f4a6e..0e4143d0 100644 --- a/test/mjsunit/regress/regress-397.js +++ b/test/mjsunit/regress/regress-397.js @@ -25,10 +25,19 @@ // (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 // See http://code.google.com/p/v8/issues/detail?id=397 -assertEquals("Infinity", String(Math.pow(Infinity, 0.5))); -assertEquals(0, Math.pow(Infinity, -0.5)); -assertEquals("Infinity", String(Math.pow(-Infinity, 0.5))); -assertEquals(0, Math.pow(-Infinity, -0.5)); +function test() { + assertEquals("Infinity", String(Math.pow(Infinity, 0.5))); + assertEquals(0, Math.pow(Infinity, -0.5)); + + assertEquals("Infinity", String(Math.pow(-Infinity, 0.5))); + assertEquals(0, Math.pow(-Infinity, -0.5)); +} + +test(); +test(); +%OptimizeFunctionOnNextCall(test); +test(); diff --git a/test/mjsunit/regress/regress-877615.js b/test/mjsunit/regress/regress-877615.js index d35aba62..bec5a4d1 100644 --- a/test/mjsunit/regress/regress-877615.js +++ b/test/mjsunit/regress/regress-877615.js @@ -25,13 +25,13 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Number.prototype.toLocaleString = function() { return 'invalid'}; -assertEquals([1].toLocaleString(), 'invalid'); // invalid +Number.prototype.toLocaleString = function() { return 'invalid'; }; +assertEquals('invalid', [1].toLocaleString()); // invalid Number.prototype.toLocaleString = 'invalid'; -assertEquals([1].toLocaleString(), '1'); // 1 +assertThrows(function() { [1].toLocaleString(); }); // Not callable. +delete Number.prototype.toLocaleString; Number.prototype.toString = function() { return 'invalid' }; -assertEquals([1].toLocaleString(), '1'); // 1 -assertEquals([1].toString(), '1'); // 1 - +assertEquals([1].toLocaleString(), 'invalid'); // Uses ToObject on elements. +assertEquals([1].toString(), '1'); // Uses ToString directly on elements. diff --git a/test/mjsunit/regress/regress-91517.js b/test/mjsunit/regress/regress-91517.js deleted file mode 100644 index 68a768c4..00000000 --- a/test/mjsunit/regress/regress-91517.js +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2011 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. - -// Getting property names of an object with a prototype chain that -// triggers dictionary elements in GetLocalPropertyNames() shouldn't -// crash the runtime - -// Flags: --allow-natives-syntax - -function Object1() { - this.foo = 1; -} - -function Object2() { - this.fuz = 2; - this.objects = new Object(); - this.fuz1 = 2; - this.fuz2 = 2; - this.fuz3 = 2; - this.fuz4 = 2; - this.fuz5 = 2; - this.fuz6 = 2; - this.fuz7 = 2; - this.fuz8 = 2; - this.fuz9 = 2; - this.fuz10 = 2; - this.fuz11 = 2; - this.fuz12 = 2; - this.fuz13 = 2; - this.fuz14 = 2; - this.fuz15 = 2; - this.fuz16 = 2; - this.fuz17 = 2; - // Force dictionary-based properties - for (x=1;x<1000;x++) { - this["sdf" + x] = 2; - } -} - -function Object3() { - this.boo = 3; -} - -function Object4() { - this.baz = 4; -} - -obj1 = new Object1(); -obj2 = new Object2(); -obj3 = new Object3(); -obj4 = new Object4(); - -%SetHiddenPrototype(obj4, obj3); -%SetHiddenPrototype(obj3, obj2); -%SetHiddenPrototype(obj2, obj1); - -function contains(a, obj) { - for(var i = 0; i < a.length; i++) { - if(a[i] === obj){ - return true; - } - } - return false; -} -names = %GetLocalPropertyNames(obj4); -assertEquals(1021, names.length); -assertTrue(contains(names, "baz")); -assertTrue(contains(names, "boo")); -assertTrue(contains(names, "foo")); -assertTrue(contains(names, "fuz")); -assertTrue(contains(names, "fuz1")); -assertTrue(contains(names, "fuz2")); -assertTrue(contains(names, "fuz3")); -assertTrue(contains(names, "fuz4")); -assertTrue(contains(names, "fuz5")); -assertTrue(contains(names, "fuz6")); -assertTrue(contains(names, "fuz7")); -assertTrue(contains(names, "fuz8")); -assertTrue(contains(names, "fuz9")); -assertTrue(contains(names, "fuz10")); -assertTrue(contains(names, "fuz11")); -assertTrue(contains(names, "fuz12")); -assertTrue(contains(names, "fuz13")); -assertTrue(contains(names, "fuz14")); -assertTrue(contains(names, "fuz15")); -assertTrue(contains(names, "fuz16")); -assertTrue(contains(names, "fuz17")); -assertFalse(names[1020] == undefined); diff --git a/test/mjsunit/regress/regress-94873.js b/test/mjsunit/regress/regress-94873.js new file mode 100644 index 00000000..41ca9921 --- /dev/null +++ b/test/mjsunit/regress/regress-94873.js @@ -0,0 +1,78 @@ +// Copyright 2011 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: --expose-debug-as debug +// Get the Debug object exposed from the debug context global object. +Debug = debug.Debug; + +function sendCommand(state, cmd) { + // Get the debug command processor in paused state. + var dcp = state.debugCommandProcessor(false); + var request = JSON.stringify(cmd); + var response = dcp.processDebugJSONRequest(request); + return JSON.parse(response); +} + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + var line = event_data.sourceLineText(); + print('break: ' + line); + + var frame = sendCommand(exec_state, { + seq: 0, + type: "request", + command: "frame" + }); + + sendCommand(exec_state, { + seq: 0, + type: "request", + command: "evaluate", + arguments: { + expression: "obj.x.toString()", + additional_context: [{ + name: "obj", + handle: frame.body.receiver.ref + }] + } + }); + } + } catch (e) { + print(e); + } +} + +Debug.setListener(listener); + +function a(x, y) { + this.x = x; + this.y = y; +} + +Debug.setBreakPoint(a, 0, 0); +new a(1, 2);
\ No newline at end of file diff --git a/test/mjsunit/regress/regress-95113.js b/test/mjsunit/regress/regress-95113.js index f01b2700..468bff84 100644 --- a/test/mjsunit/regress/regress-95113.js +++ b/test/mjsunit/regress/regress-95113.js @@ -32,7 +32,7 @@ function get_double_array() { var i = 0; while (!%HasFastDoubleElements(a)) { a[i] = i; - i++; + i += 0.5; } assertTrue(%HasFastDoubleElements(a)); a.length = 1; diff --git a/test/mjsunit/regress/regress-98773.js b/test/mjsunit/regress/regress-98773.js new file mode 100644 index 00000000..eb24eb5d --- /dev/null +++ b/test/mjsunit/regress/regress-98773.js @@ -0,0 +1,39 @@ +// Copyright 2011 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. + +// Calling Array.sort on an external array is not supposed to crash. + +var array = new Int16Array(23); +array[7] = 7; array[9] = 9; +assertEquals(23, array.length); +assertEquals(7, array[7]); +assertEquals(9, array[9]); + +Array.prototype.sort.call(array); +assertEquals(23, array.length); +assertEquals(7, array[21]); +assertEquals(9, array[22]); diff --git a/test/mjsunit/regress/regress-99167.js b/test/mjsunit/regress/regress-99167.js new file mode 100644 index 00000000..5053ae5d --- /dev/null +++ b/test/mjsunit/regress/regress-99167.js @@ -0,0 +1,33 @@ +// Copyright 2011 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: --expose-gc --max-new-space-size=1024 + +eval("function Node() { this.a = 1; this.a = 3; }"); +new Node; +for (var i = 0; i < 4; ++i) gc(); +for (var i = 0; i < 100000; ++i) new Node; diff --git a/test/mjsunit/regress/regress-crbug-100859.js b/test/mjsunit/regress/regress-crbug-100859.js new file mode 100644 index 00000000..68244262 --- /dev/null +++ b/test/mjsunit/regress/regress-crbug-100859.js @@ -0,0 +1,39 @@ +// Copyright 2011 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. + +// This used to trigger a crash because of an unhandled stack overflow. +function setx() { + setx(typeof new Uint16Array('x') === 'object'); +} +var exception = false; +try { + setx(); +} catch (ex) { + assertTrue(ex instanceof RangeError); + exception = true; +} +assertTrue(exception); diff --git a/test/mjsunit/regress/regress-crbug-107996.js b/test/mjsunit/regress/regress-crbug-107996.js new file mode 100644 index 00000000..dfe07e59 --- /dev/null +++ b/test/mjsunit/regress/regress-crbug-107996.js @@ -0,0 +1,64 @@ +// 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: --expose-debug-as debug + +Debug = debug.Debug; + +Debug.setListener(listener); + +var fourteen; +var four_in_debugger = []; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + for (var i = 0; i < exec_state.frameCount(); i++) { + var frame = exec_state.frame(i); + four_in_debugger[i] = frame.evaluate("four", false).value(); + } + } +} + +function f1() { + var three = 3; + var four = 4; + (function f2() { + var seven = 7; + (function f3() { + debugger; + fourteen = three + four + seven; + })(); + })(); +} + +f1(); +assertEquals(14, fourteen); +assertEquals(4, four_in_debugger[0]); +assertEquals(4, four_in_debugger[1]); +assertEquals(4, four_in_debugger[2]); + +Debug.setListener(null); diff --git a/test/mjsunit/regress/regress-crbug-119926.js b/test/mjsunit/regress/regress-crbug-119926.js new file mode 100644 index 00000000..26b84fad --- /dev/null +++ b/test/mjsunit/regress/regress-crbug-119926.js @@ -0,0 +1,33 @@ +// 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. + +// Test that array elements don't break upon garbage collection. + +var a = new Array(500); +for (var i = 0; i < 500000; i++) { + a[i] = new Object(); +} diff --git a/test/mjsunit/regress/regress-debug-code-recompilation.js b/test/mjsunit/regress/regress-debug-code-recompilation.js new file mode 100644 index 00000000..1a608b14 --- /dev/null +++ b/test/mjsunit/regress/regress-debug-code-recompilation.js @@ -0,0 +1,47 @@ +// 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 --hydrogen-filter=Debug.setBreakPoint --expose-debug-as debug + +Debug = debug.Debug + +function f() {a=1;b=2}; +function g() { + a=1; + b=2; +} + +bp = Debug.setBreakPoint(f, 0, 0); +Debug.clearBreakPoint(bp); +%OptimizeFunctionOnNextCall(Debug.setBreakPoint); +bp = Debug.setBreakPoint(f, 0, 0); +Debug.clearBreakPoint(bp); +bp = Debug.setBreakPoint(f, 0, 0); +Debug.clearBreakPoint(bp); +%OptimizeFunctionOnNextCall(Debug.setBreakPoint); +bp = Debug.setBreakPoint(f, 0, 0); +Debug.clearBreakPoint(bp); diff --git a/test/mjsunit/regress/regress-deopt-gc.js b/test/mjsunit/regress/regress-deopt-gc.js index 7b7c29a3..a74e2c5e 100644 --- a/test/mjsunit/regress/regress-deopt-gc.js +++ b/test/mjsunit/regress/regress-deopt-gc.js @@ -42,7 +42,7 @@ function deopt() { // Make sure we don't inline this function try { var a = 42; } catch(o) {}; %DeoptimizeFunction(opt_me); - gc(true); + gc(); } diff --git a/test/mjsunit/regress/regress-inlining-function-literal-context.js b/test/mjsunit/regress/regress-inlining-function-literal-context.js new file mode 100644 index 00000000..9b7f7ac7 --- /dev/null +++ b/test/mjsunit/regress/regress-inlining-function-literal-context.js @@ -0,0 +1,53 @@ +// 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 --expose-gc + +function mkbaz(x) { + function baz() { + return function () { + return [x]; + } + } + return baz; +} + +var baz = mkbaz(1); + +function foo() { + var f = baz(); + return f(); +} + +// Tenure. +gc(); +gc(); + +assertArrayEquals([1], foo()); +assertArrayEquals([1], foo()); +%OptimizeFunctionOnNextCall(foo); +assertArrayEquals([1], foo()); diff --git a/test/mjsunit/regress/regress-smi-only-concat.js b/test/mjsunit/regress/regress-smi-only-concat.js new file mode 100644 index 00000000..a9a6d89b --- /dev/null +++ b/test/mjsunit/regress/regress-smi-only-concat.js @@ -0,0 +1,37 @@ +// 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 + +// This tests that concatenating a fast smi-only array and a fast object array +// results in a fast object array. + +var fast_array = ['a', 'b']; +var array = fast_array.concat(fast_array); + +assertTrue(%HasFastElements(fast_array)); +assertTrue(%HasFastElements(array));
\ No newline at end of file diff --git a/test/mjsunit/regress/regress-sqrt.js b/test/mjsunit/regress/regress-sqrt.js new file mode 100644 index 00000000..f2a7e552 --- /dev/null +++ b/test/mjsunit/regress/regress-sqrt.js @@ -0,0 +1,47 @@ +// 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 + +// Check that Math.sqrt returns the same value regardless of being +// optimized or not. + +function f(x) { + return Math.sqrt(x); +} + +var x = 7.0506280066499245e-233; + +var a = f(x); + +f(0.1); +f(0.2); +%OptimizeFunctionOnNextCall(f); + +var b = f(x); + +assertEquals(a, b); diff --git a/test/mjsunit/regress/short-circuit.js b/test/mjsunit/regress/short-circuit.js new file mode 100644 index 00000000..25363d6b --- /dev/null +++ b/test/mjsunit/regress/short-circuit.js @@ -0,0 +1,32 @@ +// Copyright 2011 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. + +var arr = []; + +for (var i = 0; i < 28000; i++) { + arr.push(new RegExp("prefix" + i.toString() + i.toString() + i.toString())); +} diff --git a/test/mjsunit/stack-traces-2.js b/test/mjsunit/stack-traces-2.js new file mode 100644 index 00000000..165c4dfc --- /dev/null +++ b/test/mjsunit/stack-traces-2.js @@ -0,0 +1,87 @@ +// Copyright 2011 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: --builtins-in-stack-traces + + +// Poisonous object that throws a reference error if attempted converted to +// a primitive values. +var thrower = { valueOf: function() { FAIL; }, + toString: function() { FAIL; } }; + +// Tests that a native constructor function is included in the +// stack trace. +function testTraceNativeConstructor(nativeFunc) { + var nativeFuncName = nativeFunc.name; + try { + new nativeFunc(thrower); + assertUnreachable(nativeFuncName); + } catch (e) { + assertTrue(e.stack.indexOf(nativeFuncName) >= 0, nativeFuncName); + } +} + +// Tests that a native conversion function is included in the +// stack trace. +function testTraceNativeConversion(nativeFunc) { + var nativeFuncName = nativeFunc.name; + try { + nativeFunc(thrower); + assertUnreachable(nativeFuncName); + } catch (e) { + assertTrue(e.stack.indexOf(nativeFuncName) >= 0, nativeFuncName); + } +} + + +function testNotOmittedBuiltin(throwing, included) { + try { + throwing(); + assertUnreachable(included); + } catch (e) { + assertTrue(e.stack.indexOf(included) >= 0, included); + } +} + + +testTraceNativeConversion(String); // Does ToString on argument. +testTraceNativeConversion(Number); // Does ToNumber on argument. +testTraceNativeConversion(RegExp); // Does ToString on argument. + +testTraceNativeConstructor(String); // Does ToString on argument. +testTraceNativeConstructor(Number); // Does ToNumber on argument. +testTraceNativeConstructor(RegExp); // Does ToString on argument. +testTraceNativeConstructor(Date); // Does ToNumber on argument. + +// QuickSort has builtins object as receiver, and is non-native +// builtin. Should not be omitted with the --builtins-in-stack-traces flag. +testNotOmittedBuiltin(function(){ [thrower, 2].sort(function (a,b) { + (b < a) - (a < b); }); + }, "QuickSort"); + +// Not omitted even though ADD from runtime.js is a non-native builtin. +testNotOmittedBuiltin(function(){ thrower + 2; }, "ADD");
\ No newline at end of file diff --git a/test/mjsunit/stack-traces.js b/test/mjsunit/stack-traces.js index 47a5cc59..536e71bb 100644 --- a/test/mjsunit/stack-traces.js +++ b/test/mjsunit/stack-traces.js @@ -194,6 +194,46 @@ function testErrorsDuringFormatting() { } +// Poisonous object that throws a reference error if attempted converted to +// a primitive values. +var thrower = { valueOf: function() { FAIL; }, + toString: function() { FAIL; } }; + +// Tests that a native constructor function is included in the +// stack trace. +function testTraceNativeConstructor(nativeFunc) { + var nativeFuncName = nativeFunc.name; + try { + new nativeFunc(thrower); + assertUnreachable(nativeFuncName); + } catch (e) { + assertTrue(e.stack.indexOf(nativeFuncName) >= 0, nativeFuncName); + } +} + +// Tests that a native conversion function is included in the +// stack trace. +function testTraceNativeConversion(nativeFunc) { + var nativeFuncName = nativeFunc.name; + try { + nativeFunc(thrower); + assertUnreachable(nativeFuncName); + } catch (e) { + assertTrue(e.stack.indexOf(nativeFuncName) >= 0, nativeFuncName); + } +} + + +function testOmittedBuiltin(throwing, omitted) { + try { + throwing(); + assertUnreachable(omitted); + } catch (e) { + assertTrue(e.stack.indexOf(omitted) < 0, omitted); + } +} + + testTrace("testArrayNative", testArrayNative, ["Array.map (native)"]); testTrace("testNested", testNested, ["at one", "at two", "at three"]); testTrace("testMethodNameInference", testMethodNameInference, ["at Foo.bar"]); @@ -217,3 +257,21 @@ testTrace("testStrippedCustomError", testStrippedCustomError, ["hep-hey"], testCallerCensorship(); testUnintendedCallerCensorship(); testErrorsDuringFormatting(); + +testTraceNativeConversion(String); // Does ToString on argument. +testTraceNativeConversion(Number); // Does ToNumber on argument. +testTraceNativeConversion(RegExp); // Does ToString on argument. + +testTraceNativeConstructor(String); // Does ToString on argument. +testTraceNativeConstructor(Number); // Does ToNumber on argument. +testTraceNativeConstructor(RegExp); // Does ToString on argument. +testTraceNativeConstructor(Date); // Does ToNumber on argument. + +// Omitted because QuickSort has builtins object as receiver, and is non-native +// builtin. +testOmittedBuiltin(function(){ [thrower, 2].sort(function (a,b) { + (b < a) - (a < b); }); + }, "QuickSort"); + +// Omitted because ADD from runtime.js is non-native builtin. +testOmittedBuiltin(function(){ thrower + 2; }, "ADD");
\ No newline at end of file diff --git a/test/mjsunit/strict-mode-implicit-receiver.js b/test/mjsunit/strict-mode-implicit-receiver.js index 338f6d10..8284eddc 100644 --- a/test/mjsunit/strict-mode-implicit-receiver.js +++ b/test/mjsunit/strict-mode-implicit-receiver.js @@ -168,12 +168,7 @@ outer_eval_conversion3(return_this, 'object'); outer_eval_conversion3(strict_eval, 'undefined'); outer_eval_conversion3(non_strict_eval, 'object'); -// TODO(ager): I'm not sure this is in accordance with the spec. At -// the moment, any call to eval where eval is not bound in the global -// context is treated as an indirect call to eval which means that the -// global context is used and the global object is passed as the -// receiver. -outer_eval_conversion3(eval, 'object'); +outer_eval_conversion3(eval, 'undefined'); function test_constant_function() { var o = { f: function() { "use strict"; return this; } }; diff --git a/test/mjsunit/strict-mode.js b/test/mjsunit/strict-mode.js index 30234ba6..9c9bdfd5 100644 --- a/test/mjsunit/strict-mode.js +++ b/test/mjsunit/strict-mode.js @@ -1051,14 +1051,20 @@ function CheckPillDescriptor(func, name) { } assertThrows(function() { strict.caller; }, TypeError); assertThrows(function() { strict.arguments; }, TypeError); + assertThrows(function() { strict.caller = 42; }, TypeError); + assertThrows(function() { strict.arguments = 42; }, TypeError); var another = new Function("'use strict'"); assertThrows(function() { another.caller; }, TypeError); assertThrows(function() { another.arguments; }, TypeError); + assertThrows(function() { another.caller = 42; }, TypeError); + assertThrows(function() { another.arguments = 42; }, TypeError); var third = (function() { "use strict"; return function() {}; })(); assertThrows(function() { third.caller; }, TypeError); assertThrows(function() { third.arguments; }, TypeError); + assertThrows(function() { third.caller = 42; }, TypeError); + assertThrows(function() { third.arguments = 42; }, TypeError); CheckPillDescriptor(strict, "caller"); CheckPillDescriptor(strict, "arguments"); diff --git a/test/mjsunit/string-external-cached.js b/test/mjsunit/string-external-cached.js new file mode 100644 index 00000000..6e242853 --- /dev/null +++ b/test/mjsunit/string-external-cached.js @@ -0,0 +1,121 @@ +// Copyright 2010 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: --expose-externalize-string --expose-gc +// Test data pointer caching of external strings. + +function test() { + // Test string.charAt. + var charat_str = new Array(5); + charat_str[0] = "0123456789ABCDEF0123456789ABCDEF\ +0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\ +0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\ +0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\ +0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"; + charat_str[1] = "0123456789ABCDEF"; + for (var i = 0; i < 6; i++) charat_str[1] += charat_str[1]; + try { // String can only be externalized once + externalizeString(charat_str[0], false); + externalizeString(charat_str[1], true); + } catch (ex) { } + charat_str[2] = charat_str[0].slice(0, -1); + charat_str[3] = charat_str[1].slice(0, -1); + charat_str[4] = charat_str[0] + charat_str[0]; + + for (var i = 0; i < 5; i++) { + assertEquals('B', charat_str[i].charAt(6*16 + 11)); + assertEquals('C', charat_str[i].charAt(6*16 + 12)); + assertEquals('A', charat_str[i].charAt(3*16 + 10)); + assertEquals('B', charat_str[i].charAt(3*16 + 11)); + } + + charat_short = "012"; + try { // String can only be externalized once + externalizeString(charat_short, true); + } catch (ex) { } + assertEquals("1", charat_short.charAt(1)); + + // Test regexp and short substring. + var re = /(A|B)/; + var rere = /(T.{1,2}B)/; + var ascii = "ABCDEFGHIJKLMNOPQRST"; + var twobyte = "_ABCDEFGHIJKLMNOPQRST"; + try { + externalizeString(ascii, false); + externalizeString(twobyte, true); + } catch (ex) { } + assertTrue(isAsciiString(ascii)); + assertFalse(isAsciiString(twobyte)); + var ascii_slice = ascii.slice(1,-1); + var twobyte_slice = twobyte.slice(2,-1); + var ascii_cons = ascii + ascii; + var twobyte_cons = twobyte + twobyte; + for (var i = 0; i < 2; i++) { + assertEquals(["A", "A"], re.exec(ascii)); + assertEquals(["B", "B"], re.exec(ascii_slice)); + assertEquals(["TAB", "TAB"], rere.exec(ascii_cons)); + assertEquals(["A", "A"], re.exec(twobyte)); + assertEquals(["B", "B"], re.exec(twobyte_slice)); + assertEquals(["T_AB", "T_AB"], rere.exec(twobyte_cons)); + assertEquals("DEFG", ascii_slice.substr(2, 4)); + assertEquals("DEFG", twobyte_slice.substr(2, 4)); + assertEquals("DEFG", ascii_cons.substr(3, 4)); + assertEquals("DEFG", twobyte_cons.substr(4, 4)); + } + + // Test adding external strings + var short_ascii = "E="; + var long_ascii = "MCsquared"; + var short_twobyte = "E\u1234"; + var long_twobyte = "MCsquare\u1234"; + try { // String can only be externalized once + externalizeString(short_ascii, false); + externalizeString(long_ascii, false); + externalizeString(short_twobyte, true); + externalizeString(long_twobyte, true); + assertTrue(isAsciiString(short_asii) && isAsciiString(long_ascii)); + assertFalse(isAsciiString(short_twobyte) || isAsciiString(long_twobyte)); + } catch (ex) { } + assertEquals("E=MCsquared", short_ascii + long_ascii); + assertTrue(isAsciiString(short_ascii + long_ascii)); + assertEquals("MCsquaredE=", long_ascii + short_ascii); + assertEquals("E\u1234MCsquare\u1234", short_twobyte + long_twobyte); + assertFalse(isAsciiString(short_twobyte + long_twobyte)); + assertEquals("E=MCsquared", "E=" + long_ascii); + assertEquals("E\u1234MCsquared", short_twobyte + "MCsquared"); + assertEquals("E\u1234MCsquared", short_twobyte + long_ascii); + assertFalse(isAsciiString(short_twobyte + long_ascii)); +} + +// Run the test many times to ensure IC-s don't break things. +for (var i = 0; i < 10; i++) { + test(); +} + +// Clean up string to make Valgrind happy. +gc(); +gc(); diff --git a/test/mjsunit/string-externalize.js b/test/mjsunit/string-externalize.js index da897869..d52a7e2b 100644 --- a/test/mjsunit/string-externalize.js +++ b/test/mjsunit/string-externalize.js @@ -44,7 +44,7 @@ function test() { assertFalse(isAsciiString(twoByteExternalWithAsciiData)); var realTwoByteExternalString = - "\u1234\u1234" + (function() { return "\u1234"; })(); + "\u1234\u1234\u1234\u1234" + (function() { return "\u1234"; })(); externalizeString(realTwoByteExternalString); assertFalse(isAsciiString(realTwoByteExternalString)); diff --git a/test/mjsunit/string-replace-one-char.js b/test/mjsunit/string-replace-one-char.js new file mode 100644 index 00000000..cb4167ba --- /dev/null +++ b/test/mjsunit/string-replace-one-char.js @@ -0,0 +1,92 @@ +// 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. + +// Make sure the strings are long enough to trigger the one-char string replace. +var prefix1024 = "0123456789ABCDEF"; +for (var i = 0; i < 6; i++) prefix1024 += prefix1024; + +function test_replace(result, expected, search, replace) { + assertEquals(expected, result.replace(search, replace)); +} + +// '$' in the replace string. +test_replace(prefix1024 + "abcdefghijklmnopqrstuvwxyz", + prefix1024 + "abcdefghijk#l#mnopqrstuvwxyz", + "l", "#$&#"); + +test_replace(prefix1024 + "abcdefghijklmnopqrstuvwxyz\u1234", + prefix1024 + "abcdefghijk\u2012l\u2012mnopqrstuvwxyz\u1234", + "l", "\u2012$&\u2012"); + +test_replace(prefix1024 + "abcdefghijklmnopqrstuvwxyz", + prefix1024 + "abcdefghijk$mnopqrstuvwxyz", + "l", "$$"); + +test_replace(prefix1024 + "abcdefghijklmnopqrstuvwxyz\u1234", + prefix1024 + "abcdefghijk$mnopqrstuvwxyz\u1234", + "l", "$$"); + +// Zero length replace string. +test_replace(prefix1024 + "abcdefghijklmnopqrstuvwxyz", + prefix1024 + "abcdefghijklmnopqstuvwxyz", + "r", ""); + +test_replace(prefix1024 + "abcdefghijklmnopq\u1234stuvwxyz", + prefix1024 + "abcdefghijklmnopqstuvwxyz", + "\u1234", ""); + +// Search char not found. +var not_found_1 = prefix1024 + "abcdefghijklmnopqrstuvwxyz"; +test_replace(not_found_1, not_found_1, "+", "-"); + +var not_found_2 = prefix1024 + "abcdefghijklm\u1234nopqrstuvwxyz"; +test_replace(not_found_2, not_found_2, "+", "---"); + +var not_found_3 = prefix1024 + "abcdefghijklmnopqrstuvwxyz"; +test_replace(not_found_3, not_found_3, "\u1234", "ZZZ"); + +// Deep cons tree. +var nested_1 = ""; +for (var i = 0; i < 100000; i++) nested_1 += "y"; +var nested_1_result = prefix1024 + nested_1 + "aa"; +nested_1 = prefix1024 + nested_1 + "z"; +test_replace(nested_1, nested_1_result, "z", "aa"); + +var nested_2 = "\u2244"; +for (var i = 0; i < 100000; i++) nested_2 += "y"; +var nested_2_result = prefix1024 + nested_2 + "aa"; +nested_2 = prefix1024 + nested_2 + "\u2012"; +test_replace(nested_2, nested_2_result, "\u2012", "aa"); + +// Sliced string as input. A cons string is always flattened before sliced. +var slice_1 = ("ab" + prefix1024 + "cdefghijklmnopqrstuvwxyz").slice(1, -1); +var slice_1_result = "b" + prefix1024 + "cdefghijklmnopqrstuvwxQ"; +test_replace(slice_1, slice_1_result, "y", "Q"); + +var slice_2 = (prefix1024 + "abcdefghijklmno\u1234\u1234p").slice(1, -1); +var slice_2_result = prefix1024.substr(1) + "abcdefghijklmnoQ\u1234"; +test_replace(slice_2, slice_2_result, "\u1234", "Q"); diff --git a/test/mjsunit/string-slices-regexp.js b/test/mjsunit/string-slices-regexp.js index a8cadaed..98b8ef9d 100644 --- a/test/mjsunit/string-slices-regexp.js +++ b/test/mjsunit/string-slices-regexp.js @@ -1,4 +1,4 @@ -// Copyright 2009 the V8 project authors. All rights reserved. +// Copyright 2011 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,11 +24,6 @@ // 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: --string-slices - -//assertEquals('345"12345 6"1234567"123', -// '12345""12345 6""1234567""1234'.slice(2,-1).replace(/""/g, '"')); var foo = "lsdfj sldkfj sdklfj læsdfjl sdkfjlsdk fjsdl fjsdljskdj flsj flsdkj flskd regexp: /foobar/\nldkfj sdlkfj sdkl"; for(var i = 0; i < 1000; i++) { diff --git a/test/mjsunit/string-slices.js b/test/mjsunit/string-slices.js index 8cc1f81e..5b1dc360 100755 --- a/test/mjsunit/string-slices.js +++ b/test/mjsunit/string-slices.js @@ -1,4 +1,4 @@ -// Copyright 2008 the V8 project authors. All rights reserved. +// Copyright 2011 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,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: --string-slices --expose-externalize-string +// Flags: --expose-externalize-string --allow-natives-syntax var s = 'abcdefghijklmn'; assertEquals(s, s.substr()); @@ -100,14 +100,7 @@ for (var i = 5; i < 25; i++) { // Keep creating strings to to force allocation failure on substring creation. var x = "0123456789ABCDEF"; -x += x; // 2^5 -x += x; -x += x; -x += x; -x += x; -x += x; // 2^10 -x += x; -x += x; +for (var i = 0; i < 8; i++) x += x; var xl = x.length; var cache = []; for (var i = 0; i < 1000; i++) { @@ -119,14 +112,7 @@ for (var i = 0; i < 1000; i++) { // Same with two-byte strings var x = "\u2028123456789ABCDEF"; -x += x; // 2^5 -x += x; -x += x; -x += x; -x += x; -x += x; // 2^10 -x += x; -x += x; +for (var i = 0; i < 8; i++) x += x; var xl = x.length; var cache = []; for (var i = 0; i < 1000; i++) { @@ -174,6 +160,23 @@ for ( var i = 0; i < 1000; i++) { f(flat, cons, slice, i); } +// Short substrings. +flat = "abcdefghijkl12345"; +cons = flat + flat.toUpperCase(); +/x/.exec(cons); // Flatten cons +slice = "abcdefghijklmn12345".slice(1, -1); +assertEquals("cdefg", flat.substr(2, 5)); +assertEquals("cdefg", cons.substr(2, 5)); +assertEquals("cdefg", slice.substr(1, 5)); + +flat = "abc\u1234defghijkl12345"; +cons = flat + flat.toUpperCase(); +/x/.exec(cons); // Flatten cons +slice = "abc\u1234defghijklmn12345".slice(1, -1); +assertEquals("c\u1234def", flat.substr(2, 5)); +assertEquals("c\u1234def", cons.substr(2, 5)); +assertEquals("c\u1234def", slice.substr(1, 5)); + // Concatenate substrings. var ascii = 'abcdefghijklmnop'; var utf = '\u03B1\u03B2\u03B3\u03B4\u03B5\u03B6\u03B7\u03B8\u03B9\u03BA\u03BB'; @@ -189,11 +192,34 @@ assertEquals("\u03B4\u03B5\u03B6\u03B7\u03B8\u03B9abcdefghijklmnop", assertEquals("\u03B2\u03B3\u03B4\u03B5\u03B4\u03B5\u03B6\u03B7", utf.substring(5,1) + utf.substring(3,7)); -/* // Externalizing strings. -var a = "123456789qwertyuiopasdfghjklzxcvbnm"; -var b = a.slice(1,-1); +var a = "123456789" + "qwertyuiopasdfghjklzxcvbnm"; +var b = "23456789qwertyuiopasdfghjklzxcvbn" assertEquals(a.slice(1,-1), b); -externalizeString(a); + +assertTrue(isAsciiString(a)); +externalizeString(a, true); +assertFalse(isAsciiString(a)); + assertEquals(a.slice(1,-1), b); -*/ +assertTrue(/3456789qwe/.test(a)); +assertEquals(5, a.indexOf("678")); +assertEquals("12345", a.split("6")[0]); + +// Create a slice with an external string as parent string. +var c = a.slice(1,-1); + +function test_crankshaft() { + for (var i = 0; i < 20; i++) { + assertEquals(b.charAt(i), a.charAt(i + 1)); + assertEquals(b.charAt(i), c.charAt(i)); + assertEquals(b.charAt(4), c.charAt(4)); + assertTrue(/3456789qwe/.test(c)); + assertEquals(4, c.indexOf("678")); + assertEquals("2345", c.split("6")[0]); + } +} + +test_crankshaft(); +%OptimizeFunctionOnNextCall(test_crankshaft); +test_crankshaft();
\ No newline at end of file diff --git a/test/mjsunit/switch.js b/test/mjsunit/switch.js index 180f994a..6a61fe59 100644 --- a/test/mjsunit/switch.js +++ b/test/mjsunit/switch.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 f0() { switch (0) { // switch deliberately left empty @@ -126,6 +128,42 @@ assertEquals(3, f4(1), "fallthrough-switch.1"); assertEquals(3, f4(2), "fallthrough-switch.2"); assertEquals(5, f4(3), "fallthrough-switch.3"); +function f4_string(tag, x) { + switch(tag) { + case 'zero': + x++; + case 'two': + x++; + } + return x; +} + +// Symbols +assertEquals(2, f4_string('zero', 0), "fallthrough-string-switch.0"); +assertEquals(1, f4_string('one', 1), "fallthrough-string-switch.1"); +assertEquals(3, f4_string('two', 2), "fallthrough-string-switch.2"); + +// Strings +assertEquals(2, f4_string('_zero'.slice(1), 0), "fallthrough-string-switch.3"); +assertEquals(1, f4_string('_one'.slice(1), 1), "fallthrough-string-switch.4"); +assertEquals(3, f4_string('_two'.slice(1), 2), "fallthrough-string-switch.5"); + +// Oddball +assertEquals(3, f4_string(null, 3), "fallthrough-string-switch.6"); + +// Test for regression +function regress_string(value) { + var json = 1; + switch (typeof value) { + case 'object': + break; + + default: + + } + return json; +}; +assertEquals(1, regress_string('object'), 'regression-string'); function f5(x) { switch(x) { @@ -287,3 +325,138 @@ var verylong_size = 1000; var verylong = makeVeryLong(verylong_size); assertEquals(verylong_size * 2 + 1, verylong()); + +// +// Test suite below aims to cover all possible combinations of following: +// +// clauses | tags | type feedback | optimization +// ========================================================= +// strings | symbol | all | on +// smis | string | target | off +// mixed | oddball | non-target | +// | smis | none | +// | heapnum | | +// ========================================================= + +// Function-with-switch generator +var test_id = 0, + clause_values = { + string: ['abc', 'def', 'ghi', 'jkl'], + smi: [1, 2, 3, 4], + mixed: ['abc', 1, 'def', 2, 'ghi', 3, 'jkl', 4] + }; + +function switch_gen(clause_type, feedback, optimize) { + var values = clause_values[clause_type]; + + function opt(fn) { + if (feedback === 'all') { + values.forEach(fn); + } else if (Array.isArray(feedback)) { + // Non-target + values.filter(function(v) { + return feedback.indexOf(v) === -1; + }).forEach(fn); + } else if (feedback !== undefined) { + // Target + fn(feedback); + } else { + // None + } + + if (optimize) %OptimizeFunctionOnNextCall(fn); + + return fn; + }; + + return opt(new Function( + 'tag', + '"' + (test_id++) + '";' + + 'switch(tag) {' + + values.map(function(value) { + return 'case ' + JSON.stringify(value) + ': return' + + JSON.stringify('ok-' + value); + }).join(';') + + '}' + )); +}; + +function test_switch(clause_type, test_type, feedback, optimize) { + var pairs = [], + fn = switch_gen(clause_type, feedback, optimize); + + if (Array.isArray(test_type)) { + pairs = test_type.map(function(v) { + return { + value: v, + expected: 'ok-' + v + }; + }); + } else if (test_type === 'symbols') { + pairs = clause_values.string.map(function(v) { + return { + value: v, + expected: clause_type !== 'smi' ? 'ok-' + v : undefined + }; + }); + } else if (test_type === 'strings') { + pairs = clause_values.string.map(function(v) { + return { + value: ('%%' + v).slice(2), + expected: clause_type !== 'smi' ? 'ok-' + v : undefined + }; + }); + } else if (test_type === 'oddball') { + pairs = [ + { value: null, expected: undefined }, + { value: NaN, expected: undefined }, + { value: undefined, expected: undefined } + ]; + } else if (test_type === 'smi') { + pairs = clause_values.smi.map(function(v) { + return { + value: v, + expected: clause_type !== 'string' ? 'ok-' + v : undefined + }; + }); + } else if (test_type === 'heapnum') { + pairs = clause_values.smi.map(function(v) { + return { + value: ((v * 17)/16) - ((v*17)%16/16), + expected: clause_type !== 'string' ? 'ok-' + v : undefined + }; + }); + } + + pairs.forEach(function(pair) { + assertEquals(fn(pair.value), pair.expected); + }); +}; + +// test_switch(clause_type, test_type, feedback, optimize); + +function test_switches(opt) { + var test_types = ['symbols', 'strings', 'oddball', 'smi', 'heapnum']; + + function test(clause_type) { + var values = clause_values[clause_type]; + + test_types.forEach(function(test_type) { + test_switch(clause_type, test_type, 'all', opt); + test_switch(clause_type, test_type, 'none', opt); + + // Targeting specific clause feedback + values.forEach(function(value) { + test_switch(clause_type, test_type, [value], value, opt); + test_switch(clause_type, test_type, value, value, opt); + }); + }); + }; + + test('string'); + test('smi'); + test('mixed'); +}; + +test_switches(false); +test_switches(true); diff --git a/test/mjsunit/to_number_order.js b/test/mjsunit/to_number_order.js index d17e6000..50e4bc76 100644 --- a/test/mjsunit/to_number_order.js +++ b/test/mjsunit/to_number_order.js @@ -161,7 +161,7 @@ assertEquals("fiskfisk", x, "Compare objects b >= b valueOf order"); x = ""; assertFalse(a > b, "Compare objects a > b"); -assertEquals("fiskhest", x, "Compare objects a > b valueOf order"); +assertEquals("hestfisk", x, "Compare objects a > b valueOf order"); x = ""; assertFalse(a > void(0), "Compare objects a > undefined"); @@ -195,7 +195,7 @@ function identical_object_comparison() { x = ""; assertFalse(a > b, "Compare objects a > b"); - assertEquals("fiskhest", x, "Compare objects a > b valueOf order"); + assertEquals("hestfisk", x, "Compare objects a > b valueOf order"); x = ""; assertFalse(a > void(0), "Compare objects a > undefined"); diff --git a/test/mjsunit/tools/tickprocessor.js b/test/mjsunit/tools/tickprocessor.js index 30b0ec23..c48d9f3a 100644 --- a/test/mjsunit/tools/tickprocessor.js +++ b/test/mjsunit/tools/tickprocessor.js @@ -376,8 +376,11 @@ function driveTickProcessorTest( } assertTrue(pathLen != -1); var testsPath = TEST_FILE_NAME.substr(0, pathLen + 1); - var tp = new TickProcessor( - new CppEntriesProviderMock(), separateIc, ignoreUnknown, stateFilter); + var tp = new TickProcessor(new CppEntriesProviderMock(), + separateIc, + TickProcessor.CALL_GRAPH_SIZE, + ignoreUnknown, + stateFilter); var pm = new PrintMonitor(testsPath + refOutput); tp.processLogFileInTest(testsPath + logInput); tp.printStatistics(); diff --git a/test/mjsunit/unbox-double-arrays.js b/test/mjsunit/unbox-double-arrays.js index feecaec8..fd7db28a 100644 --- a/test/mjsunit/unbox-double-arrays.js +++ b/test/mjsunit/unbox-double-arrays.js @@ -77,8 +77,6 @@ function testOneArrayType(allocator) { assertEquals(value_6, a[6]); assertEquals(value_6, a[computed_6()]); // Test non-constant key assertEquals(value_7, a[7]); - assertEquals(undefined, a[large_array_size-1]); - assertEquals(undefined, a[-1]); assertEquals(large_array_size, a.length); assertTrue(%HasFastDoubleElements(a)); } @@ -89,8 +87,6 @@ function testOneArrayType(allocator) { assertEquals(value_6, a[6]); assertEquals(value_6, a[computed_6()]); // Test non-constant key assertEquals(value_7, a[7]); - assertEquals(undefined, a[large_array_size-1]); - assertEquals(undefined, a[-1]); assertEquals(large_array_size, a.length); assertTrue(%HasFastDoubleElements(a)); } @@ -101,8 +97,6 @@ function testOneArrayType(allocator) { assertEquals(value_6, a[6]); assertEquals(value_6, a[computed_6()]); // Test non-constant key assertEquals(value_7, a[7]); - assertEquals(undefined, a[large_array_size-1]); - assertEquals(undefined, a[-1]); assertEquals(large_array_size, a.length); assertTrue(%HasFastDoubleElements(a)); } @@ -113,32 +107,40 @@ function testOneArrayType(allocator) { assertEquals(value_6, a[6]); assertEquals(value_6, a[computed_6()]); // Test non-constant key assertEquals(value_7, a[7]); - assertEquals(undefined, a[large_array_size-1]); - assertEquals(undefined, a[-1]); assertEquals(large_array_size, a.length); assertTrue(%HasFastDoubleElements(a)); } function test_various_loads5(a, value_5, value_6, value_7) { assertTrue(%HasFastDoubleElements(a)); + if (value_5 != undefined) { + assertEquals(value_5, a[5]); + }; + if (value_6 != undefined) { + assertEquals(value_6, a[6]); + assertEquals(value_6, a[computed_6()]); // Test non-constant key + } + assertEquals(value_7, a[7]); + assertEquals(large_array_size, a.length); + assertTrue(%HasFastDoubleElements(a)); + } + + function test_various_loads6(a, value_5, value_6, value_7) { + assertTrue(%HasFastDoubleElements(a)); assertEquals(value_5, a[5]); assertEquals(value_6, a[6]); assertEquals(value_6, a[computed_6()]); // Test non-constant key assertEquals(value_7, a[7]); - assertEquals(undefined, a[large_array_size-1]); - assertEquals(undefined, a[-1]); assertEquals(large_array_size, a.length); assertTrue(%HasFastDoubleElements(a)); } - function test_various_loads6(a, value_5, value_6, value_7) { + function test_various_loads7(a, value_5, value_6, value_7) { assertTrue(%HasFastDoubleElements(a)); assertEquals(value_5, a[5]); assertEquals(value_6, a[6]); assertEquals(value_6, a[computed_6()]); // Test non-constant key assertEquals(value_7, a[7]); - assertEquals(undefined, a[large_array_size-1]); - assertEquals(undefined, a[-1]); assertEquals(large_array_size, a.length); assertTrue(%HasFastDoubleElements(a)); } @@ -248,6 +250,8 @@ function testOneArrayType(allocator) { expected_array_value(7)); // Make sure Crankshaft code handles the hole correctly (bailout) + var large_array = new allocator(large_array_size); + force_to_fast_double_array(large_array); test_various_stores(large_array, expected_array_value(5), expected_array_value(6), @@ -273,7 +277,12 @@ function testOneArrayType(allocator) { undefined, expected_array_value(7)); + %DeoptimizeFunction(test_various_loads6); + gc(); + // Test stores for non-NaN. + var large_array = new allocator(large_array_size); + force_to_fast_double_array(large_array); %OptimizeFunctionOnNextCall(test_various_stores); test_various_stores(large_array, expected_array_value(5), @@ -285,7 +294,19 @@ function testOneArrayType(allocator) { expected_array_value(6), expected_array_value(7)); - test_various_loads6(large_array, + test_various_loads7(large_array, + expected_array_value(5), + expected_array_value(6), + expected_array_value(7)); + + test_various_loads7(large_array, + expected_array_value(5), + expected_array_value(6), + expected_array_value(7)); + + %OptimizeFunctionOnNextCall(test_various_loads7); + + test_various_loads7(large_array, expected_array_value(5), expected_array_value(6), expected_array_value(7)); @@ -301,7 +322,7 @@ function testOneArrayType(allocator) { -NaN, expected_array_value(7)); - test_various_loads6(large_array, + test_various_loads7(large_array, NaN, -NaN, expected_array_value(7)); @@ -317,7 +338,7 @@ function testOneArrayType(allocator) { -Infinity, expected_array_value(7)); - test_various_loads6(large_array, + test_various_loads7(large_array, Infinity, -Infinity, expected_array_value(7)); @@ -434,7 +455,6 @@ large_array3[3] = Infinity; large_array3[4] = -Infinity; function call_apply() { - assertTrue(%HasFastDoubleElements(large_array3)); called_by_apply.apply({}, large_array3); } @@ -449,7 +469,6 @@ call_apply(); function test_for_in() { // Due to previous tests, keys 0..25 and 95 should be present. next_expected = 0; - assertTrue(%HasFastDoubleElements(large_array3)); for (x in large_array3) { assertTrue(next_expected++ == x); if (next_expected == 25) { diff --git a/test/mjsunit/undeletable-functions.js b/test/mjsunit/undeletable-functions.js index 04fd0606..635ea6fa 100644 --- a/test/mjsunit/undeletable-functions.js +++ b/test/mjsunit/undeletable-functions.js @@ -25,11 +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. -// Test that we match JSC in making some functions undeletable. -// See http://code.google.com/p/chromium/issues/detail?id=1717 -// The functions on these prototypes are not just undeletable. It is -// possible to override them with new definitions, then get the old -// version back by deleting the new definition. +// Test that we match ECMAScript in making most builtin functions +// deletable and only specific ones undeletable or read-only. var array; @@ -37,7 +34,7 @@ array = [ "toString", "toLocaleString", "join", "pop", "push", "concat", "reverse", "shift", "unshift", "slice", "splice", "sort", "filter", "forEach", "some", "every", "map", "indexOf", "lastIndexOf", "reduce", "reduceRight"]; -CheckJSCSemantics(Array.prototype, array, "Array prototype"); +CheckEcmaSemantics(Array.prototype, array, "Array prototype"); var old_Array_prototype = Array.prototype; var new_Array_prototype = {}; @@ -57,12 +54,12 @@ array = [ "setUTCMinutes", "setHours", "setUTCHours", "setDate", "setUTCDate", "setMonth", "setUTCMonth", "setFullYear", "setUTCFullYear", "toGMTString", "toUTCString", "getYear", "setYear", "toISOString", "toJSON"]; -CheckJSCSemantics(Date.prototype, array, "Date prototype"); +CheckEcmaSemantics(Date.prototype, array, "Date prototype"); array = [ "random", "abs", "acos", "asin", "atan", "ceil", "cos", "exp", "floor", "log", "round", "sin", "sqrt", "tan", "atan2", "pow", "max", "min"]; -CheckJSCSemantics(Math, array, "Math1"); +CheckEcmaSemantics(Math, array, "Math1"); CheckEcmaSemantics(Date, ["UTC", "parse", "now"], "Date"); @@ -76,6 +73,8 @@ array = [ "execScript"]; CheckEcmaSemantics(this, array, "Global"); CheckReadOnlyAttr(this, "Infinity"); +CheckReadOnlyAttr(this, "NaN"); +CheckReadOnlyAttr(this, "undefined"); array = ["exec", "test", "toString", "compile"]; CheckEcmaSemantics(RegExp.prototype, array, "RegExp prototype"); @@ -112,7 +111,7 @@ array = [ "toUpperCase", "toLocaleUpperCase", "link", "anchor", "fontcolor", "fontsize", "big", "blink", "bold", "fixed", "italics", "small", "strike", "sub", "sup", "toJSON", "toString", "valueOf"]; -CheckJSCSemantics(String.prototype, array, "String prototype"); +CheckEcmaSemantics(String.prototype, array, "String prototype"); CheckEcmaSemantics(String, ["fromCharCode"], "String"); @@ -124,14 +123,6 @@ function CheckEcmaSemantics(type, props, name) { } -function CheckJSCSemantics(type, props, name) { - print(name); - for (var i = 0; i < props.length; i++) { - CheckNotDeletable(type, props[i]); - } -} - - function CheckDontDelete(type, props, name) { print(name); for (var i = 0; i < props.length; i++) { @@ -154,21 +145,6 @@ function CheckDeletable(type, prop) { } -function CheckNotDeletable(type, prop) { - var old = type[prop]; - if (!type[prop]) return; - assertTrue(type.hasOwnProperty(prop), "inherited: " + prop); - var deleted = delete type[prop]; - assertTrue(deleted, "delete operator returned false: " + prop); - assertTrue(type.hasOwnProperty(prop), "not there after delete: " + prop); - type[prop] = "foo"; - assertEquals("foo", type[prop], "not overwritable: " + prop); - deleted = delete type[prop]; - assertTrue(deleted, "delete operator returned false 2nd time: " + prop); - assertEquals(old.toString(), type[prop].toString(), "delete didn't restore the old value: " + prop); -} - - function CheckDontDeleteAttr(type, prop) { var old = type[prop]; if (!type[prop]) return; @@ -189,7 +165,7 @@ function CheckReadOnlyAttr(type, prop) { assertFalse(deleted, "delete operator returned true: " + prop); assertTrue(type.hasOwnProperty(prop), "not there after delete: " + prop); type[prop] = "foo"; - assertEquals("foo", type[prop], "overwritable: " + prop); + assertEquals(old, type[prop], "overwritable: " + prop); } print("OK"); diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status index 3a271309..e64959ac 100644 --- a/test/mozilla/mozilla.status +++ b/test/mozilla/mozilla.status @@ -1,4 +1,4 @@ -# Copyright 2009 the V8 project authors. All rights reserved. +# Copyright 2011 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: @@ -69,6 +69,8 @@ js1_5/Array/regress-465980-02: SKIP ecma_3/Date/15.9.3.2-1: SKIP js1_2/function/Number: SKIP +# TODO(2018): Temporarily allow timeout in debug mode. +js1_5/GC/regress-203278-2: PASS || TIMEOUT if $mode == debug ##################### SLOW TESTS ##################### @@ -123,14 +125,14 @@ ecma/Date/15.9.2.2-4: PASS || FAIL ecma/Date/15.9.2.2-5: PASS || FAIL ecma/Date/15.9.2.2-6: PASS || FAIL -# 1026139: These date tests fail on arm -ecma/Date/15.9.5.29-1: PASS || ($ARM && FAIL) -ecma/Date/15.9.5.34-1: PASS || ($ARM && FAIL) -ecma/Date/15.9.5.28-1: PASS || ($ARM && FAIL) +# 1026139: These date tests fail on arm and mips +ecma/Date/15.9.5.29-1: PASS || (($ARM || $MIPS) && FAIL) +ecma/Date/15.9.5.34-1: PASS || (($ARM || $MIPS) && FAIL) +ecma/Date/15.9.5.28-1: PASS || (($ARM || $MIPS) && FAIL) -# 1050186: Arm vm is broken; probably unrelated to dates -ecma/Array/15.4.4.5-3: PASS || ($ARM && FAIL) -ecma/Date/15.9.5.22-2: PASS || ($ARM && FAIL) +# 1050186: Arm/MIPS vm is broken; probably unrelated to dates +ecma/Array/15.4.4.5-3: PASS || (($ARM || $MIPS) && FAIL) +ecma/Date/15.9.5.22-2: PASS || (($ARM || $MIPS) && FAIL) # Flaky test that fails due to what appears to be a bug in the test. # Occurs depending on current time @@ -214,6 +216,10 @@ js1_5/Array/regress-101964: PASS || FAIL if $mode == debug # builtin to have undefined as the receiver. ecma/String/15.5.4.6-2: FAIL_OK +# Fail because it expects String.prototype.split to distinguish whether +# separator was undefined or not passed at all. +ecma/String/15.5.4.8-2: FAIL_OK + # Fail because of toLowerCase and toUpperCase conversion. ecma/String/15.5.4.11-2: FAIL_OK ecma/String/15.5.4.11-5: FAIL_OK @@ -227,7 +233,7 @@ ecma/String/15.5.4.12-4: FAIL_OK ecma/String/15.5.4.12-5: FAIL_OK # Creates a linked list of arrays until we run out of memory or timeout. -js1_5/Regress/regress-312588: FAIL || TIMEOUT +js1_5/Regress/regress-312588: SKIP # Runs out of memory because it compiles huge functions. @@ -301,6 +307,11 @@ js1_2/regexp/RegExp_multiline_as_array: FAIL_OK js1_2/regexp/beginLine: FAIL_OK js1_2/regexp/endLine: FAIL_OK +# We no longer let calls to test and exec with no argument implicitly +# use the previous input. +js1_2/regexp/RegExp_input: FAIL_OK +js1_2/regexp/RegExp_input_as_array: FAIL_OK + # To be compatible with safari typeof a regexp yields 'function'; # in firefox it yields 'object'. @@ -411,12 +422,6 @@ js1_5/extensions/regress-435345-01: FAIL_OK js1_5/extensions/regress-455413: FAIL_OK -# The spec specifies reverse evaluation order for < and >=. -# See section 11.8.2 and 11.8.5. -# We implement the spec here but the test tests the more straigtforward order. -ecma_3/Operators/order-01: FAIL_OK - - # Uses Mozilla-specific QName, XML, XMLList and Iterator. js1_5/Regress/regress-407323: FAIL_OK js1_5/Regress/regress-407957: FAIL_OK @@ -619,6 +624,10 @@ js1_5/Expressions/regress-394673: FAIL # We do not correctly handle assignments within "with" /ecma_3/Statements/12.10-01: FAIL +# We do not throw an exception when a const is redeclared. +# (We only fail section 1 of the test.) +js1_5/Regress/regress-103602: FAIL + ##################### MOZILLA EXTENSION TESTS ##################### ecma/extensions/15.1.2.1-1: FAIL_OK @@ -861,3 +870,59 @@ ecma/Expressions/11.7.3: SKIP ecma/Expressions/11.10-3: SKIP ecma/Expressions/11.7.1: SKIP ecma_3/RegExp/regress-209067: SKIP + +[ $arch == mips ] + +# Times out and print so much output that we need to skip it to not +# hang the builder. +js1_5/extensions/regress-342960: SKIP + +# BUG(3251229): Times out when running new crankshaft test script. +ecma_3/RegExp/regress-311414: SKIP +ecma/Date/15.9.5.8: SKIP +ecma/Date/15.9.5.10-2: SKIP +ecma/Date/15.9.5.11-2: SKIP +ecma/Date/15.9.5.12-2: SKIP +js1_5/Array/regress-99120-02: SKIP +js1_5/extensions/regress-371636: SKIP +js1_5/Regress/regress-203278-1: SKIP +js1_5/Regress/regress-404755: SKIP +js1_5/Regress/regress-451322: SKIP + + +# BUG(1040): Allow this test to timeout. +js1_5/GC/regress-203278-2: PASS || TIMEOUT + + +[ $fast == yes && $arch == mips ] + +# In fast mode on mips we try to skip all tests that would time out, +# since running the tests takes so long in the first place. + +js1_5/Regress/regress-280769-2: SKIP +js1_5/Regress/regress-280769-3: SKIP +js1_5/Regress/regress-244470: SKIP +js1_5/Regress/regress-203278-1: SKIP +js1_5/Regress/regress-290575: SKIP +js1_5/Regress/regress-159334: SKIP +js1_5/Regress/regress-321971: SKIP +js1_5/Regress/regress-347306-01: SKIP +js1_5/Regress/regress-280769-1: SKIP +js1_5/Regress/regress-280769-5: SKIP +js1_5/GC/regress-306788: SKIP +js1_5/GC/regress-278725: SKIP +js1_5/GC/regress-203278-3: SKIP +js1_5/GC/regress-311497: SKIP +js1_5/Array/regress-99120-02: SKIP +ecma/Date/15.9.5.22-1: SKIP +ecma/Date/15.9.5.20: SKIP +ecma/Date/15.9.5.12-2: SKIP +ecma/Date/15.9.5.8: SKIP +ecma/Date/15.9.5.9: SKIP +ecma/Date/15.9.5.11-2: SKIP +ecma/Expressions/11.7.2: SKIP +ecma/Expressions/11.10-2: SKIP +ecma/Expressions/11.7.3: SKIP +ecma/Expressions/11.10-3: SKIP +ecma/Expressions/11.7.1: SKIP +ecma_3/RegExp/regress-209067: SKIP diff --git a/test/preparser/preparser.status b/test/preparser/preparser.status index db177782..6f15fedd 100644 --- a/test/preparser/preparser.status +++ b/test/preparser/preparser.status @@ -31,9 +31,3 @@ prefix preparser # escapes (we need to parse to distinguish octal escapes from valid # back-references). strict-octal-regexp: FAIL - -############################################################################## -[ $arch == mips ] - -# Skip all tests on MIPS. -*: SKIP diff --git a/test/preparser/strict-identifiers.pyt b/test/preparser/strict-identifiers.pyt index 72808e25..aa3d5210 100644 --- a/test/preparser/strict-identifiers.pyt +++ b/test/preparser/strict-identifiers.pyt @@ -138,6 +138,38 @@ setter_arg = StrictTemplate("setter-param-$id", """ var x = {set foo($id) { }}; """) +label_normal = Template("label-normal-$id", """ + $id: ''; +""") + +label_strict = StrictTemplate("label-strict-$id", """ + $id: ''; +""") + +break_normal = Template("break-normal-$id", """ + for (;;) { + break $id; + } +""") + +break_strict = StrictTemplate("break-strict-$id", """ + for (;;) { + break $id; + } +""") + +continue_normal = Template("continue-normal-$id", """ + for (;;) { + continue $id; + } +""") + +continue_strict = StrictTemplate("continue-strict-$id", """ + for (;;) { + continue $id; + } +""") + non_strict_use = Template("nonstrict-$id", """ var $id = 42; $id++; @@ -162,6 +194,7 @@ non_strict_use = Template("nonstrict-$id", """ function $id($id) { } x = {$id: 42}; x = {get $id() {}, set $id(value) {}}; + $id: ''; """) identifier_name_source = """ @@ -197,6 +230,12 @@ for id in ["eval", "arguments"]: prefix_var({"id": id, "op":"--", "opname":"dec"}, "strict_lhs_prefix") postfix_var({"id": id, "op":"++", "opname":"inc"}, "strict_lhs_postfix") postfix_var({"id": id, "op":"--", "opname":"dec"}, "strict_lhs_postfix") + label_normal({"id": id}, None) + label_strict({"id": id}, None) + break_normal({"id": id}, None) + break_strict({"id": id}, None) + continue_normal({"id": id}, None) + continue_strict({"id": id}, None) non_strict_use({"id": id}, None) @@ -205,10 +244,13 @@ for id in ["eval", "arguments"]: for reserved_word in reserved_words + strict_reserved_words: if (reserved_word in strict_reserved_words): message = "strict_reserved_word" + label_message = None elif (reserved_word == "const"): message = "unexpected_token" + label_message = message else: message = "reserved_word" + label_message = message arg_name_own({"id":reserved_word}, message) arg_name_nested({"id":reserved_word}, message) setter_arg({"id": reserved_word}, message) @@ -225,6 +267,19 @@ for reserved_word in reserved_words + strict_reserved_words: read_var({"id": reserved_word}, message) identifier_name({"id": reserved_word}, None); identifier_name_strict({"id": reserved_word}, None); + label_normal({"id": reserved_word}, label_message) + break_normal({"id": reserved_word}, label_message) + continue_normal({"id": reserved_word}, label_message) + if (reserved_word == "const"): + # The error message for this case is different because + # ParseLabelledStatementOrExpression will try to parse this as an expression + # first, effectively disallowing the use in ParseVariableDeclarations, i.e. + # the preparser never sees that 'const' was intended to be a label. + label_strict({"id": reserved_word}, "strict_const") + else: + label_strict({"id": reserved_word}, message) + break_strict({"id": reserved_word}, message) + continue_strict({"id": reserved_word}, message) # Future reserved words in strict mode behave like normal identifiers diff --git a/test/sputnik/sputnik.status b/test/sputnik/sputnik.status index 868509d7..a4c7d57f 100644 --- a/test/sputnik/sputnik.status +++ b/test/sputnik/sputnik.status @@ -30,10 +30,6 @@ def FAIL_OK = FAIL, OKAY ############################### BUGS ################################### -# A bound function should fail on access to 'caller' and 'arguments'. -S15.3.4.5_A1: FAIL -S15.3.4.5_A2: FAIL - # '__proto__' should be treated as a normal property in JSON. S15.12.2_A1: FAIL @@ -46,11 +42,8 @@ S15.8.2.16_A7: PASS || FAIL_OK S15.8.2.18_A7: PASS || FAIL_OK S15.8.2.13_A23: PASS || FAIL_OK -# We allow calls to regexp exec() with no arguments to fail for -# compatibility reasons. -S15.10.6.2_A1_T16: FAIL_OK -S15.10.6.2_A12: FAIL_OK -S15.10.6.3_A1_T16: FAIL_OK +# Sputnik tests (r97) assume RegExp.prototype is an Object, not a RegExp. +S15.10.6_A2: FAIL_OK # We are silent in some regexp cases where the spec wants us to give # errors, for compatibility. @@ -132,6 +125,13 @@ S15.5.2_D2: PASS || FAIL_OK S15.5.4.11_D1.1_T1: PASS || FAIL_OK S15.5.4.11_D1.1_T3: PASS || FAIL_OK S12.6.4_D1: PASS || FAIL_OK +S15.5.4.14_A1_T6: FAIL_OK +S15.5.4.14_A1_T7: FAIL_OK +S15.5.4.14_A1_T8: FAIL_OK +S15.5.4.14_A1_T9: FAIL_OK +S15.5.4.14_A2_T7: FAIL_OK +S15.10.2.12_A1_T1: FAIL_OK +S15.10.2.12_A2_T1: FAIL_OK # We allow function declarations within statements S12.6.2_A13_T1: FAIL_OK @@ -159,6 +159,10 @@ S11.1.5_A4.2: FAIL_OK S9.9_A1: FAIL_OK S9.9_A2: FAIL_OK +# The expected evaluation order of comparison operations changed. +S11.8.2_A2.3_T1: FAIL_OK +S11.8.3_A2.3_T1: FAIL_OK + # Calls builtins without an explicit receiver which means that # undefined is passed to the builtin. The tests expect the global # object to be passed which was true in ES3 but not in ES5. @@ -176,6 +180,22 @@ S15.5.4.13_A1_T3: FAIL_OK S15.5.4.14_A1_T3: FAIL_OK S15.5.4.15_A1_T3: FAIL_OK +# NaN, Infinity and undefined are read-only according to ES5. +S15.1.1.1_A2_T1: FAIL_OK # NaN +S15.1.1.1_A2_T2: FAIL_OK # NaN +S15.1.1.2_A2_T1: FAIL_OK # Infinity +# S15.1.1.2_A2_T2 would fail if it weren't bogus in r97. sputnik bug #45. +S15.1.1.3_A2_T1: FAIL_OK # undefined +S15.1.1.3_A2_T2: FAIL_OK # undefined + +# Function.prototype.apply can handle arbitrary object as argument list. +S15.3.4.3_A6_T1: FAIL_OK +S15.3.4.3_A6_T4: FAIL_OK + +# Array.prototype.to[Locale]String is generic in ES5. +S15.4.4.2_A2_T1: FAIL_OK +S15.4.4.3_A2_T1: FAIL_OK + ##################### SKIPPED TESTS ##################### # These tests take a looong time to run in debug mode. @@ -194,53 +214,6 @@ S15.3_A3_T1: FAIL # Invalid test case (recent change adding var changes semantics) S15.3_A3_T3: FAIL -# These tests fail because we had to add bugs to be compatible with JSC. See -# http://code.google.com/p/chromium/issues/detail?id=1717 -S15.5.4.1_A1_T2: FAIL_OK -S15.5.4_A1: FAIL_OK -S15.5.4_A3: FAIL_OK -S15.9.5.10_A1_T2: FAIL_OK -S15.9.5.11_A1_T2: FAIL_OK -S15.9.5.12_A1_T2: FAIL_OK -S15.9.5.13_A1_T2: FAIL_OK -S15.9.5.14_A1_T2: FAIL_OK -S15.9.5.15_A1_T2: FAIL_OK -S15.9.5.16_A1_T2: FAIL_OK -S15.9.5.17_A1_T2: FAIL_OK -S15.9.5.18_A1_T2: FAIL_OK -S15.9.5.19_A1_T2: FAIL_OK -S15.9.5.20_A1_T2: FAIL_OK -S15.9.5.21_A1_T2: FAIL_OK -S15.9.5.22_A1_T2: FAIL_OK -S15.9.5.23_A1_T2: FAIL_OK -S15.9.5.24_A1_T2: FAIL_OK -S15.9.5.25_A1_T2: FAIL_OK -S15.9.5.26_A1_T2: FAIL_OK -S15.9.5.27_A1_T2: FAIL_OK -S15.9.5.28_A1_T2: FAIL_OK -S15.9.5.29_A1_T2: FAIL_OK -S15.9.5.2_A1_T2: FAIL_OK -S15.9.5.30_A1_T2: FAIL_OK -S15.9.5.31_A1_T2: FAIL_OK -S15.9.5.32_A1_T2: FAIL_OK -S15.9.5.33_A1_T2: FAIL_OK -S15.9.5.34_A1_T2: FAIL_OK -S15.9.5.35_A1_T2: FAIL_OK -S15.9.5.36_A1_T2: FAIL_OK -S15.9.5.37_A1_T2: FAIL_OK -S15.9.5.38_A1_T2: FAIL_OK -S15.9.5.39_A1_T2: FAIL_OK -S15.9.5.3_A1_T2: FAIL_OK -S15.9.5.40_A1_T2: FAIL_OK -S15.9.5.41_A1_T2: FAIL_OK -S15.9.5.42_A1_T2: FAIL_OK -S15.9.5.4_A1_T2: FAIL_OK -S15.9.5.5_A1_T2: FAIL_OK -S15.9.5.6_A1_T2: FAIL_OK -S15.9.5.7_A1_T2: FAIL_OK -S15.9.5.8_A1_T2: FAIL_OK -S15.9.5.9_A1_T2: FAIL_OK - [ $arch == arm ] # BUG(3251225): Tests that timeout with --nocrankshaft. @@ -257,5 +230,14 @@ S15.1.3.2_A2.5_T1: SKIP [ $arch == mips ] -# Skip all tests on MIPS. -*: SKIP +# BUG(3251225): Tests that timeout with --nocrankshaft. +S15.1.3.1_A2.5_T1: SKIP +S15.1.3.2_A2.5_T1: SKIP +S15.1.3.1_A2.4_T1: SKIP +S15.1.3.1_A2.5_T1: SKIP +S15.1.3.2_A2.4_T1: SKIP +S15.1.3.2_A2.5_T1: SKIP +S15.1.3.3_A2.3_T1: SKIP +S15.1.3.4_A2.3_T1: SKIP +S15.1.3.1_A2.5_T1: SKIP +S15.1.3.2_A2.5_T1: SKIP diff --git a/test/test262/README b/test/test262/README index ea6b4a71..dae18433 100644 --- a/test/test262/README +++ b/test/test262/README @@ -4,11 +4,11 @@ tests from http://hg.ecmascript.org/tests/test262 -at revision 128 as 'data' in this directory. Using later version +at revision 309 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. -hg clone -r 128 http://hg.ecmascript.org/tests/test262 data +hg clone -r 309 http://hg.ecmascript.org/tests/test262 data 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/test/test262/test262.status b/test/test262/test262.status index 8cee2107..67607fff 100644 --- a/test/test262/test262.status +++ b/test/test262/test262.status @@ -25,1330 +25,94 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +prefix test262 +def FAIL_OK = FAIL, OKAY -# -# ietestcenter tests. -# - -prefix ietestcenter +############################### BUGS ################################### +# '__proto__' should be treated as a normal property in JSON. +S15.12.2_A1: FAIL -# -# Deliberate differences for compatibility with other browsers -# -# 15.9.5.43-0-9 and 15.9.5.43-0-10. V8 doesn't throw RangeError -# from Date.prototype.toISOString when string is not a finite number. -# This is compatible with Firefox and Safari. -15.9.5.43-0-9: PASS || FAIL -15.9.5.43-0-10: PASS || FAIL - -# -# Unanalyzed failures which may be bugs or deliberate differences -# - -# Bug? Strict Mode - TypeError is thrown when changing the value of a Value -# Property of the Global Object under strict mode (NaN) -10.2.1.1.3-4-16-s: FAIL -# Bug? Strict Mode - TypeError is thrown when changing the value of a Value -# Property of the Global Object under strict mode (undefined) -10.2.1.1.3-4-18-s: FAIL -# Invalid test: https://bugs.ecmascript.org/show_bug.cgi?id=76 -10.4.2-2-c-1: FAIL -# BUG: 11.8.2 Greater-than Operator - Partial left to right order enforced -# when using Greater-than operator: valueOf > valueOf -11.8.2-1: FAIL -# BUG: 11.8.2 Greater-than Operator - Partial left to right order enforced -# when using Greater-than operator: valueOf > toString -11.8.2-2: FAIL -# BUG: 11.8.2 Greater-than Operator - Partial left to right order enforced -# when using Greater-than operator: toString > valueOf -11.8.2-3: FAIL -# BUG: 11.8.2 Greater-than Operator - Partial left to right order enforced -# when using Greater-than operator: toString > toString -11.8.2-4: FAIL -# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order -# enforced when using Less-than-or-equal operator: valueOf <= valueOf -11.8.3-1: FAIL -# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order -# enforced when using Less-than-or-equal operator: valueOf <= toString -11.8.3-2: FAIL -# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order -# enforced when using Less-than-or-equal operator: toString <= valueOf -11.8.3-3: FAIL -# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order -# enforced when using Less-than-or-equal operator: toString <= toString -11.8.3-4: FAIL -# BUG: 11.8.3 Less-than-or-equal Operator - Partial left to right order -# enforced when using Less-than-or-equal operator: valueOf <= valueOf -11.8.3-5: FAIL -# Bug? simple assignment throws TypeError if LeftHandSide is a readonly property -# in strict mode (Global.undefined) -11.13.1-4-27-s: FAIL -# Bug? simple assignment throws TypeError if LeftHandSide is a readonly property -# in strict mode (Global.Infinity) -11.13.1-4-3-s: FAIL -# BUG: Global.NaN is a data property with default attribute values -15.1.1.1-0: FAIL -# BUG: Global.Infinity is a data property with default attribute values -15.1.1.2-0: FAIL -# BUG: Global.undefined is a data property with default attribute values -15.1.1.3-0: FAIL -# BUG: Object.getOwnPropertyDescriptor returns data desc (all false) -# for properties on built-ins (Global.NaN) -15.2.3.3-4-178: FAIL -# BUG: Object.getOwnPropertyDescriptor returns data desc (all false) -# for properties on built-ins (Global.Infinity) -15.2.3.3-4-179: FAIL -# BUG: Object.getOwnPropertyDescriptor returns data desc (all false) -# for properties on built-ins (Global.undefined) -15.2.3.3-4-180: FAIL -# BUG: Object.getOwnPropertyDescriptor returns data desc (all false) -# for properties on built-ins (RegExp.prototype.source) -# There is no RegExp.prototype.source -15.2.3.3-4-212: FAIL -# BUG: Object.getOwnPropertyDescriptor returns data desc (all false) -# for properties on built-ins (RegExp.prototype.global) -# There is no RegExp.prototype.global -15.2.3.3-4-213: FAIL -# BUG: Object.getOwnPropertyDescriptor returns data desc (all false) -# for properties on built-ins (RegExp.prototype.ignoreCase) -# There is no RegExp.prototype.ignoreCase -15.2.3.3-4-214: FAIL -# BUG: Object.getOwnPropertyDescriptor returns data desc (all false) -# for properties on built-ins (RegExp.prototype.multiline) -15.2.3.3-4-215: FAIL -# Bug? Object.defineProperty - Update [[Enumerable]] attribute of 'name' -# property to true successfully when [[Enumerable]] attribute of 'name' -# is false and [[Configurable]] attribute of 'name' is true, the 'desc' -# is a generic descriptor which only contains [[Enumerable]] attribute -# as true, 'name' property is an index data property (8.12.9 step 8) -15.2.3.6-4-82-18: FAIL -# Bug? Object.defineProperty - Update [[Enumerable]] attribute of 'name' -# property to false successfully when [[Enumerable]] and [[Configurable]] -# attributes of 'name' property are true, the 'desc' is a generic -# descriptor which only contains [Enumerable]] attribute as false and -# 'name' property is an index accessor property (8.12.9 step 8) -15.2.3.6-4-82-19: FAIL -# Bug? Object.defineProperty - Update [[Enumerable]] attribute of 'name' -# property to false successfully when [[Enumerable]] and [[Configurable]] -# attributes of 'name' property are true, the 'desc' is a generic -# descriptor which contains [Enumerable]] attribute as false and -# [[Configurable]] property is true, 'name' property is an index accessor -# property (8.12.9 step 8) -15.2.3.6-4-82-20: FAIL -# Bug? Object.defineProperty - Update [[Configurable]] attribute of 'name' -# property to false successfully when [[Enumerable]] and [[Configurable]] -# attributes of 'name' property are true, the 'desc' is a generic -# descriptor which only contains [[Configurable]] attribute as false, -# 'name' property is an index accessor property (8.12.9 step 8) -15.2.3.6-4-82-21: FAIL -# Bug? Object.defineProperty - Update [[Configurable]] attribute of 'name' -# property to false successfully when [[Enumerable]] and [[Configurable]] -# attributes of 'name' property are true, the 'desc' is a generic -# descriptor which contains [[Enumerable]] attribute as true and -# [[Configurable]] attribute is false, 'name' property is an index accessor -# property (8.12.9 step 8) -15.2.3.6-4-82-22: FAIL -# Bug? Object.defineProperty - Update [[Enumerable]] and [[Configurable]] -# attributes of 'name' property to false successfully when [[Enumerable]] -# and [[Configurable]] attributes of 'name' property are true, the 'desc' -# is a generic descriptor which contains [[Enumerable]] and -# [[Configurable]] attributes as false, 'name' property is an index -# accessor property (8.12.9 step 8) -15.2.3.6-4-82-23: FAIL -# Bug? Object.defineProperty - Update [[Enumerable]] attributes of 'name' -# property to true successfully when [[Enumerable]] attribute of 'name' is -# false and [[Configurable]] attribute of 'name' is true, the 'desc' is a -# generic descriptor which only contains [[Enumerable]] attribute as true, -# 'name' property is an index accessor property (8.12.9 step 8) -15.2.3.6-4-82-24: FAIL -# Bug? Object.defineProperty - 'O' is an Array, test the length property of 'O' -# is own data property (15.4.5.1 step 1) -15.2.3.6-4-116: FAIL -# Bug? Object.defineProperty - 'O' is an Array, test the length property of 'O' -# is own data property that overrides an inherited data property (15.4.5.1 -# step 1) -15.2.3.6-4-117: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test that RangeError exception is thrown when [[Value]] field of -# 'desc' is undefined (15.4.5.1 step 3.c) -15.2.3.6-4-125: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is null (15.4.5.1 step 3.c) -15.2.3.6-4-126: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is a boolean with value false -# (15.4.5.1 step 3.c) -15.2.3.6-4-127: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is a boolean with value true -# (15.4.5.1 step 3.c) -15.2.3.6-4-128: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is not thrown when the [[Value]] field of -# 'desc' is 0 (15.4.5.1 step 3.c) -15.2.3.6-4-129: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is not thrown when the [[Value]] field of -# 'desc' is +0 (15.4.5.1 step 3.c) -15.2.3.6-4-130: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is not thrown when the [[Value]] field of -# 'desc' is -0 (15.4.5.1 step 3.c) -15.2.3.6-4-131: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is not thrown when the [[Value]] field of -# 'desc' is a positive number (15.4.5.1 step 3.c) -15.2.3.6-4-132: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is a negative number (15.4.5.1 step 3.c) -15.2.3.6-4-133: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is +Infinity (15.4.5.1 step 3.c) -15.2.3.6-4-134: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is -Infinity (15.4.5.1 step 3.c) -15.2.3.6-4-135: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is NaN (15.4.5.1 step 3.c) -15.2.3.6-4-136: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is not thrown when the [[Value]] field of -# 'desc' is a string containing a positive number (15.4.5.1 step 3.c) -15.2.3.6-4-137: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is a string containing a negative number (15.4.5.1 step 3.c) -15.2.3.6-4-138: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is a string containing a decimal number (15.4.5.1 step 3.c) -15.2.3.6-4-139: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is a string containing +Infinity (15.4.5.1 step 3.c) -15.2.3.6-4-140: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is a string containing -Infinity (15.4.5.1 step 3.c) -15.2.3.6-4-141: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is a string containing an -# exponential number (15.4.5.1 step 3.c) -15.2.3.6-4-142: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is a string containing a hex -# number (15.4.5.1 step 3.c) -15.2.3.6-4-143: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is a string containing a number -# with leading zeros (15.4.5.1 step 3.c) -15.2.3.6-4-144: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError exception is thrown when the [[Value]] field of -# 'desc' is a string which doesn't convert to a number (15.4.5.1 step 3.c) -15.2.3.6-4-145: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is an object which has an own -# toString method (15.4.5.1 step 3.c) -15.2.3.6-4-146: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is an Object which has an own -# valueOf method (15.4.5.1 step 3.c) -15.2.3.6-4-147: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is an Object which has an own -# valueOf method that returns an object and toString method that returns a -# string (15.4.5.1 step 3.c) -15.2.3.6-4-148: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is an Object which has an own -# toString and valueOf method (15.4.5.1 step 3.c) -15.2.3.6-4-149: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test TypeError is thrown when the [[Value]] field of 'desc' is an -# Object that both toString and valueOf wouldn't return primitive value -# (15.4.5.1 step 3.c) -15.2.3.6-4-150: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', and the [[Value]] field of 'desc' is an Object with an own toString -# method and an inherited valueOf method (15.4.5.1 step 3.c), test that the -# inherited valueOf method is used -15.2.3.6-4-151: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError is thrown when the [[Value]] field of 'desc' is a -# positive non-integer values (15.4.5.1 step 3.c) -15.2.3.6-4-152: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length prosperty -# of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is a -# negative non-integer values (15.4.5.1 step 3.c) -15.2.3.6-4-153: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is boundary value 2^32 - 2 -# (15.4.5.1 step 3.c) -15.2.3.6-4-154: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test the [[Value]] field of 'desc' is boundary value 2^32 - 1 -# (15.4.5.1 step 3.c) -15.2.3.6-4-155: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError is thrown when the [[Value]] field of 'desc' is -# boundary value 2^32 (15.4.5.1 step 3.c) -15.2.3.6-4-156: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', test RangeError is thrown when the [[Value]] field of 'desc' is -# boundary value 2^32 + 1 (15.4.5.1 step 3.c) -15.2.3.6-4-157: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', set the [[Value]] field of 'desc' to a value greater than the -# existing value of length (15.4.5.1 step 3.f) -15.2.3.6-4-159: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', set the [[Value]] field of 'desc' to a value lesser than the -# existing value of length and test that indexes beyond the new length are -# deleted(15.4.5.1 step 3.f) -15.2.3.6-4-161: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to true after deleting properties with large index named if the -# [[Writable]] field of 'desc' is absent (15.4.5.1 step 3.h) -15.2.3.6-4-165: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to true after deleting properties with large index named if the -# [[Writable]] field of 'desc' is true (15.4.5.1 step 3.h) -15.2.3.6-4-166: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to false after deleting properties with large index named if the -# [[Writable]] field of 'desc' is false (15.4.5.1 step 3.i.ii) -15.2.3.6-4-167: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', whose writable attribute is being changed to false and the [[Value]] -# field of 'desc' is less than value of the length property and also lesser -# than an index of the array which is set to configurable:false, test that -# new length is set to a value greater than the non-deletable index by 1, -# writable attribute of length is set to false and TypeError exception is -# thrown (15.4.5.1 step 3.i.iii) -15.2.3.6-4-168: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property and also lesser than an index of the array which is set to -# configurable: false, test that new length is set to a value greater than -# the non-deletable index by 1, and TypeError is thrown (15.4.5.1 step -# 3.l.i) -15.2.3.6-4-169: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property and also lesser than an index of the array which is set to -# configurable: false, test that new length is set to a value greater than -# the non-deletable index by 1, writable attribute of length is set to -# false and TypeError exception is thrown (15.4.5.1 step 3.l.ii) -15.2.3.6-4-170: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of an inherited data -# property with large index named in 'O' can't stop deleting index named -# properties (15.4.5.1 step 3.l.ii) -15.2.3.6-4-171: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own data property with -# large index named in 'O' that overrides an inherited data property can -# stop deleting index named properties (15.4.5.1 step 3.l.ii) -15.2.3.6-4-172: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own data property with -# large index named in 'O' that overrides an inherited accessor property -# can stop deleting index named properties (15.4.5.1 step 3.l.ii) -15.2.3.6-4-173: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own accessor property -# with large index named in 'O' can stop deleting index named properties -# (15.4.5.1 step 3.l.ii) -15.2.3.6-4-174: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of an inherited accessor -# property with large index named in 'O' can't stop deleting index named -# properties (15.4.5.1 step 3.l.ii) -15.2.3.6-4-175: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own accessor property -# with large index named in 'O' that overrides an inherited data property -# can stop deleting index named properties (15.4.5.1 step 3.l.ii) -15.2.3.6-4-176: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own accessor property -# with large index named in 'O' that overrides an inherited accessor -# property can stop deleting index named properties (15.4.5.1 step 3.l.ii) -15.2.3.6-4-177: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the configurable large index named property of 'O' is -# deleted (15.4.5.1 step 3.l.ii) -15.2.3.6-4-178: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is greater than value of the length -# property, test value of the length property is same as [[Value]] -# (15.4.5.1 step 3.l.iii.1) -15.2.3.6-4-179-1: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to false at last when the [[Writable]] field of 'desc' is false and 'O' -# doesn't contain non-configurable large index named property (15.4.5.1 -# step 3.m) -15.2.3.6-4-181: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, 'name' is boundary value 2^32 - 2 (15.4.5.1 step 4.a) -15.2.3.6-4-183: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, test TypeError is thrown if the [[Writable]] attribute of the -# length property in 'O' is false and value of 'name' equals to value of -# the length property (15.4.5.1 step 4.b) -15.2.3.6-4-188: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, test TypeError is thrown if the [[Writable]] attribute of the -# length property in 'O' is false and value of 'name' is greater than value -# of the length property (15.4.5.1 step 4.b) -15.2.3.6-4-189: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, 'desc' is accessor descriptor, test updating all attribute -# values of 'name' (15.4.5.1 step 4.c) -15.2.3.6-4-209: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, name is accessor property and 'desc' is accessor descriptor, -# test updating the [[Enumerable]] attribute value of 'name' (15.4.5.1 step -# 4.c) -15.2.3.6-4-271: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, name is accessor property and 'desc' is accessor descriptor, -# test updating the [[Configurable]] attribute value of 'name' (15.4.5.1 -# step 4.c) -15.2.3.6-4-272: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, name is accessor property and 'desc' is accessor descriptor, -# test updating multiple attribute values of 'name' (15.4.5.1 step 4.c) -15.2.3.6-4-273: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, test the length property of 'O' is set as ToUint32('name') + 1 -# if ToUint32('name') equals to value of the length property in 'O' -# (15.4.5.1 step 4.e.ii) -15.2.3.6-4-275: FAIL -# Bug? Object.defineProperty - 'O' is an Array, 'name' is an array index named -# property, test the length property of 'O' is set as ToUint32('name') + 1 -# if ToUint32('name') is greater than value of the length property in 'O' -# (15.4.5.1 step 4.e.ii) -15.2.3.6-4-276: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has -# formal parameters, 'name' is own accessor property of 'O' which is also -# defined in [[ParameterMap]] of 'O', and 'desc' is accessor descriptor, -# test updating multiple attribute values of 'name' (10.6 -# [[DefineOwnProperty]] step 3 and 5.a.i) -15.2.3.6-4-291-1: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object, 'name' is own -# accessor property of 'O', and 'desc' is accessor descriptor, test -# updating multiple attribute values of 'name' (10.6 [[DefineOwnProperty]] -# step 3) -15.2.3.6-4-291: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has -# formal parameters, 'name' is own property of 'O' which is also defined in -# [[ParameterMap]] of 'O', and 'desc' is data descriptor, test updating -# multiple attribute values of 'name' (10.6 [[DefineOwnProperty]] step 3 -# and 5.b) -15.2.3.6-4-292-1: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has -# formal parameters, 'name' is own data property of 'O' which is also -# defined in [[ParameterMap]] of 'O', test TypeError is thrown when -# updating the [[Value]] attribute value of 'name' which is defined as -# unwritable and non-configurable (10.6 [[DefineOwnProperty]] step 4 and -# step 5b) -15.2.3.6-4-293-2: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has -# formal parameters, 'name' is own data property of 'O' which is also -# defined in [[ParameterMap]] of 'O', test TypeError is not thrown when -# updating the [[Value]] attribute value of 'name' which is defined as -# non-writable and configurable (10.6 [[DefineOwnProperty]] step 3 and step -# 5.b) -15.2.3.6-4-293-3: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has -# formal parameters, 'name' is own data property of 'O' which is also -# defined in [[ParameterMap]] of 'O', test TypeError is thrown when -# updating the [[Writable]] attribute value of 'name' which is defined as -# non-configurable (10.6 [[DefineOwnProperty]] step 4 and 5b) -15.2.3.6-4-294-1: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has -# formal parameters, 'name' is own data property of 'O' which is also -# defined in [[ParameterMap]] of 'O', test TypeError is thrown when -# updating the [[Enumerable]] attribute value of 'name' which is defined as -# non-configurable (10.6 [[DefineOwnProperty]] step 4 and step 5b) -15.2.3.6-4-295-1: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object of a function that has -# formal parameters, 'name' is own data property of 'O' which is also -# defined in [[ParameterMap]] of 'O', test TypeError is thrown when -# updating the [[Configurable]] attribute value of 'name' which is defined -# as non-configurable (10.6 [[DefineOwnProperty]] step 4 and step 5b) -15.2.3.6-4-296-1: FAIL -# Bug? Object.defineProperty - 'O' is an Arguments object, 'name' is an index -# named accessor property of 'O' but not defined in [[ParameterMap]] of -# 'O', and 'desc' is accessor descriptor, test updating multiple attribute -# values of 'name' (10.6 [[DefineOwnProperty]] step 3) -15.2.3.6-4-303: FAIL -# Bug? ES5 Attributes - indexed property 'P' with attributes [[Writable]]: true, -# [[Enumerable]]: true, [[Configurable]]: false is writable using simple -# assignment, 'O' is an Arguments object -15.2.3.6-4-333-11: FAIL -# Bug? ES5 Attributes - Updating indexed data property 'P' whose attributes are -# [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: true to an -# accessor property, 'A' is an Array object (8.12.9 - step 9.b.i) -15.2.3.6-4-360-1: FAIL -# Bug? ES5 Attributes - Updating indexed data property 'P' whose attributes are -# [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: true to an -# accessor property, 'O' is an Arguments object (8.12.9 - step 9.b.i) -15.2.3.6-4-360-6: FAIL -# Bug? ES5 Attributes - Updating indexed data property 'P' whose attributes are -# [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: true to an -# accessor property, 'O' is the global object (8.12.9 - step 9.b.i) -15.2.3.6-4-360-7: FAIL -# Bug? ES5 Attributes - [[Value]] attribute of data property is the activex host -# object -15.2.3.6-4-401: FAIL -# Bug? ES5 Attributes - Failed to add a property to an object when the object's -# object has a property with same name and [[Writable]] attribute is set to -# false (Number instance) +# V8 Bug: http://code.google.com/p/v8/issues/detail?id=1475 15.2.3.6-4-405: FAIL -# Bug? ES5 Attributes - Failed to add a property to an object when the object's -# prototype has a property with the same name and [[Writable]] set to false -# (JSON) 15.2.3.6-4-410: FAIL -# Bug? ES5 Attributes - Failed to add properties to an object when the object's -# prototype has properties with the same name and [[Writable]] set to false -# (Object.create) 15.2.3.6-4-415: FAIL -# Bug? ES5 Attributes - Failed to add a property to an object when the object's -# prototype has a property with the same name and [[Writable]] set to -# false(Function.prototype.bind) 15.2.3.6-4-420: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.indexOf are correct -15.2.3.6-4-612: FAIL -# Bug? ES5 Attributes - all attributes in Object.lastIndexOf are correct -15.2.3.6-4-613: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.every are correct -15.2.3.6-4-614: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.some are correct -15.2.3.6-4-615: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.forEach are correct -15.2.3.6-4-616: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.map are correct -15.2.3.6-4-617: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.filter are correct -15.2.3.6-4-618: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.reduce are correct -15.2.3.6-4-619: FAIL -# Bug? ES5 Attributes - all attributes in Array.prototype.reduceRight are -# correct -15.2.3.6-4-620: FAIL -# Bug? ES5 Attributes - all attributes in String.prototype.trim are correct -15.2.3.6-4-621: FAIL -# Bug? ES5 Attributes - all attributes in Date.prototype.toISOString are correct -15.2.3.6-4-623: FAIL -# Bug? ES5 Attributes - all attributes in Date.prototype.toJSON are correct -15.2.3.6-4-624: FAIL -# Bug? Object.defineProperties - 'O' is an Array, test the length property of -# 'O' is own data property (15.4.5.1 step 1) -15.2.3.7-6-a-112: FAIL -# Bug? Object.defineProperties - 'O' is an Array, test the length property of -# 'O' is own data property that overrides an inherited data property -# (15.4.5.1 step 1) -15.2.3.7-6-a-113: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', test RangeError is thrown when setting the [[Value]] field of 'desc' -# to undefined (15.4.5.1 step 3.c) -15.2.3.7-6-a-121: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', test setting the [[Value]] field of 'desc' to null actuall is set to -# 0 (15.4.5.1 step 3.c) -15.2.3.7-6-a-122: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a boolean with value false -# (15.4.5.1 step 3.c) -15.2.3.7-6-a-123: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a boolean with value true -# (15.4.5.1 step 3.c) -15.2.3.7-6-a-124: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is 0 (15.4.5.1 step 3.c) -15.2.3.7-6-a-125: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is +0 (15.4.5.1 step 3.c) -15.2.3.7-6-a-126: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is -0 (15.4.5.1 step 3.c) -15.2.3.7-6-a-127: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is positive number (15.4.5.1 -# step 3.c) -15.2.3.7-6-a-128: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is negative number (15.4.5.1 -# step 3.c) -15.2.3.7-6-a-129: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is +Infinity (15.4.5.1 step -# 3.c) -15.2.3.7-6-a-130: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is -Infinity (15.4.5.1 step -# 3.c) -15.2.3.7-6-a-131: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is NaN (15.4.5.1 step 3.c) -15.2.3.7-6-a-132: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing a -# positive number (15.4.5.1 step 3.c) -15.2.3.7-6-a-133: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing a -# negative number (15.4.5.1 step 3.c) -15.2.3.7-6-a-134: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing a -# decimal number (15.4.5.1 step 3.c) -15.2.3.7-6-a-135: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing -# +Infinity (15.4.5.1 step 3.c) -15.2.3.7-6-a-136: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing -# -Infinity (15.4.5.1 step 3.c) -15.2.3.7-6-a-137: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing an -# exponential number (15.4.5.1 step 3.c) -15.2.3.7-6-a-138: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing an hex -# number (15.4.5.1 step 3.c) -15.2.3.7-6-a-139: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is a string containing an -# leading zero number (15.4.5.1 step 3.c) -15.2.3.7-6-a-140: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', test the [[Value]] field of 'desc' is a string which doesn't convert -# to a number (15.4.5.1 step 3.c) -15.2.3.7-6-a-141: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', test the [[Value]] field of 'desc' is an Object which has an own -# toString method (15.4.5.1 step 3.c) -15.2.3.7-6-a-142: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is an Object which has an own -# valueOf method (15.4.5.1 step 3.c) -15.2.3.7-6-a-143: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is an Object which has an own -# valueOf method that returns an object and toString method that returns a -# string (15.4.5.1 step 3.c) -15.2.3.7-6-a-144: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is an Object which has an own -# toString and valueOf method (15.4.5.1 step 3.c) -15.2.3.7-6-a-145: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test TypeError is thrown when the [[Value]] field of 'desc' is an -# Object that both toString and valueOf wouldn't return primitive value -# (15.4.5.1 step 3.c) -15.2.3.7-6-a-146: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test using inherited valueOf method when the [[Value]] field of -# 'desc' is an Objec with an own toString and inherited valueOf methods -# (15.4.5.1 step 3.c) -15.2.3.7-6-a-147: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is -# positive non-integer values (15.4.5.1 step 3.c) -15.2.3.7-6-a-148: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is -# negative non-integer values (15.4.5.1 step 3.c) -15.2.3.7-6-a-149: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is boundary value 2^32 - 2 -# (15.4.5.1 step 3.c) -15.2.3.7-6-a-150: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test the [[Value]] field of 'desc' is boundary value 2^32 - 1 -# (15.4.5.1 step 3.c) -15.2.3.7-6-a-151: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is -# boundary value 2^32 (15.4.5.1 step 3.c) -15.2.3.7-6-a-152: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'name' is the length property -# of 'O', test RangeError is thrown when the [[Value]] field of 'desc' is -# boundary value 2^32 + 1 (15.4.5.1 step 3.c) -15.2.3.7-6-a-153: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', test the [[Value]] field of 'desc' which is greater than value of -# the length property is defined into 'O' without deleting any property -# with large index named (15.4.5.1 step 3.f) -15.2.3.7-6-a-155: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', test the [[Value]] field of 'desc' which is less than value of the -# length property is defined into 'O' with deleting properties with large -# index named (15.4.5.1 step 3.f) -15.2.3.7-6-a-157: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to true at last after deleting properties with large index named if the -# [[Writable]] field of 'desc' is absent (15.4.5.1 step 3.h) -15.2.3.7-6-a-161: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to true at last after deleting properties with large index named if the -# [[Writable]] field of 'desc' is true (15.4.5.1 step 3.h) -15.2.3.7-6-a-162: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to false at last after deleting properties with large index named if the -# [[Writable]] field of 'desc' is false (15.4.5.1 step 3.i.ii) -15.2.3.7-6-a-163: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property in 'O' -# is set as true before deleting properties with large index named -# (15.4.5.1 step 3.i.iii) -15.2.3.7-6-a-164: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the length property is decreased by 1 (15.4.5.1 step -# 3.l.i) -15.2.3.7-6-a-165: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own data property with -# large index named in 'O' can stop deleting index named properties -# (15.4.5.1 step 3.l.ii) -15.2.3.7-6-a-166: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of inherited data property -# with large index named in 'O' can't stop deleting index named properties -# (15.4.5.1 step 3.l.ii) -15.2.3.7-6-a-167: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own data property with -# large index named in 'O' that overrides inherited data property can stop -# deleting index named properties (15.4.5.1 step 3.l.ii) -15.2.3.7-6-a-168: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own data property with -# large index named in 'O' that overrides inherited accessor property can -# stop deleting index named properties (15.4.5.1 step 3.l.ii) -15.2.3.7-6-a-169: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own accessor property -# with large index named in 'O' can stop deleting index named properties -# (15.4.5.1 step 3.l.ii) -15.2.3.7-6-a-170: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of inherited accessor -# property with large index named in 'O' can't stop deleting index named -# properties (15.4.5.1 step 3.l.ii) -15.2.3.7-6-a-171: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own accessor property -# with large index named in 'O' that overrides inherited data property can -# stop deleting index named properties (15.4.5.1 step 3.l.ii) -15.2.3.7-6-a-172: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Configurable]] attribute of own accessor property -# with large index named in 'O' that overrides inherited accessor property -# can stop deleting index named properties (15.4.5.1 step 3.l.ii) -15.2.3.7-6-a-173: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the configurable large index named property of 'O' can be -# deleted (15.4.5.1 step 3.l.ii) -15.2.3.7-6-a-174: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test value of the length property is set to the last -# non-configurable index named property of 'O' plus 1 (15.4.5.1 step -# 3.l.iii.1) -15.2.3.7-6-a-175: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to false at last when the [[Writable]] field of 'desc' is false and 'O' -# contains non-configurable large index named property (15.4.5.1 step -# 3.l.iii.2) -15.2.3.7-6-a-176: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is the length property of -# 'O', the [[Value]] field of 'desc' is less than value of the length -# property, test the [[Writable]] attribute of the length property is set -# to false at last when the [[Writable]] field of 'desc' is false and 'O' -# doesn't contain non-configurable large index named property (15.4.5.1 -# step 3.m) -15.2.3.7-6-a-177: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named -# property, 'P' is boundary value 2^32 - 2 (15.4.5.1 step 4.a) -15.2.3.7-6-a-179: FAIL -# Bug? Object.defineProperties - TypeError is thrown if 'O' is an Array, 'P' is -# an array index named property,[[Writable]] attribute of the length -# property in 'O' is false, value of 'P' is equal to value of the length -# property in 'O' (15.4.5.1 step 4.b) -15.2.3.7-6-a-184: FAIL -# Bug? Object.defineProperties - TypeError is thrown if 'O' is an Array, 'P' is -# an array index named property,[[Writable]] attribute of the length -# property in 'O' is false, value of 'P' is bigger than value of the length -# property in 'O' (15.4.5.1 step 4.b) -15.2.3.7-6-a-185: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named -# property, 'desc' is accessor descriptor, test updating all attribute -# values of 'P' (15.4.5.1 step 4.c) -15.2.3.7-6-a-205: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named -# property that already exists on 'O' is accessor property and 'desc' is -# accessor descriptor, test updating the [[Enumerable]] attribute value of -# 'P' (15.4.5.1 step 4.c) -15.2.3.7-6-a-260: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named -# property that already exists on 'O' is accessor property and 'desc' is -# accessor descriptor, test updating the [[Configurable]] attribute value -# of 'P' (15.4.5.1 step 4.c) -15.2.3.7-6-a-261: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named -# property that already exists on 'O' is accessor property and 'desc' is -# accessor descriptor, test updating multiple attribute values of 'P' -# (15.4.5.1 step 4.c) -15.2.3.7-6-a-262: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named -# property, test the length property of 'O' is set as ToUint32('P') + 1 if -# ToUint32('P') equals to value of the length property in 'O' (15.4.5.1 -# step 4.e.ii) -15.2.3.7-6-a-264: FAIL -# Bug? Object.defineProperties - 'O' is an Array, 'P' is an array index named -# property, test the length property of 'O' is set as ToUint32('P') + 1 if -# ToUint32('P') is greater than value of the length property in 'O' -# (15.4.5.1 step 4.e.ii) -15.2.3.7-6-a-265: FAIL -# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is own accessor -# property of 'O' which is also defined in [[ParameterMap]] of 'O', and -# 'desc' is accessor descriptor, test updating multiple attribute values of -# 'P' (10.6 [[DefineOwnProperty]] step 3) -15.2.3.7-6-a-280: FAIL -# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is own data -# property of 'O' which is also defined in [[ParameterMap]] of 'O', and -# 'desc' is data descriptor, test updating multiple attribute values of 'P' -# (10.6 [[DefineOwnProperty]] step 3) -15.2.3.7-6-a-281: FAIL -# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is own data -# property of 'O' which is also defined in [[ParameterMap]] of 'O', test -# TypeError is thrown when updating the [[Value]] attribute value of 'P' -# whose writable and configurable attributes are false (10.6 -# [[DefineOwnProperty]] step 4) -15.2.3.7-6-a-282: FAIL -# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is own data -# property of 'O' which is also defined in [[ParameterMap]] of 'O', test -# TypeError is thrown when updating the [[Writable]] attribute value of 'P' -# which is defined as non-configurable (10.6 [[DefineOwnProperty]] step 4) -15.2.3.7-6-a-283: FAIL -# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is own data -# property of 'O' which is also defined in [[ParameterMap]] of 'O', test -# TypeError is thrown when updating the [[Enumerable]] attribute value of -# 'P' which is defined as non-configurable (10.6 [[DefineOwnProperty]] step -# 4) -15.2.3.7-6-a-284: FAIL -# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is own data -# property of 'O' which is also defined in [[ParameterMap]] of 'O', test -# TypeError is thrown when updating the [[Configurable]] attribute value of -# 'P' which is defined as non-configurable (10.6 [[DefineOwnProperty]] step -# 4) -15.2.3.7-6-a-285: FAIL -# Bug? Object.defineProperties - 'O' is an Arguments object, 'P' is an array -# index named accessor property of 'O' but not defined in [[ParameterMap]] -# of 'O', and 'desc' is accessor descriptor, test updating multiple -# attribute values of 'P' (10.6 [[DefineOwnProperty]] step 3) -15.2.3.7-6-a-292: FAIL -# Bug? Strict Mode - 'this' value is a string which cannot be converted to -# wrapper objects when the function is called with an array of arguments -15.3.4.3-1-s: FAIL -# Bug? Strict Mode - 'this' value is a number which cannot be converted to -# wrapper objects when the function is called with an array of arguments -15.3.4.3-2-s: FAIL -# Bug? Strict Mode - 'this' value is a boolean which cannot be converted to -# wrapper objects when the function is called with an array of arguments -15.3.4.3-3-s: FAIL -# Bug? Function.prototype.bind - [[Get]] attribute of 'caller' property in 'F' -# is thrower -15.3.4.5-20-2: FAIL -# Bug? Function.prototype.bind - [[Set]] attribute of 'caller' property in 'F' -# is thrower -15.3.4.5-20-3: FAIL -# Bug? Function.prototype.bind - [[Get]] attribute of 'arguments' property in -# 'F' is thrower -15.3.4.5-21-2: FAIL -# Bug? Function.prototype.bind - [[Set]] attribute of 'arguments' property in -# 'F' is thrower -15.3.4.5-21-3: FAIL -# Bug? Array.prototype.indexOf - decreasing length of array does not delete -# non-configurable properties -15.4.4.14-9-a-19: FAIL -# Bug? Array.prototype.indexOf - element to be retrieved is own accessor -# property that overrides an inherited data property on an Array -15.4.4.14-9-b-i-11: FAIL -# Bug? Array.prototype.indexOf - element to be retrieved is own accessor -# property that overrides an inherited accessor property on an Array -15.4.4.14-9-b-i-13: FAIL -# Bug? Array.prototype.indexOf - element to be retrieved is own accessor -# property without a get function on an Array -15.4.4.14-9-b-i-17: FAIL -# Bug? Array.prototype.indexOf - element to be retrieved is own accessor -# property without a get function that overrides an inherited accessor -# property on an Array -15.4.4.14-9-b-i-19: FAIL -# Bug? Array.prototype.indexOf - side-effects are visible in subsequent -# iterations on an Array -15.4.4.14-9-b-i-28: FAIL -# Bug? Array.prototype.indexOf - terminates iteration on unhandled exception on -# an Array -15.4.4.14-9-b-i-30: FAIL -# Bug? Array.prototype.lastIndexOf - deleting property of prototype causes -# prototype index property not to be visited on an Array -15.4.4.15-8-a-14: FAIL -# Bug? Array.prototype.lastIndexOf - decreasing length of array does not delete -# non-configurable properties -15.4.4.15-8-a-19: FAIL -# Bug? Array.prototype.lastIndexOf - element to be retrieved is own accessor -# property that overrides an inherited data property on an Array -15.4.4.15-8-b-i-11: FAIL -# Bug? Array.prototype.lastIndexOf - element to be retrieved is own accessor -# property that overrides an inherited accessor property on an Array -15.4.4.15-8-b-i-13: FAIL -# Bug? Array.prototype.lastIndexOf - element to be retrieved is own accessor -# property without a get function on an Array -15.4.4.15-8-b-i-17: FAIL -# Bug? Array.prototype.lastIndexOf - side-effects are visible in subsequent -# iterations on an Array -15.4.4.15-8-b-i-28: FAIL -# Bug? Array.prototype.lastIndexOf terminates iteration on unhandled exception -# on an Array -15.4.4.15-8-b-i-30: FAIL -# Bug? Array.prototype.every applied to boolean primitive -15.4.4.16-1-3: FAIL -# Bug? Array.prototype.every applied to number primitive -15.4.4.16-1-5: FAIL -# Bug? Array.prototype.every applied to string primitive -15.4.4.16-1-7: FAIL -# Bug? Array.prototype.every - side effects produced by step 2 are visible when -# an exception occurs -15.4.4.16-4-8: FAIL -# Bug? Array.prototype.every - side effects produced by step 3 are visible when -# an exception occurs -15.4.4.16-4-9: FAIL -# Bug? Array.prototype.every - the exception is not thrown if exception was -# thrown by step 2 -15.4.4.16-4-10: FAIL -# Bug? Array.prototype.every - the exception is not thrown if exception was -# thrown by step 3 -15.4.4.16-4-11: FAIL -# Bug? Array.prototype.every - calling with no callbackfn is the same as passing -# undefined for callbackfn -15.4.4.16-4-15: FAIL -# Bug? Array.prototype.every - decreasing length of array does not delete -# non-configurable properties -15.4.4.16-7-b-16: FAIL -# Bug? Array.prototype.every - element to be retrieved is own accessor property -# on an Array -15.4.4.16-7-c-i-10: FAIL -# Bug? Array.prototype.every - element to be retrieved is own accessor property -# that overrides an inherited data property on an Array -15.4.4.16-7-c-i-12: FAIL -# Bug? Array.prototype.every - element to be retrieved is own accessor property -# that overrides an inherited accessor property on an Array -15.4.4.16-7-c-i-14: FAIL -# Bug? Array.prototype.every - element to be retrieved is own accessor property -# without a get function on an Array -15.4.4.16-7-c-i-18: FAIL -# Bug? Array.prototype.every - element to be retrieved is own accessor property -# without a get function that overrides an inherited accessor property on -# an Array -15.4.4.16-7-c-i-20: FAIL -# Bug? Array.prototype.every - element changed by getter on previous iterations -# is observed on an Array -15.4.4.16-7-c-i-28: FAIL -# Bug? Array.prototype.some applied to boolean primitive -15.4.4.17-1-3: FAIL -# Bug? Array.prototype.some applied to number primitive -15.4.4.17-1-5: FAIL -# Bug? Array.prototype.some applied to applied to string primitive -15.4.4.17-1-7: FAIL -# Bug? Array.prototype.some - side effects produced by step 2 are visible when -# an exception occurs -15.4.4.17-4-8: FAIL -# Bug? Array.prototype.some - side effects produced by step 3 are visible when -# an exception occurs -15.4.4.17-4-9: FAIL -# Bug? Array.prototype.some - the exception is not thrown if exception was -# thrown by step 2 -15.4.4.17-4-10: FAIL -# Bug? Array.prototype.some - the exception is not thrown if exception was -# thrown by step 3 -15.4.4.17-4-11: FAIL -# Bug? Array.prototype.some - calling with no callbackfn is the same as passing -# undefined for callbackfn -15.4.4.17-4-15: FAIL -# Bug? Array.prototype.some - decreasing length of array does not delete -# non-configurable properties -15.4.4.17-7-b-16: FAIL -# Bug? Array.prototype.some - element to be retrieved is own accessor property -# on an Array -15.4.4.17-7-c-i-10: FAIL -# Bug? Array.prototype.some - element to be retrieved is own accessor property -# that overrides an inherited data property on an Array -15.4.4.17-7-c-i-12: FAIL -# Bug? Array.prototype.some - element to be retrieved is own accessor property -# that overrides an inherited accessor property on an Array -15.4.4.17-7-c-i-14: FAIL -# Bug? Array.prototype.some - element to be retrieved is own accessor property -# without a get function on an Array -15.4.4.17-7-c-i-18: FAIL -# Bug? Array.prototype.some - element to be retrieved is own accessor property -# without a get function that overrides an inherited accessor property on -# an Array -15.4.4.17-7-c-i-20: FAIL -# Bug? Array.prototype.some - element changed by getter on previous iterations -# is observed on an Array -15.4.4.17-7-c-i-28: FAIL -# Bug? Array.prototype.forEach applied to boolean primitive -15.4.4.18-1-3: FAIL -# Bug? Array.prototype.forEach applied to number primitive -15.4.4.18-1-5: FAIL -# Bug? Array.prototype.forEach applied to string primitive -15.4.4.18-1-7: FAIL -# Bug? Array.prototype.forEach - side effects produced by step 2 are visible -# when an exception occurs -15.4.4.18-4-8: FAIL -# Bug? Array.prototype.forEach - side effects produced by step 3 are visible -# when an exception occurs -15.4.4.18-4-9: FAIL -# Bug? Array.prototype.forEach - the exception is not thrown if exception was -# thrown by step 2 -15.4.4.18-4-10: FAIL -# Bug? Array.prototype.forEach - the exception is not thrown if exception was -# thrown by step 3 -15.4.4.18-4-11: FAIL -# Bug? Array.prototype.forEach - calling with no callbackfn is the same as -# passing undefined for callbackfn -15.4.4.18-4-15: FAIL -# Bug? Array.prototype.forEach - decreasing length of array does not delete -# non-configurable properties -15.4.4.18-7-b-16: FAIL -# Bug? Array.prototype.forEach - element to be retrieved is own accessor -# property on an Array -15.4.4.18-7-c-i-10: FAIL -# Bug? Array.prototype.forEach - element to be retrieved is own accessor -# property that overrides an inherited data property on an Array -15.4.4.18-7-c-i-12: FAIL -# Bug? Array.prototype.forEach - element to be retrieved is own accessor -# property that overrides an inherited accessor property on an Array -15.4.4.18-7-c-i-14: FAIL -# Bug? Array.prototype.forEach - element to be retrieved is own accessor -# property without a get function on an Array -15.4.4.18-7-c-i-18: FAIL -# Bug? Array.prototype.forEach - element to be retrieved is own accessor -# property without a get function that overrides an inherited accessor -# property on an Array -15.4.4.18-7-c-i-20: FAIL -# Bug? Array.prototype.forEach - element changed by getter on previous -# iterations is observed on an Array -15.4.4.18-7-c-i-28: FAIL -# Bug? Array.prototype.map - applied to boolean primitive -15.4.4.19-1-3: FAIL -# Bug? Array.prototype.map - applied to number primitive -15.4.4.19-1-5: FAIL -# Bug? Array.prototype.map - applied to string primitive -15.4.4.19-1-7: FAIL -# Bug? Array.prototype.map - Side effects produced by step 2 are visible when an -# exception occurs -15.4.4.19-4-8: FAIL -# Bug? Array.prototype.map - Side effects produced by step 3 are visible when an -# exception occurs -15.4.4.19-4-9: FAIL -# Bug? Array.prototype.map - the exception is not thrown if exception was thrown -# by step 2 -15.4.4.19-4-10: FAIL -# Bug? Array.prototype.map - the exception is not thrown if exception was thrown -# by step 3 -15.4.4.19-4-11: FAIL -# Bug? Array.prototype.map - calling with no callbackfn is the same as passing -# undefined for callbackfn -15.4.4.19-4-15: FAIL -# Bug? Array.prototype.map - decreasing length of array does not delete -# non-configurable properties -15.4.4.19-8-b-16: FAIL -# Bug? Array.prototype.map - element to be retrieved is own accessor property on -# an Array -15.4.4.19-8-c-i-10: FAIL -# Bug? Array.prototype.map - element to be retrieved is own accessor property -# that overrides an inherited data property on an Array -15.4.4.19-8-c-i-12: FAIL -# Bug? Array.prototype.map - element to be retrieved is own accessor property -# that overrides an inherited accessor property on an Array -15.4.4.19-8-c-i-14: FAIL -# Bug? Array.prototype.map - element to be retrieved is own accessor property -# without a get function on an Array -15.4.4.19-8-c-i-18: FAIL -# Bug? Array.prototype.map - element to be retrieved is own accessor property -# without a get function that overrides an inherited accessor property on -# an Array -15.4.4.19-8-c-i-19: FAIL -# Bug? Array.prototype.map - element changed by getter on previous iterations is -# observed on an Array -15.4.4.19-8-c-i-28: FAIL -# Bug? Array.prototype.filter applied to boolean primitive -15.4.4.20-1-3: FAIL -# Bug? Array.prototype.filter applied to number primitive -15.4.4.20-1-5: FAIL -# Bug? Array.prototype.filter applied to string primitive -15.4.4.20-1-7: FAIL -# Bug? Array.prototype.filter - side effects produced by step 2 are visible when -# an exception occurs -15.4.4.20-4-8: FAIL -# Bug? Array.prototype.filter - side effects produced by step 3 are visible when -# an exception occurs -15.4.4.20-4-9: FAIL -# Bug? Array.prototype.filter - the exception is not thrown if exception was -# thrown by step 2 -15.4.4.20-4-10: FAIL -# Bug? Array.prototype.filter - the exception is not thrown if exception was -# thrown by step 3 -15.4.4.20-4-11: FAIL -# Bug? Array.prototype.filter - calling with no callbackfn is the same as -# passing undefined for callbackfn -15.4.4.20-4-15: FAIL -# Bug? Array.prototype.filter - properties can be added to prototype after -# current position are visited on an Array-like object -15.4.4.20-9-b-6: FAIL -# Bug? Array.prototype.filter - decreasing length of array does not delete -# non-configurable properties -15.4.4.20-9-b-16: FAIL -# Bug? Array.prototype.filter - element to be retrieved is own data property -# that overrides an inherited accessor property on an Array -15.4.4.20-9-c-i-6: FAIL -# Bug? Array.prototype.filter - element to be retrieved is own accessor property -# on an Array -15.4.4.20-9-c-i-10: FAIL -# Bug? Array.prototype.filter - element to be retrieved is own accessor property -# that overrides an inherited data property on an Array -15.4.4.20-9-c-i-12: FAIL -# Bug? Array.prototype.filter - element to be retrieved is own accessor property -# that overrides an inherited accessor property on an Array -15.4.4.20-9-c-i-14: FAIL -# Bug? Array.prototype.filter - element to be retrieved is inherited accessor -# property on an Array -15.4.4.20-9-c-i-16: FAIL -# Bug? Array.prototype.filter - element to be retrieved is own accessor property -# without a get function on an Array -15.4.4.20-9-c-i-18: FAIL -# Bug? Array.prototype.filter - element to be retrieved is own accessor property -# without a get function that overrides an inherited accessor property on -# an Array -15.4.4.20-9-c-i-20: FAIL -# Bug? Array.prototype.filter - element to be retrieved is inherited accessor -# property without a get function on an Array -15.4.4.20-9-c-i-22: FAIL -# Bug? Array.prototype.filter - element changed by getter on previous iterations -# is observed on an Array -15.4.4.20-9-c-i-28: FAIL -# Bug? Array.prototype.reduce applied to boolean primitive -15.4.4.21-1-3: FAIL -# Bug? Array.prototype.reduce applied to number primitive -15.4.4.21-1-5: FAIL -# Bug? Array.prototype.reduce applied to string primitive -15.4.4.21-1-7: FAIL -# Bug? Array.prototype.reduce - side effects produced by step 2 are visible when -# an exception occurs -15.4.4.21-4-8: FAIL -# Bug? Array.prototype.reduce - side effects produced by step 3 are visible when -# an exception occurs -15.4.4.21-4-9: FAIL -# Bug? Array.prototype.reduce - the exception is not thrown if exception was -# thrown by step 2 -15.4.4.21-4-10: FAIL -# Bug? Array.prototype.reduce - the exception is not thrown if exception was -# thrown by step 3 -15.4.4.21-4-11: FAIL -# Bug? Array.prototype.reduce - calling with no callbackfn is the same as -# passing undefined for callbackfn -15.4.4.21-4-15: FAIL -# Bug? Array.prototype.reduce - decreasing length of array in step 8 does not -# delete non-configurable properties -15.4.4.21-9-b-16: FAIL -# Bug? Array.prototype.reduce - decreasing length of array does not delete -# non-configurable properties -15.4.4.21-9-b-29: FAIL -# Bug? Array.prototype.reduceRight applied to boolean primitive -15.4.4.22-1-3: FAIL -# Bug? Array.prototype.reduceRight applied to number primitive -15.4.4.22-1-5: FAIL -# Bug? Array.prototype.reduceRight applied to string primitive -15.4.4.22-1-7: FAIL -# Bug? Array.prototype.reduceRight - side effects produced by step 2 are visible -# when an exception occurs -15.4.4.22-4-8: FAIL -# Bug? Array.prototype.reduceRight - side effects produced by step 3 are visible -# when an exception occurs -15.4.4.22-4-9: FAIL -# Bug? Array.prototype.reduceRight - the exception is not thrown if exception -# was thrown by step 2 -15.4.4.22-4-10: FAIL -# Bug? Array.prototype.reduceRight - the exception is not thrown if exception -# was thrown by step 3 -15.4.4.22-4-11: FAIL -# Bug? Array.prototype.reduceRight - calling with no callbackfn is the same as -# passing undefined for callbackfn -15.4.4.22-4-15: FAIL -# Bug? Array.prototype.reduceRight - element to be retrieved is own accessor -# property that overrides an inherited data property on an Array -15.4.4.22-8-b-iii-1-12: FAIL -# Bug? Array.prototype.reduceRight - element to be retrieved is own accessor -# property without a get function on an Array -15.4.4.22-8-b-iii-1-18: FAIL -# Bug? Array.prototype.reduceRight - element to be retrieved is own accessor -# property without a get function that overrides an inherited accessor -# property on an Array -15.4.4.22-8-b-iii-1-20: FAIL -# Bug? Array.prototype.reduceRight - element changed by getter on current -# iteration is observed in subsequent iterations on an Array -15.4.4.22-8-b-iii-1-30: FAIL -# Bug? Array.prototype.reduceRight - Exception in getter terminate iteration on -# an Array -15.4.4.22-8-b-iii-1-33: FAIL -# Bug? Array.prototype.reduceRight - modifications to length don't change number -# of iterations in step 9 -15.4.4.22-8-b-2: FAIL -# Bug? Array.prototype.reduceRight - deleting own property in step 8 causes -# deleted index property not to be visited on an Array -15.4.4.22-9-b-9: FAIL -# Bug? Array.prototype.reduceRight - deleting own property with prototype -# property in step 8 causes prototype index property to be visited on an -# Array -15.4.4.22-9-b-13: FAIL -# Bug? Array.prototype.reduceRight - decreasing length of array in step 8 does -# not delete non-configurable properties -15.4.4.22-9-b-16: FAIL -# Bug? Array.prototype.reduceRight - deleting property of prototype causes -# deleted index property not to be visited on an Array -15.4.4.22-9-b-24: FAIL -# Bug? Array.prototype.reduceRight - deleting own property with prototype -# property causes prototype index property to be visited on an Array -15.4.4.22-9-b-26: FAIL -# Bug? Array.prototype.reduceRight - decreasing length of array does not delete -# non-configurable properties -15.4.4.22-9-b-29: FAIL -# Bug? Array.prototype.reduceRight - element changed by getter on previous -# iterations is observed on an Array -15.4.4.22-9-c-i-30: FAIL -# Bug? Array.prototype.reduceRight - modifications to length will change number -# of iterations -15.4.4.22-9-9: FAIL -# Bug? String.prototype.trim - 'S' is a string with all WhiteSpace -15.5.4.20-3-2: FAIL -# Bug? String.prototype.trim - 'S' is a string with all union of WhiteSpace and -# LineTerminator -15.5.4.20-3-3: FAIL -# Bug? String.prototype.trim - 'S' is a string start with union of all -# LineTerminator and all WhiteSpace -15.5.4.20-3-4: FAIL -# Bug? String.prototype.trim - 'S' is a string end with union of all -# LineTerminator and all WhiteSpace -15.5.4.20-3-5: FAIL -# Bug? String.prototype.trim - 'S' is a string start with union of all -# LineTerminator and all WhiteSpace and end with union of all -# LineTerminator and all WhiteSpace -15.5.4.20-3-6: FAIL -# Bug? String.prototype.trim handles whitepace and lineterminators (\\uFEFFabc) -15.5.4.20-4-10: FAIL -# Bug? String.prototype.trim handles whitepace and lineterminators (abc\\uFEFF) -15.5.4.20-4-18: FAIL -# Bug? String.prototype.trim handles whitepace and lineterminators -# (\\uFEFF\\uFEFF) -15.5.4.20-4-34: FAIL -# Bug? Date.prototype.toISOString - RangeError is thrown when value of date is -# Date(1970, 0, -99999999, 0, 0, 0, -1), the time zone is UTC(0) -15.9.5.43-0-8: FAIL -# Bug? Date.prototype.toISOString - RangeError is not thrown when value of date -# is Date(1970, 0, 100000001, 0, 0, 0, -1), the time zone is UTC(0) -15.9.5.43-0-11: FAIL -# Bug? Date.prototype.toISOString - RangeError is not thrown when value of date -# is Date(1970, 0, 100000001, 0, 0, 0, 0), the time zone is UTC(0) -15.9.5.43-0-12: FAIL -# Bug? Date.prototype.toISOString - RangeError is thrown when value of date is -# Date(1970, 0, 100000001, 0, 0, 0, 1), the time zone is UTC(0) -15.9.5.43-0-13: FAIL -# Bug? Date.prototype.toISOString - when value of year is -Infinity -# Date.prototype.toISOString throw the RangeError -15.9.5.43-0-14: FAIL -# Bug? Date.prototype.toISOString - value of year is Infinity -# Date.prototype.toISOString throw the RangeError -15.9.5.43-0-15: FAIL -# Bug? RegExp - the thrown error is SyntaxError instead of RegExpError when 'F' -# contains any character other than 'g', 'i', or 'm' -15.10.4.1-3: FAIL -# Bug? RegExp.prototype is itself a RegExp -15.10.6: FAIL -# Bug? RegExp.prototype.source is of type String -15.10.7.1-1: FAIL -# Bug? RegExp.prototype.source is a data property with default attribute values -# (false) -15.10.7.1-2: FAIL -# Bug? RegExp.prototype.global is of type Boolean -15.10.7.2-1: FAIL -# Bug? RegExp.prototype.global is a data property with default attribute values -# (false) -15.10.7.2-2: FAIL -# Bug? RegExp.prototype.ignoreCase is of type Boolean -15.10.7.3-1: FAIL -# Bug? RegExp.prototype.ignoreCase is a data property with default attribute -# values (false) -15.10.7.3-2: FAIL -# Bug? RegExp.prototype.multiline is of type Boolean -15.10.7.4-1: FAIL -# Bug? RegExp.prototype.multiline is a data property with default attribute -# values (false) -15.10.7.4-2: FAIL -# Bug? RegExp.prototype.lastIndex is of type Number -15.10.7.5-1: FAIL -# Bug? RegExp.prototype.lastIndex is a data property with specified attribute -# values -15.10.7.5-2: FAIL -# Bug? Error.prototype.toString return the value of 'msg' when 'name' is empty -# string and 'msg' isn't undefined -15.11.4.4-8-1: FAIL + +##################### DELIBERATE INCOMPATIBILITIES ##################### + +# We deliberately treat arguments to parseInt() with a leading zero as +# octal numbers in order to not break the web. +S15.1.2.2_A5.1_T1: FAIL_OK + +# This tests precision of Math.tan and Math.sin. The implementation for those +# trigonometric functions are platform/compiler dependent. Furthermore, the +# expectation values by far deviates from the actual result given by an +# arbitrary-precision calculator, making those tests partly bogus. +S15.8.2.16_A7: PASS || FAIL_OK +S15.8.2.18_A7: PASS || FAIL_OK + +# We are more lenient in which string character escapes we allow than +# the spec (7.8.4 p. 19) wants us to be. This is for compatibility. +S7.8.4_A6.1_T4: FAIL_OK +S7.8.4_A6.2_T1: FAIL_OK +S7.8.4_A6.2_T2: FAIL_OK +S7.8.4_A7.1_T4: FAIL_OK +S7.8.4_A7.2_T1: FAIL_OK +S7.8.4_A7.2_T2: FAIL_OK +S7.8.4_A7.2_T3: FAIL_OK +S7.8.4_A7.2_T4: FAIL_OK +S7.8.4_A7.2_T5: FAIL_OK +S7.8.4_A7.2_T6: FAIL_OK + +# Linux and Mac defaults to extended 80 bit floating point format in the FPU. +# We follow the other major JS engines by keeping this default. +S8.5_A2.2: PASS if ($system != linux || $arch == x64), FAIL_OK if ($system == linux && $arch != x64) +S8.5_A2.1: PASS if ($system != linux || $arch == x64), FAIL_OK if ($system == linux && $arch != x64) + +############################ INVALID TESTS ############################# + +# The reference value calculated by Test262 is incorrect if you run these tests +# in PST/PDT between first Sunday in March and first Sunday in April. The DST +# switch was moved in 2007 whereas Test262 bases the reference value on 2000. +# Test262 Bug: https://bugs.ecmascript.org/show_bug.cgi?id=293 +S15.9.3.1_A5_T1: PASS || FAIL_OK +S15.9.3.1_A5_T2: PASS || FAIL_OK +S15.9.3.1_A5_T3: PASS || FAIL_OK +S15.9.3.1_A5_T4: PASS || FAIL_OK +S15.9.3.1_A5_T5: PASS || FAIL_OK +S15.9.3.1_A5_T6: PASS || FAIL_OK + +############################ SKIPPED TESTS ############################# + +# These tests take a looong time to run in debug mode. +S15.1.3.2_A2.5_T1: PASS, SKIP if $mode == debug +S15.1.3.1_A2.5_T1: PASS, SKIP if $mode == debug + +[ $arch == arm ] + +# BUG(3251225): Tests that timeout with --nocrankshaft. +S15.1.3.1_A2.5_T1: SKIP +S15.1.3.2_A2.5_T1: SKIP +S15.1.3.1_A2.4_T1: SKIP +S15.1.3.1_A2.5_T1: SKIP +S15.1.3.2_A2.4_T1: SKIP +S15.1.3.2_A2.5_T1: SKIP +S15.1.3.3_A2.3_T1: SKIP +S15.1.3.4_A2.3_T1: SKIP +S15.1.3.1_A2.5_T1: SKIP +S15.1.3.2_A2.5_T1: SKIP + +[ $arch == mips ] + +# BUG(3251225): Tests that timeout with --nocrankshaft. +S15.1.3.1_A2.5_T1: SKIP +S15.1.3.2_A2.5_T1: SKIP +S15.1.3.1_A2.4_T1: SKIP +S15.1.3.1_A2.5_T1: SKIP +S15.1.3.2_A2.4_T1: SKIP +S15.1.3.2_A2.5_T1: SKIP +S15.1.3.3_A2.3_T1: SKIP +S15.1.3.4_A2.3_T1: SKIP +S15.1.3.1_A2.5_T1: SKIP +S15.1.3.2_A2.5_T1: SKIP diff --git a/test/test262/testcfg.py b/test/test262/testcfg.py index 94820460..294b39c9 100644 --- a/test/test262/testcfg.py +++ b/test/test262/testcfg.py @@ -29,8 +29,14 @@ import test import os from os.path import join, exists +import urllib +import hashlib +import tarfile +TEST_262_ARCHIVE_REVISION = '3a890174343c' # This is the r309 revision. +TEST_262_ARCHIVE_MD5 = 'be5d4cfbe69cef70430907b8f3a92b50' +TEST_262_URL = 'http://hg.ecmascript.org/tests/test262/archive/%s.tar.bz2' TEST_262_HARNESS = ['sta.js'] @@ -43,10 +49,10 @@ class Test262TestCase(test.TestCase): self.root = root def IsNegative(self): - return self.filename.endswith('-n.js') + return '@negative' in self.GetSource() def GetLabel(self): - return "%s test262 %s %s" % (self.mode, self.GetGroup(), self.GetName()) + return "%s test262 %s" % (self.mode, self.GetName()) def IsFailureOutput(self, output): if output.exit_code != 0: @@ -55,7 +61,6 @@ class Test262TestCase(test.TestCase): def GetCommand(self): result = self.context.GetVmCommand(self, self.mode) - result += ['-e', 'var window = this'] result += self.framework result.append(self.filename) return result @@ -63,9 +68,6 @@ class Test262TestCase(test.TestCase): def GetName(self): return self.path[-1] - def GetGroup(self): - return self.path[0] - def GetSource(self): return open(self.filename).read() @@ -75,13 +77,14 @@ class Test262TestConfiguration(test.TestConfiguration): def __init__(self, context, root): super(Test262TestConfiguration, self).__init__(context, root) - def AddIETestCenter(self, tests, current_path, path, mode): - current_root = join(self.root, 'data', 'test', 'suite', 'ietestcenter') + def ListTests(self, current_path, path, mode, variant_flags): + testroot = join(self.root, 'data', 'test', 'suite') harness = [join(self.root, 'data', 'test', 'harness', f) for f in TEST_262_HARNESS] harness += [join(self.root, 'harness-adapt.js')] - for root, dirs, files in os.walk(current_root): - for dotted in [x for x in dirs if x.startswith('.')]: + tests = [] + for root, dirs, files in os.walk(testroot): + for dotted in [x for x in dirs if x.startswith('.')]: dirs.remove(dotted) dirs.sort() root_path = root[len(self.root):].split(os.path.sep) @@ -89,27 +92,35 @@ class Test262TestConfiguration(test.TestConfiguration): files.sort() for file in files: if file.endswith('.js'): - if self.Contains(path, root_path): - test_path = ['ietestcenter', file[:-3]] + test_path = ['test262', file[:-3]] + if self.Contains(path, test_path): test = Test262TestCase(join(root, file), test_path, self.context, self.root, mode, harness) tests.append(test) - - def AddSputnikConvertedTests(self, tests, current_path, path, mode): - # To be enabled - pass - - def AddSputnikTests(self, tests, current_path, path, mode): - # To be enabled - pass - - def ListTests(self, current_path, path, mode, variant_flags): - tests = [] - self.AddIETestCenter(tests, current_path, path, mode) - self.AddSputnikConvertedTests(tests, current_path, path, mode) - self.AddSputnikTests(tests, current_path, path, mode) return tests + def DownloadData(self): + revision = TEST_262_ARCHIVE_REVISION + archive_url = TEST_262_URL % revision + archive_name = join(self.root, 'test262-%s.tar.bz2' % revision) + directory_name = join(self.root, "test262-%s" % revision) + if not exists(directory_name) or not exists(archive_name): + if not exists(archive_name): + print "Downloading test data from %s ..." % archive_url + urllib.urlretrieve(archive_url, archive_name) + if not exists(directory_name): + print "Extracting test262-%s.tar.bz2 ..." % revision + md5 = hashlib.md5() + with open(archive_name,'rb') as f: + for chunk in iter(lambda: f.read(8192), ''): + md5.update(chunk) + if md5.hexdigest() != TEST_262_ARCHIVE_MD5: + raise Exception("Hash mismatch of test data file") + archive = tarfile.open(archive_name, 'r:bz2') + archive.extractall(join(self.root)) + if not exists(join(self.root, 'data')): + os.symlink(directory_name, join(self.root, 'data')) + def GetBuildRequirements(self): return ['d8'] |